From 422f84e92de6c72c3cab23eebb6631287b6d742c Mon Sep 17 00:00:00 2001 From: QuentinArguillere Date: Tue, 28 Nov 2023 23:44:28 +0100 Subject: [PATCH] Fixes for 5.2 release FIx Fix PipController Other fixes (Reported on AppStoreConnect) --- Classes/LinphoneUI/UIChatBubblePhotoCell.m | 4 +-- Classes/LinphoneUI/UIChatBubbleTextCell.m | 14 ++++---- Classes/LinphoneUI/UIChatReplyBubbleView.m | 2 +- Classes/Swift/CallManager.swift | 14 ++++---- .../ChatConversationTableViewSwift.swift | 2 +- Classes/Swift/Chat/Views/MessageView.swift | 16 +++++++-- .../Chat/Views/MultilineMessageCell.swift | 22 ++++++------ .../Views/ScheduledConferencesCell.swift | 2 +- .../Voip/ViewModels/ConferenceViewModel.swift | 2 +- .../SingleCallView.swift | 24 +++++++------ Classes/Swift/Voip/Widgets/Avatar.swift | 2 +- GoogleService-Info.plist | 34 +++++++++++++------ Podfile | 6 ++-- 13 files changed, 87 insertions(+), 57 deletions(-) diff --git a/Classes/LinphoneUI/UIChatBubblePhotoCell.m b/Classes/LinphoneUI/UIChatBubblePhotoCell.m index d9073ab74..ec2560723 100644 --- a/Classes/LinphoneUI/UIChatBubblePhotoCell.m +++ b/Classes/LinphoneUI/UIChatBubblePhotoCell.m @@ -211,7 +211,7 @@ size_t contentCount = bctbx_list_size(contents); if (voiceContent) contentCount--; - BOOL multiParts = ((linphone_chat_message_get_text_content(self.message) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1); + BOOL multiParts = ((linphone_chat_message_get_utf8_text(self.message) != NULL) ? bctbx_list_size(contents) > 2 : bctbx_list_size(contents) > 1); if (voiceContent && !multiParts) { _cancelButton.hidden = _fileTransferProgress.hidden = _downloadButton.hidden = _playButton.hidden = _fileName.hidden = _fileView.hidden = _fileButton.hidden = YES; return; @@ -732,7 +732,7 @@ } // Positioning text message - const char *utf8Text = linphone_chat_message_get_text_content(self.message); + const char *utf8Text = linphone_chat_message_get_utf8_text(self.message); CGRect textFrame = self.messageText.frame; if (_contentViews.count > 0 || _finalImage.image) diff --git a/Classes/LinphoneUI/UIChatBubbleTextCell.m b/Classes/LinphoneUI/UIChatBubbleTextCell.m index b149e1a17..ee561c9dd 100644 --- a/Classes/LinphoneUI/UIChatBubbleTextCell.m +++ b/Classes/LinphoneUI/UIChatBubbleTextCell.m @@ -140,12 +140,12 @@ const char *url = linphone_chat_message_get_external_body_url(message); const LinphoneContent *last_content = linphone_chat_message_get_file_transfer_information(message); // Last message was a file transfer (image) so display a picture... - if (url || last_content) { - if (linphone_chat_message_get_text_content(message)) - return [NSString stringWithUTF8String:linphone_chat_message_get_text_content(message)]; + if ((url || last_content) && message) { + if (linphone_chat_message_get_utf8_text(message)) + return [NSString stringWithUTF8String:linphone_chat_message_get_utf8_text(message)]; return @"🗻"; } else { - const char *text = linphone_chat_message_get_text_content(message) ?: ""; + const char *text = linphone_chat_message_get_utf8_text(message) ?: ""; return [NSString stringWithUTF8String:text] ?: [NSString stringWithCString:text encoding:NSASCIIStringEncoding] ?: NSLocalizedString(@"(invalid string)", nil); } @@ -530,7 +530,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18; if (voiceContent) contentCount--; - BOOL multiParts = ((linphone_chat_message_get_text_content(chat) != NULL) ? contentCount > 2 : contentCount > 1); + BOOL multiParts = ((linphone_chat_message_get_utf8_text(chat) != NULL) ? contentCount > 2 : contentCount > 1); if (voiceContent && contentCount == 0) { size = CGSizeMake(VOICE_RECORDING_PLAYER_WIDTH, VOICE_RECORDING_PLAYER_HEIGHT); @@ -618,7 +618,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18; // if here, either 1 file + text or just one file or just text. - BOOL justText = linphone_chat_message_get_text_content(chat) != NULL && contentCount == 1; + BOOL justText = linphone_chat_message_get_utf8_text(chat) != NULL && contentCount == 1; if (justText) { // Just text size = [self computeBoundingBox:messageText size:CGSizeMake(width - CELL_MESSAGE_X_MARGIN - 4, CGFLOAT_MAX) @@ -886,7 +886,7 @@ static const CGFloat REPLY_OR_FORWARD_TAG_HEIGHT = 18; [_messageActionsIcons addObject:@"menu_copy_text_default"]; [_messageActionsBlocks addObject:^{ [thiz dismissPopup]; - [UIPasteboard.generalPasteboard setString:[NSString stringWithUTF8String:linphone_chat_message_get_text_content(message)]]; + [UIPasteboard.generalPasteboard setString:[NSString stringWithUTF8String:linphone_chat_message_get_utf8_text(message)]]; }]; } diff --git a/Classes/LinphoneUI/UIChatReplyBubbleView.m b/Classes/LinphoneUI/UIChatReplyBubbleView.m index c9890977e..cf9c05709 100644 --- a/Classes/LinphoneUI/UIChatReplyBubbleView.m +++ b/Classes/LinphoneUI/UIChatReplyBubbleView.m @@ -67,7 +67,7 @@ NSString *sender = [FastAddressBook displayNameForAddress:linphone_chat_message_get_from_address(message)]; _senderName.text = sender; - const char * text = isIcal ? [ICSBubbleView getSubjectFromContentWithCmessage:message].UTF8String : linphone_chat_message_get_text_content(message); + const char * text = isIcal ? [ICSBubbleView getSubjectFromContentWithCmessage:message].UTF8String : linphone_chat_message_get_utf8_text(message); if (text && strlen(text) == 0) text = nil; _textContent.text = text ? [NSString stringWithUTF8String:text] : @""; diff --git a/Classes/Swift/CallManager.swift b/Classes/Swift/CallManager.swift index ba35a1721..565553c8e 100644 --- a/Classes/Swift/CallManager.swift +++ b/Classes/Swift/CallManager.swift @@ -564,13 +564,15 @@ import AVFoundation if call.replacedCall != nil { endCallKitReplacedCall = false - let uuid = CallManager.instance().providerDelegate.uuids["\(CallManager.uuidReplacedCall)"] + let uuid = CallManager.instance().providerDelegate.uuids["\(CallManager.uuidReplacedCall ?? "")"] let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!] callInfo!.callId = CallManager.instance().referedToCall ?? "" - CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!) - CallManager.instance().providerDelegate.uuids.removeValue(forKey: callId) - CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callInfo!.callId) - CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName) + if (callInfo != nil && uuid != nil && addr != nil) { + CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!) + CallManager.instance().providerDelegate.uuids.removeValue(forKey: callId) + CallManager.instance().providerDelegate.uuids.updateValue(uuid!, forKey: callInfo!.callId) + CallManager.instance().providerDelegate.updateCall(uuid: uuid!, handle: addr!.asStringUriOnly(), hasVideo: video, displayName: displayName) + } } else if (CallManager.callKitEnabled()) { let isConference = isConferenceCall(call: call) let isEarlyConference = isConference && CallsViewModel.shared.currentCallData.value??.isConferenceCall.value != true // Conference info not be received yet. @@ -638,7 +640,7 @@ import AVFoundation .OutgoingEarlyMedia: if (CallManager.callKitEnabled()) { let uuid = CallManager.instance().providerDelegate.uuids[""] - if (uuid != nil) { + if (uuid != nil && callId != nil) { let callInfo = CallManager.instance().providerDelegate.callInfos[uuid!] callInfo!.callId = callId CallManager.instance().providerDelegate.callInfos.updateValue(callInfo!, forKey: uuid!) diff --git a/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift b/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift index 982e193d0..0b7678334 100644 --- a/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift +++ b/Classes/Swift/Chat/Views/ChatConversationTableViewSwift.swift @@ -642,7 +642,7 @@ class ChatConversationTableViewSwift: UIViewController, UICollectionViewDataSour ChatConversationViewModel.sharedModel.removeTmpFile(filePath: plainFile) plainFile = "" - }else { + }else if chatMessage.contents.first?.filePath != nil { self.previewItems.append(self.getPreviewItem(filePath: (chatMessage.contents.first?.filePath)!)) } diff --git a/Classes/Swift/Chat/Views/MessageView.swift b/Classes/Swift/Chat/Views/MessageView.swift index 22c75a7d6..d40c79240 100644 --- a/Classes/Swift/Chat/Views/MessageView.swift +++ b/Classes/Swift/Chat/Views/MessageView.swift @@ -88,6 +88,10 @@ class MessageView: UIView, UITextViewDelegate { messageWithEmojiView.addArrangedSubview(emojisButton) emojisButton.alignParentRight().matchParentHeight().done() + if #available(iOS 17.0, *) { + emojisButton.isHidden = true + } + UIDeviceBridge.displayModeSwitched.readCurrentAndObserve { _ in self.backgroundColor = VoipTheme.voipToolbarBackgroundColor.get() self.messageWithEmojiView.backgroundColor = VoipTheme.backgroundWhiteBlack.get() @@ -99,7 +103,11 @@ class MessageView: UIView, UITextViewDelegate { let chatRoom = ChatRoom.getSwiftObject(cObject: PhoneMainView.instance().currentRoom) if ((messageText.text.isEmpty && !fileContext) || isLoading) { sendButton.isEnabled = false - emojisButton.isHidden = false + if #available(iOS 17.0, *) { + emojisButton.isHidden = true + } else { + emojisButton.isHidden = false + } NotificationCenter.default.post(name: Notification.Name("LinphoneResetTextViewSize"), object: self) lastNumLines = 0 } else { @@ -111,7 +119,11 @@ class MessageView: UIView, UITextViewDelegate { } } if onlyEmojis { - emojisButton.isHidden = false + if #available(iOS 17.0, *) { + emojisButton.isHidden = true + } else { + emojisButton.isHidden = false + } } else { emojisButton.isHidden = true } diff --git a/Classes/Swift/Chat/Views/MultilineMessageCell.swift b/Classes/Swift/Chat/Views/MultilineMessageCell.swift index 5b5d668c4..11b424459 100644 --- a/Classes/Swift/Chat/Views/MultilineMessageCell.swift +++ b/Classes/Swift/Chat/Views/MultilineMessageCell.swift @@ -1784,8 +1784,10 @@ class MultilineMessageCell: SwipeCollectionViewCell, UICollectionViewDataSource, var result = "" do{ let linphonePlayer = try core.createLocalPlayer(soundCardName: nil, videoDisplayName: nil, windowId: nil) - try linphonePlayer.open(filename: _voiceRecordingFile!) - result = formattedDuration(linphonePlayer.duration)! + if _voiceRecordingFile != nil { + try linphonePlayer.open(filename: _voiceRecordingFile!) + } + result = formattedDuration(linphonePlayer.duration) ?? "" linphonePlayer.close() }catch{ Log.e(error.localizedDescription) @@ -2026,13 +2028,13 @@ class MultilineMessageCell: SwipeCollectionViewCell, UICollectionViewDataSource, subject = event.subject! return VoipTexts.bubble_chat_event_message_new_subject + subject case Int(LinphoneEventLogTypeConferenceParticipantAdded.rawValue): - participant = (event.participantAddress!.displayName != "" && event.participantAddress!.displayName != nil ? event.participantAddress!.displayName : event.participantAddress!.username)! + participant = (event.participantAddress!.displayName != nil && event.participantAddress!.displayName != "" ? event.participantAddress!.displayName : event.participantAddress!.username)! return participant + VoipTexts.bubble_chat_event_message_has_joined case Int(LinphoneEventLogTypeConferenceParticipantRemoved.rawValue): - participant = (event.participantAddress!.displayName != "" && event.participantAddress!.displayName != nil ? event.participantAddress!.displayName : event.participantAddress!.username)! + participant = (event.participantAddress!.displayName != nil && event.participantAddress!.displayName != "" ? event.participantAddress!.displayName : event.participantAddress!.username)! return participant + VoipTexts.bubble_chat_event_message_has_left case Int(LinphoneEventLogTypeConferenceParticipantSetAdmin.rawValue): - participant = (event.participantAddress!.displayName != "" && event.participantAddress!.displayName != nil ? event.participantAddress!.displayName : event.participantAddress!.username)! + participant = (event.participantAddress!.displayName != nil && event.participantAddress!.displayName != nil && event.participantAddress!.displayName != "" ? event.participantAddress!.displayName : event.participantAddress!.username)! return participant + VoipTexts.bubble_chat_event_message_now_admin case Int(LinphoneEventLogTypeConferenceParticipantUnsetAdmin.rawValue): participant = (event.participantAddress!.displayName != "" && event.participantAddress!.displayName != nil ? event.participantAddress!.displayName : event.participantAddress!.username)! @@ -2043,28 +2045,28 @@ class MultilineMessageCell: SwipeCollectionViewCell, UICollectionViewDataSource, return VoipTexts.bubble_chat_event_message_joined_group case Int(LinphoneEventLogTypeConferenceSecurityEvent.rawValue): let type = event.securityEventType - let participant = event.securityEventFaultyDeviceAddress!.displayName != "" ? event.securityEventFaultyDeviceAddress!.displayName : event.securityEventFaultyDeviceAddress!.username + let participant = event.securityEventFaultyDeviceAddress!.displayName != nil && event.securityEventFaultyDeviceAddress!.displayName != "" ? event.securityEventFaultyDeviceAddress!.displayName : event.securityEventFaultyDeviceAddress!.username switch (type.rawValue) { case Int(LinphoneSecurityEventTypeSecurityLevelDowngraded.rawValue): - if (participant!.isEmpty){ + if (participant != nil && participant!.isEmpty){ return VoipTexts.bubble_chat_event_message_security_level_decreased }else{ return VoipTexts.bubble_chat_event_message_security_level_decreased_because + participant! } case Int(LinphoneSecurityEventTypeParticipantMaxDeviceCountExceeded.rawValue): - if (participant!.isEmpty){ + if (participant != nil && participant!.isEmpty){ return VoipTexts.bubble_chat_event_message_max_participant }else{ return VoipTexts.bubble_chat_event_message_max_participant_by + participant! } case Int(LinphoneSecurityEventTypeEncryptionIdentityKeyChanged.rawValue): - if (participant!.isEmpty){ + if (participant != nil && participant!.isEmpty){ return VoipTexts.bubble_chat_event_message_lime_changed }else{ return VoipTexts.bubble_chat_event_message_lime_changed_for + participant! } case Int(LinphoneSecurityEventTypeManInTheMiddleDetected.rawValue): - if (participant!.isEmpty){ + if (participant != nil && participant!.isEmpty){ return VoipTexts.bubble_chat_event_message_attack_detected }else{ return VoipTexts.bubble_chat_event_message_attack_detected_for + participant! diff --git a/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift b/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift index 635288da9..7cc4d6af2 100644 --- a/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift +++ b/Classes/Swift/Conference/Views/ScheduledConferencesCell.swift @@ -67,7 +67,7 @@ class ScheduledConferencesCell: UITableViewCell { subject.text = (isBroadcast ? VoipTexts.conference_scheduled_title_broadcast_cell : VoipTexts.conference_scheduled_title_meeting_cell) + data.subject.value! cancelledLabel.text = data.isConferenceCancelled.value == true ? ( data.canEdit.value == true ? VoipTexts.conference_scheduled_cancelled_by_me: VoipTexts.conference_scheduled_cancelled_by_organizer) : nil cancelledLabel.isHidden = data.isConferenceCancelled.value != true - descriptionValue.text = data.description.value! + descriptionValue.text = data.description.value != nil ? data.description.value! : "" urlValue.text = data.address.value! self.joinConf.isHidden = data.isConferenceCancelled.value == true self.editConf.isHidden = data.canEdit.value != true || data.isConferenceCancelled.value == true diff --git a/Classes/Swift/Voip/ViewModels/ConferenceViewModel.swift b/Classes/Swift/Voip/ViewModels/ConferenceViewModel.swift index 78a7eef2b..1c25b8c4b 100644 --- a/Classes/Swift/Voip/ViewModels/ConferenceViewModel.swift +++ b/Classes/Swift/Voip/ViewModels/ConferenceViewModel.swift @@ -463,7 +463,7 @@ class ConferenceViewModel { } static func getConferenceSubject(conference:Conference) -> String? { - if (conference.subject!.count > 0) { + if (conference.subject != nil && conference.subject!.count > 0) { return conference.subject } else { let conferenceInfo = Core.get().findConferenceInformationFromUri(uri: conference.conferenceAddress!) diff --git a/Classes/Swift/Voip/Views/CompositeViewControllers/SingleCallView.swift b/Classes/Swift/Voip/Views/CompositeViewControllers/SingleCallView.swift index 9e9c80627..3eac53109 100644 --- a/Classes/Swift/Voip/Views/CompositeViewControllers/SingleCallView.swift +++ b/Classes/Swift/Voip/Views/CompositeViewControllers/SingleCallView.swift @@ -148,18 +148,20 @@ extension SingleCallView : AVPictureInPictureControllerDelegate { activeVideoCallSourceView: currentCallView!.remoteVideo, contentViewController: pipVideoCallController) pipController = AVPictureInPictureController(contentSource: pipContentSource) - pipController.delegate = self - - ControlsViewModel.shared.isVideoEnabled.readCurrentAndObserve{ (video) in - pipVideoCallController.matchVideoDimension() - self.pipController.canStartPictureInPictureAutomaticallyFromInline = video == true - } - - CallsViewModel.shared.currentCallData.observe(onChange: { callData in - if (callData??.call.state != .StreamsRunning && self.pipController.isPictureInPictureActive) { - self.pipController.stopPictureInPicture() + if (pipController != nil) { + pipController.delegate = self + + ControlsViewModel.shared.isVideoEnabled.readCurrentAndObserve{ (video) in + pipVideoCallController.matchVideoDimension() + self.pipController.canStartPictureInPictureAutomaticallyFromInline = video == true } - }) + + CallsViewModel.shared.currentCallData.observe(onChange: { callData in + if (callData??.call.state != .StreamsRunning && self.pipController.isPictureInPictureActive) { + self.pipController.stopPictureInPicture() + } + }) + } } diff --git a/Classes/Swift/Voip/Widgets/Avatar.swift b/Classes/Swift/Voip/Widgets/Avatar.swift index eba8d9f05..65ab908eb 100644 --- a/Classes/Swift/Voip/Widgets/Avatar.swift +++ b/Classes/Swift/Voip/Widgets/Avatar.swift @@ -66,7 +66,7 @@ class Avatar : UIView { initialsLabel.isHidden = true iconImageView.isHidden = false } else { - if (Core.get().defaultAccount?.isPhoneNumber(username: address.username!) == true) { + if (Core.get().defaultAccount != nil && address.username != nil && Core.get().defaultAccount!.isPhoneNumber(username: address.username!) == true) { iconImageView.image = Avatar.singleAvatar initialsLabel.isHidden = true iconImageView.isHidden = false diff --git a/GoogleService-Info.plist b/GoogleService-Info.plist index e3fe76c08..f996be8f2 100644 --- a/GoogleService-Info.plist +++ b/GoogleService-Info.plist @@ -2,23 +2,35 @@ - AD_UNIT_ID_FOR_BANNER_TEST - - AD_UNIT_ID_FOR_INTERSTITIAL_TEST - CLIENT_ID - + 221368768663-0ufgu96cel0auk4v0me863lgm252b9n2.apps.googleusercontent.com REVERSED_CLIENT_ID - + com.googleusercontent.apps.221368768663-0ufgu96cel0auk4v0me863lgm252b9n2 API_KEY - + AIzaSyDJTtlRCM7IqdVUU2dSIYq2YIsTz6bqnkI GCM_SENDER_ID - + 221368768663 + PLIST_VERSION + 1 BUNDLE_ID - + org.linphone.phone PROJECT_ID - + linphone-iphone STORAGE_BUCKET - + linphone-iphone.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:221368768663:ios:a2c822bc087b5a219431d2 + DATABASE_URL + https://linphone-iphone.firebaseio.com diff --git a/Podfile b/Podfile index ccf4e474f..d3b72222c 100644 --- a/Podfile +++ b/Podfile @@ -1,11 +1,11 @@ # Uncomment the next line to define a global platform for your project -platform :ios, '12.0' +platform :ios, '13.0' source "https://gitlab.linphone.org/BC/public/podspec.git" source "https://github.com/CocoaPods/Specs.git" def all_pods if ENV['PODFILE_PATH'].nil? - pod 'linphone-sdk', '~>5.3.0-alpha' + pod 'linphone-sdk', '~>5.3.0-beta' else pod 'linphone-sdk', :path => ENV['PODFILE_PATH'] # local sdk end @@ -121,7 +121,7 @@ post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0' + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' end end end