diff --git a/SiriIntents/IntentContacts.swift b/SiriIntents/IntentContacts.swift index cfe9f540bf..fcfd7edbba 100644 --- a/SiriIntents/IntentContacts.swift +++ b/SiriIntents/IntentContacts.swift @@ -10,18 +10,33 @@ struct MatchingDeviceContact { let firstName: String let lastName: String let phoneNumbers: [String] + let peerId: PeerId? } enum IntentContactsError { case generic } +private let phonebookUsernamePathPrefix = "@id" +private let phonebookUsernamePrefix = "https://t.me/" + phonebookUsernamePathPrefix + +private func parseAppSpecificContactReference(_ value: String) -> PeerId? { + if !value.hasPrefix(phonebookUsernamePrefix) { + return nil + } + let idString = String(value[value.index(value.startIndex, offsetBy: phonebookUsernamePrefix.count)...]) + if let id = Int32(idString) { + return PeerId(namespace: Namespaces.Peer.CloudUser, id: id) + } + return nil +} + func matchingDeviceContacts(stableIds: [String]) -> Signal<[MatchingDeviceContact], IntentContactsError> { guard CNContactStore.authorizationStatus(for: .contacts) == .authorized else { return .fail(.generic) } let store = CNContactStore() - guard let contacts = try? store.unifiedContacts(matching: CNContact.predicateForContacts(withIdentifiers: stableIds), keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey as CNKeyDescriptor]) else { + guard let contacts = try? store.unifiedContacts(matching: CNContact.predicateForContacts(withIdentifiers: stableIds), keysToFetch: [CNContactFormatter.descriptorForRequiredKeys(for: .fullName), CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactUrlAddressesKey as CNKeyDescriptor]) else { return .fail(.generic) } @@ -34,7 +49,14 @@ func matchingDeviceContacts(stableIds: [String]) -> Signal<[MatchingDeviceContac } }) - return MatchingDeviceContact(stableId: contact.identifier, firstName: contact.givenName, lastName: contact.familyName, phoneNumbers: phoneNumbers) + var contactPeerId: PeerId? + for address in contact.urlAddresses { + if address.label == "Telegram", let peerId = parseAppSpecificContactReference(address.value as String) { + contactPeerId = peerId + } + } + + return MatchingDeviceContact(stableId: contact.identifier, firstName: contact.givenName, lastName: contact.familyName, phoneNumbers: phoneNumbers, peerId: contactPeerId) })) } @@ -52,44 +74,24 @@ func matchingCloudContacts(postbox: Postbox, contacts: [MatchingDeviceContact]) return postbox.transaction { transaction -> [(String, TelegramUser)] in var result: [(String, TelegramUser)] = [] outer: for peerId in transaction.getContactPeerIds() { - if let peer = transaction.getPeer(peerId) as? TelegramUser, let peerPhoneNumber = peer.phone { - for contact in contacts { - for phoneNumber in contact.phoneNumbers { - if matchPhoneNumbers(phoneNumber, peerPhoneNumber) { + if let peer = transaction.getPeer(peerId) as? TelegramUser { + if let peerPhoneNumber = peer.phone { + for contact in contacts { + for phoneNumber in contact.phoneNumbers { + if matchPhoneNumbers(phoneNumber, peerPhoneNumber) { + result.append((contact.stableId, peer)) + continue outer + } + } + } + } else { + for contact in contacts { + if let contactPeerId = contact.peerId, contactPeerId == peerId { result.append((contact.stableId, peer)) continue outer } } } -// var parsedPhoneNumbers: [String: ParsedPhoneNumber] = [:] -// let parsedPeerPhoneNumber: ParsedPhoneNumber? -// if let number = parsedPhoneNumbers[peerPhoneNumber] { -// parsedPeerPhoneNumber = number -// } else if let number = ParsedPhoneNumber(string: peerPhoneNumber) { -// parsedPeerPhoneNumber = number -// parsedPhoneNumbers[peerPhoneNumber] = number -// } else { -// parsedPeerPhoneNumber = nil -// } -// -// for contact in contacts { -// for phoneNumber in contact.phoneNumbers { -// let parsedPhoneNumber: ParsedPhoneNumber? -// if let number = parsedPhoneNumbers[phoneNumber] { -// parsedPhoneNumber = number -// } else if let number = ParsedPhoneNumber(string: phoneNumber) { -// parsedPhoneNumber = number -// parsedPhoneNumbers[phoneNumber] = number -// } else { -// parsedPhoneNumber = nil -// } -// -// if parsedPeerPhoneNumber == parsedPhoneNumber { -// result.append((contact.stableId, peer)) -// continue outer -// } -// } -// } } } return result @@ -110,5 +112,14 @@ func personWithUser(stableId: String, user: TelegramUser) -> INPerson { var nameComponents = PersonNameComponents() nameComponents.givenName = user.firstName nameComponents.familyName = user.lastName - return INPerson(personHandle: INPersonHandle(value: stableId, type: .unknown), nameComponents: nameComponents, displayName: user.debugDisplayTitle, image: nil, contactIdentifier: stableId, customIdentifier: "tg\(user.id.toInt64())") + let personHandle: INPersonHandle + if let phone = user.phone { + personHandle = INPersonHandle(value: formatPhoneNumber(phone), type: .phoneNumber) + } else if let username = user.username { + personHandle = INPersonHandle(value: "@\(username)", type: .unknown) + } else { + personHandle = INPersonHandle(value: user.displayTitle, type: .unknown) + } + + return INPerson(personHandle: personHandle, nameComponents: nameComponents, displayName: user.debugDisplayTitle, image: nil, contactIdentifier: stableId, customIdentifier: "tg\(user.id.toInt64())") } diff --git a/SiriIntents/IntentHandler.swift b/SiriIntents/IntentHandler.swift index 27479e02d0..50daf8ba39 100644 --- a/SiriIntents/IntentHandler.swift +++ b/SiriIntents/IntentHandler.swift @@ -202,11 +202,6 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag return } - if filteredPersons.count > 1 { - completion([.disambiguation(filteredPersons)]) - return - } - var allPersonsAlreadyMatched = true for person in filteredPersons { if !(person.customIdentifier ?? "").hasPrefix("tg") { @@ -215,7 +210,7 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag } } - if allPersonsAlreadyMatched { + if allPersonsAlreadyMatched && filteredPersons.count == 1 { completion([.success(filteredPersons[0])]) return } @@ -239,29 +234,31 @@ class IntentHandler: INExtension, INSendMessageIntentHandling, INSearchForMessag let account = self.accountPromise.get() let signal = matchingDeviceContacts(stableIds: stableIds) - |> take(1) - |> mapToSignal { matchedContacts in - return account - |> introduceError(IntentContactsError.self) - |> mapToSignal { account -> Signal<[(String, TelegramUser)], IntentContactsError> in - if let account = account { - return matchingCloudContacts(postbox: account.postbox, contacts: matchedContacts) - |> introduceError(IntentContactsError.self) - } else { - return .fail(.generic) - } - } + |> take(1) + |> mapToSignal { matchedContacts in + return account + |> introduceError(IntentContactsError.self) + |> mapToSignal { account -> Signal<[(String, TelegramUser)], IntentContactsError> in + if let account = account { + return matchingCloudContacts(postbox: account.postbox, contacts: matchedContacts) + |> introduceError(IntentContactsError.self) + } else { + return .fail(.generic) + } + } } self.resolvePersonsDisposable.set((signal - |> deliverOnMainQueue).start(next: { peers in - if peers.isEmpty { - completion([.needsValue]) - } else { - completion(peers.map { .success(personWithUser(stableId: $0, user: $1)) }) - } - }, error: { error in - completion([.skip]) - })) + |> deliverOnMainQueue).start(next: { peers in + if peers.isEmpty { + completion([.noResult]) + } else if peers.count == 1 { + completion(peers.map { .success(personWithUser(stableId: $0, user: $1)) }) + } else { + completion([.disambiguation(peers.map { (personWithUser(stableId: $0, user: $1)) })]) + } + }, error: { error in + completion([.skip]) + })) } // MARK: - INSendMessageIntentHandling diff --git a/Telegram-iOS.xcworkspace/contents.xcworkspacedata b/Telegram-iOS.xcworkspace/contents.xcworkspacedata index 5e3d9ae7bd..e681a480b3 100644 --- a/Telegram-iOS.xcworkspace/contents.xcworkspacedata +++ b/Telegram-iOS.xcworkspace/contents.xcworkspacedata @@ -1,9 +1,28 @@ + + + + + + + + + + + + @@ -38,19 +57,22 @@ location = "group:submodules/SaveToCameraRoll/SaveToCameraRoll_Xcode.xcodeproj"> + location = "group:submodules/TelegramNotices/TelegramNotices_Xcode.xcodeproj"> + location = "group:submodules/TelegramPermissions/TelegramPermissions_Xcode.xcodeproj"> + location = "group:submodules/WebsiteType/WebsiteType_Xcode.xcodeproj"> + location = "group:submodules/ScreenCaptureDetection/ScreenCaptureDetection_Xcode.xcodeproj"> + + + location = "group:submodules/TinyThumbnail/TinyThumbnail_Xcode.xcodeproj"> + location = "group:submodules/ImageTransparency/ImageTransparency_Xcode.xcodeproj"> + location = "group:submodules/ImageCompression/ImageCompression_Xcode.xcodeproj"> @@ -101,6 +123,9 @@ + + @@ -108,7 +133,7 @@ location = "group:submodules/MediaResources/MediaResources_Xcode.xcodeproj"> + location = "group:submodules/PhotoResources/PhotoResources_Xcode.xcodeproj"> @@ -135,7 +160,7 @@ location = "container:" name = "Video Content"> + location = "group:submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent_Xcode.xcodeproj"> + location = "group:submodules/PhoneInputNode/PhoneInputNode_Xcode.xcodeproj"> + location = "group:submodules/SearchBarNode/SearchBarNode_Xcode.xcodeproj"> + location = "group:submodules/TouchDownGesture/TouchDownGesture_Xcode.xcodeproj"> + location = "group:submodules/SwipeToDismissGesture/SwipeToDismissGesture_Xcode.xcodeproj"> + location = "group:submodules/DirectionalPanGesture/DirectionalPanGesture_Xcode.xcodeproj"> + location = "group:submodules/DateSelectionUI/DateSelectionUI_Xcode.xcodeproj"> @@ -226,13 +251,16 @@ + location = "group:submodules/LegacyComponents/LegacyComponents_Xcode.xcodeproj"> + location = "group:submodules/LegacyUI/LegacyUI_Xcode.xcodeproj"> + location = "group:submodules/OpenInExternalAppUI/OpenInExternalAppUI_Xcode.xcodeproj"> + + @@ -274,57 +302,33 @@ location = "group:submodules/ContextUI/ContextUI_Xcode.xcodeproj"> + location = "group:submodules/ComposePollUI/ComposePollUI_Xcode.xcodeproj"> + location = "group:submodules/UndoUI/UndoUI_Xcode.xcodeproj"> + location = "group:submodules/GameUI/GameUI_Xcode.xcodeproj"> + location = "group:submodules/WebUI/WebUI_Xcode.xcodeproj"> + location = "group:submodules/PassportUI/PassportUI_Xcode.xcodeproj"> + location = "group:submodules/CountrySelectionUI/CountrySelectionUI_Xcode.xcodeproj"> + location = "group:submodules/GalleryUI/GalleryUI_Xcode.xcodeproj"> + location = "group:submodules/PasswordSetupUI/PasswordSetupUI_Xcode.xcodeproj"> - - - - - - - - - - - - - - - - diff --git a/submodules/Display/Display/TextNode.swift b/submodules/Display/Display/TextNode.swift index 4f46c270b1..7a0bc0a530 100644 --- a/submodules/Display/Display/TextNode.swift +++ b/submodules/Display/Display/TextNode.swift @@ -401,11 +401,11 @@ public final class TextNodeLayout: NSObject { let lineRange = NSIntersectionRange(range, line.range) if lineRange.length != 0 { var leftOffset: CGFloat = 0.0 - if lineRange.location != line.range.location { + if lineRange.location != line.range.location || line.isRTL { leftOffset = floor(CTLineGetOffsetForStringIndex(line.line, lineRange.location, nil)) } var rightOffset: CGFloat = line.frame.width - if lineRange.location + lineRange.length != line.range.length { + if lineRange.location + lineRange.length != line.range.length || line.isRTL { var secondaryOffset: CGFloat = 0.0 let rawOffset = CTLineGetOffsetForStringIndex(line.line, lineRange.location + lineRange.length, &secondaryOffset) rightOffset = ceil(rawOffset) @@ -417,7 +417,10 @@ public final class TextNodeLayout: NSObject { lineFrame = displayLineFrame(frame: lineFrame, isRTL: line.isRTL, boundingRect: CGRect(origin: CGPoint(), size: self.size), cutout: self.cutout) - rects.append((lineFrame, CGRect(origin: CGPoint(x: lineFrame.minX + leftOffset + self.insets.left, y: lineFrame.minY + self.insets.top), size: CGSize(width: rightOffset - leftOffset, height: lineFrame.size.height)))) + let width = abs(rightOffset - leftOffset) + if width > 1.0 { + rects.append((lineFrame, CGRect(origin: CGPoint(x: lineFrame.minX + (leftOffset < rightOffset ? leftOffset : rightOffset) + self.insets.left, y: lineFrame.minY + self.insets.top), size: CGSize(width: width, height: lineFrame.size.height)))) + } } } if !rects.isEmpty { diff --git a/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift b/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift index 35bed5bcd5..b3762f6bb8 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListSingleLineInputItem.swift @@ -177,7 +177,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg } let leftInset: CGFloat = 16.0 + params.leftInset - var rightInset: CGFloat = params.rightInset + var rightInset: CGFloat = 16.0 + params.rightInset if item.clearButton { rightInset += 32.0 @@ -225,27 +225,31 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg secureEntry = false capitalizationType = capitalization ? .sentences : .none autocorrectionType = autocorrection ? .default : .no - keyboardType = UIKeyboardType.default + keyboardType = .default case .email: secureEntry = false capitalizationType = .none autocorrectionType = .no - keyboardType = UIKeyboardType.emailAddress + keyboardType = .emailAddress case .password: secureEntry = true capitalizationType = .none autocorrectionType = .no - keyboardType = UIKeyboardType.default + keyboardType = .default case .number: secureEntry = false capitalizationType = .none autocorrectionType = .no - keyboardType = UIKeyboardType.numberPad + if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { + keyboardType = .asciiCapableNumberPad + } else { + keyboardType = .numberPad + } case .username: secureEntry = false capitalizationType = .none autocorrectionType = .no - keyboardType = UIKeyboardType.asciiCapable + keyboardType = .asciiCapable } if strongSelf.textNode.textField.isSecureTextEntry != secureEntry { diff --git a/submodules/MediaResources/MediaResources_Xcode.xcodeproj/project.pbxproj b/submodules/MediaResources/MediaResources_Xcode.xcodeproj/project.pbxproj index a7e656e838..1366b4530d 100644 --- a/submodules/MediaResources/MediaResources_Xcode.xcodeproj/project.pbxproj +++ b/submodules/MediaResources/MediaResources_Xcode.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ D084FA1622F436DE004874CE /* SwiftSignalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D084FA1522F436DE004874CE /* SwiftSignalKit.framework */; }; D0C9C0D322FE3E7500FAB518 /* MapResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C9C0D222FE3E7500FAB518 /* MapResources.swift */; }; D0C9C0D522FE3E8200FAB518 /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0C9C0D422FE3E8200FAB518 /* MapKit.framework */; }; + D0C9C5342301CC5100FAB518 /* TelegramCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0C9C5332301CC5100FAB518 /* TelegramCore.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -28,6 +29,7 @@ D084FA1522F436DE004874CE /* SwiftSignalKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwiftSignalKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0C9C0D222FE3E7500FAB518 /* MapResources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapResources.swift; sourceTree = ""; }; D0C9C0D422FE3E8200FAB518 /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; }; + D0C9C5332301CC5100FAB518 /* TelegramCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = TelegramCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -35,6 +37,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D0C9C5342301CC5100FAB518 /* TelegramCore.framework in Frameworks */, D0C9C0D522FE3E8200FAB518 /* MapKit.framework in Frameworks */, D084FA1622F436DE004874CE /* SwiftSignalKit.framework in Frameworks */, D084FA1422F436DA004874CE /* Postbox.framework in Frameworks */, @@ -77,6 +80,7 @@ D084FA0E22F436D2004874CE /* Frameworks */ = { isa = PBXGroup; children = ( + D0C9C5332301CC5100FAB518 /* TelegramCore.framework */, D0C9C0D422FE3E8200FAB518 /* MapKit.framework */, D084FA1522F436DE004874CE /* SwiftSignalKit.framework */, D084FA1322F436DA004874CE /* Postbox.framework */, diff --git a/submodules/MtProtoKit/MTProtoKit/MTApiEnvironment.m b/submodules/MtProtoKit/MTProtoKit/MTApiEnvironment.m index c12d36c60a..fe5777904a 100644 --- a/submodules/MtProtoKit/MTProtoKit/MTApiEnvironment.m +++ b/submodules/MtProtoKit/MTProtoKit/MTApiEnvironment.m @@ -225,6 +225,8 @@ static NSData *base64_decode(NSString *str) { if (hexData == nil) { NSString *finalString = @""; finalString = [finalString stringByAppendingString:[string stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"="]]]; + finalString = [finalString stringByReplacingOccurrencesOfString:@"-" withString:@"+"]; + finalString = [finalString stringByReplacingOccurrencesOfString:@"_" withString:@"/"]; while (finalString.length % 4 != 0) { finalString = [finalString stringByAppendingString:@"="]; } diff --git a/submodules/PassportUI/Sources/Form/FormControllerTextInputItem.swift b/submodules/PassportUI/Sources/Form/FormControllerTextInputItem.swift index 62157b05c9..a94b686695 100644 --- a/submodules/PassportUI/Sources/Form/FormControllerTextInputItem.swift +++ b/submodules/PassportUI/Sources/Form/FormControllerTextInputItem.swift @@ -123,7 +123,11 @@ final class FormControllerTextInputItemNode: FormBlockItemNode=4.2) if #available(iOSApplicationExtension 12.0, iOS 12.0, *) { self.codeField.textField.textContentType = .oneTimeCode diff --git a/submodules/TelegramUI/TelegramUI/Bridge Audio/TGBridgeAudioEncoder.m b/submodules/TelegramUI/TelegramUI/Bridge Audio/TGBridgeAudioEncoder.m index af5ba77bf5..0177caaffa 100644 --- a/submodules/TelegramUI/TelegramUI/Bridge Audio/TGBridgeAudioEncoder.m +++ b/submodules/TelegramUI/TelegramUI/Bridge Audio/TGBridgeAudioEncoder.m @@ -12,7 +12,7 @@ static const char *AMQueueSpecific = "AMQueueSpecific"; -const NSInteger TGBridgeAudioEncoderSampleRate = 16000; +const NSInteger TGBridgeAudioEncoderSampleRate = 48000; typedef enum { ATQueuePriorityLow, @@ -81,13 +81,13 @@ typedef enum { NSDictionary *outputSettings = @ { - AVFormatIDKey: @(kAudioFormatLinearPCM), - AVSampleRateKey: @(TGBridgeAudioEncoderSampleRate), - AVNumberOfChannelsKey: @1, - AVLinearPCMBitDepthKey: @16, - AVLinearPCMIsFloatKey: @false, - AVLinearPCMIsBigEndianKey: @false, - AVLinearPCMIsNonInterleaved: @false + AVFormatIDKey: @(kAudioFormatLinearPCM), + AVSampleRateKey: @(TGBridgeAudioEncoderSampleRate), + AVNumberOfChannelsKey: @1, + AVLinearPCMBitDepthKey: @16, + AVLinearPCMIsFloatKey: @false, + AVLinearPCMIsBigEndianKey: @false, + AVLinearPCMIsNonInterleaved: @false }; _readerOutput = [AVAssetReaderAudioMixOutput assetReaderAudioMixOutputWithAudioTracks:asset.tracks audioSettings:outputSettings]; @@ -114,9 +114,9 @@ typedef enum { static ATQueue *queue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ - { - queue = [[ATQueue alloc] initWithName:@"org.telegram.opusAudioEncoderQueue"]; - }); + { + queue = [[ATQueue alloc] initWithName:@"org.telegram.opusAudioEncoderQueue"]; + }); return queue; } @@ -126,74 +126,74 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 - (void)startWithCompletion:(void (^)(NSString *, int32_t))completion { [[TGBridgeAudioEncoder processingQueue] dispatch:^ - { - _oggWriter = [[TGOggOpusWriter alloc] init]; - if (![_oggWriter beginWithDataItem:_tempFileItem]) - { - [self cleanup]; - return; - } - - [_assetReader startReading]; - - while (_assetReader.status != AVAssetReaderStatusCompleted) - { - if (_assetReader.status == AVAssetReaderStatusReading) - { - CMSampleBufferRef nextBuffer = [_readerOutput copyNextSampleBuffer]; - if (nextBuffer) - { - AudioBufferList abl; - CMBlockBufferRef blockBuffer; - CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(nextBuffer, NULL, &abl, sizeof(abl), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer); - - [[TGBridgeAudioEncoder processingQueue] dispatch:^ - { - [self _processBuffer:&abl.mBuffers[0]]; - - CFRelease(nextBuffer); - CFRelease(blockBuffer); - }]; - } - else - { - [[TGBridgeAudioEncoder processingQueue] dispatch:^ - { - if (_tailLength > 0) { - [_oggWriter writeFrame:(uint8_t *)_audioBuffer.bytes frameByteCount:(NSUInteger)_tailLength]; - } - }]; - break; - } - } - } - - [[TGBridgeAudioEncoder processingQueue] dispatch:^ - { - TGFileDataItem *dataItemResult = nil; - NSTimeInterval durationResult = 0.0; - - NSUInteger totalBytes = 0; - - if (_assetReader.status == AVAssetReaderStatusCompleted) - { - NSLog(@"finished"); - if (_oggWriter != nil) - { - dataItemResult = _tempFileItem; - durationResult = [_oggWriter encodedDuration]; - totalBytes = [_oggWriter encodedBytes]; - } - - [self cleanup]; - } - - //TGLog(@"[TGBridgeAudioEncoder#%x convert time: %f ms]", self, (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0); - - if (completion != nil) - completion(dataItemResult.path, (int32_t)durationResult); - }]; - }]; + { + _oggWriter = [[TGOggOpusWriter alloc] init]; + if (![_oggWriter beginWithDataItem:_tempFileItem]) + { + [self cleanup]; + return; + } + + [_assetReader startReading]; + + while (_assetReader.status != AVAssetReaderStatusCompleted) + { + if (_assetReader.status == AVAssetReaderStatusReading) + { + CMSampleBufferRef nextBuffer = [_readerOutput copyNextSampleBuffer]; + if (nextBuffer) + { + AudioBufferList abl; + CMBlockBufferRef blockBuffer; + CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(nextBuffer, NULL, &abl, sizeof(abl), NULL, NULL, kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment, &blockBuffer); + + [[TGBridgeAudioEncoder processingQueue] dispatch:^ + { + [self _processBuffer:&abl.mBuffers[0]]; + + CFRelease(nextBuffer); + CFRelease(blockBuffer); + }]; + } + else + { + [[TGBridgeAudioEncoder processingQueue] dispatch:^ + { + if (_tailLength > 0) { + [_oggWriter writeFrame:(uint8_t *)_audioBuffer.bytes frameByteCount:(NSUInteger)_tailLength]; + } + }]; + break; + } + } + } + + [[TGBridgeAudioEncoder processingQueue] dispatch:^ + { + TGFileDataItem *dataItemResult = nil; + NSTimeInterval durationResult = 0.0; + + NSUInteger totalBytes = 0; + + if (_assetReader.status == AVAssetReaderStatusCompleted) + { + NSLog(@"finished"); + if (_oggWriter != nil && [_oggWriter writeFrame:NULL frameByteCount:0]) + { + dataItemResult = _tempFileItem; + durationResult = [_oggWriter encodedDuration]; + totalBytes = [_oggWriter encodedBytes]; + } + + [self cleanup]; + } + + //TGLog(@"[TGBridgeAudioEncoder#%x convert time: %f ms]", self, (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0); + + if (completion != nil) + completion(dataItemResult.path, (int32_t)durationResult); + }]; + }]; } - (void)_processBuffer:(AudioBuffer const *)buffer @@ -306,11 +306,11 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 [_queue dispatch:^ - { - _fileName = filePath; - _length = [[[NSFileManager defaultManager] attributesOfItemAtPath:_fileName error:nil][NSFileSize] unsignedIntegerValue]; - _fileExists = [[NSFileManager defaultManager] fileExistsAtPath:_fileName]; - }]; + { + _fileName = filePath; + _length = [[[NSFileManager defaultManager] attributesOfItemAtPath:_fileName error:nil][NSFileSize] unsignedIntegerValue]; + _fileExists = [[NSFileManager defaultManager] fileExistsAtPath:_fileName]; + }]; } return self; } @@ -322,38 +322,38 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 - (void)moveToPath:(NSString *)path { [_queue dispatch:^ - { - [[NSFileManager defaultManager] moveItemAtPath:_fileName toPath:path error:nil]; - _fileName = path; - }]; + { + [[NSFileManager defaultManager] moveItemAtPath:_fileName toPath:path error:nil]; + _fileName = path; + }]; } - (void)remove { [_queue dispatch:^ - { - [[NSFileManager defaultManager] removeItemAtPath:_fileName error:nil]; - }]; + { + [[NSFileManager defaultManager] removeItemAtPath:_fileName error:nil]; + }]; } - (void)appendData:(NSData *)data { [_queue dispatch:^ - { - if (!_fileExists) - { - [[NSFileManager defaultManager] createFileAtPath:_fileName contents:nil attributes:nil]; - _fileExists = true; - } - NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:_fileName]; - [file seekToEndOfFile]; - [file writeData:data]; - [file synchronizeFile]; - [file closeFile]; - _length += data.length; - - [_data appendData:data]; - }]; + { + if (!_fileExists) + { + [[NSFileManager defaultManager] createFileAtPath:_fileName contents:nil attributes:nil]; + _fileExists = true; + } + NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:_fileName]; + [file seekToEndOfFile]; + [file writeData:data]; + [file synchronizeFile]; + [file closeFile]; + _length += data.length; + + [_data appendData:data]; + }]; } - (NSData *)readDataAtOffset:(NSUInteger)offset length:(NSUInteger)length @@ -361,14 +361,14 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 __block NSData *data = nil; [_queue dispatch:^ - { - NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:_fileName]; - [file seekToFileOffset:(unsigned long long)offset]; - data = [file readDataOfLength:length]; - if (data.length != length) - //TGLog(@"Read data length mismatch"); - [file closeFile]; - } synchronous:true]; + { + NSFileHandle *file = [NSFileHandle fileHandleForUpdatingAtPath:_fileName]; + [file seekToFileOffset:(unsigned long long)offset]; + data = [file readDataOfLength:length]; + if (data.length != length) + //TGLog(@"Read data length mismatch"); + [file closeFile]; + } synchronous:true]; return data; } @@ -377,9 +377,9 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 { __block NSUInteger result = 0; [_queue dispatch:^ - { - result = _length; - } synchronous:true]; + { + result = _length; + } synchronous:true]; return result; } @@ -420,11 +420,11 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 static ATQueue *queue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ - { - queue = [[ATQueue alloc] init]; - queue->_nativeQueue = dispatch_get_main_queue(); - queue->_isMainQueue = true; - }); + { + queue = [[ATQueue alloc] init]; + queue->_nativeQueue = dispatch_get_main_queue(); + queue->_isMainQueue = true; + }); return queue; } @@ -434,9 +434,9 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 static ATQueue *queue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ - { - queue = [[ATQueue alloc] initWithNativeQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; - }); + { + queue = [[ATQueue alloc] initWithNativeQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)]; + }); return queue; } @@ -446,9 +446,9 @@ static const int encoderPacketSizeInBytes = TGBridgeAudioEncoderSampleRate / 100 static ATQueue *queue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^ - { - queue = [[ATQueue alloc] initWithNativeQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)]; - }); + { + queue = [[ATQueue alloc] initWithNativeQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)]; + }); return queue; } diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 1156d676ea..18b0a345bf 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -6652,7 +6652,7 @@ public final class ChatController: TelegramBaseController, GalleryHiddenMediaTar let targetRect = node.view.convert(rect, to: sourceView) let sourceRect = CGRect(origin: CGPoint(x: floor(targetRect.midX), y: floor(targetRect.midY)), size: CGSize(width: 1.0, height: 1.0)) - if let parsedUrl = URL(string: string) { + if let parsedUrl = parsedUrlValue { if parsedUrl.scheme == "http" || parsedUrl.scheme == "https" { if #available(iOSApplicationExtension 9.0, iOS 9.0, *) { let controller = SFSafariViewController(url: parsedUrl) diff --git a/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift index 58a88a7467..ea5e3f9788 100644 --- a/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift @@ -105,8 +105,6 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel self.pickerView.timeZone = TimeZone.current self.pickerView.minuteInterval = 5 - self.pickerView.maximumDate = Date(timeIntervalSince1970: Double(Int32.max - 1)) - self.pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor") self.contentContainerNode.view.addSubview(self.pickerView) @@ -137,6 +135,10 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel components.second = 0 let minute = (components.minute ?? 0) % 5 + if let date = calendar.date(byAdding: .day, value: 365, to: currentDate) { + self.pickerView.maximumDate = date + } + if let date = calendar.date(byAdding: .minute, value: 5 - minute, to: calendar.date(from: components)!) { self.pickerView.minimumDate = date self.pickerView.date = date diff --git a/submodules/TelegramUI/TelegramUI/ManagedAudioRecorder.swift b/submodules/TelegramUI/TelegramUI/ManagedAudioRecorder.swift index 69f0b29f54..01052fb460 100644 --- a/submodules/TelegramUI/TelegramUI/ManagedAudioRecorder.swift +++ b/submodules/TelegramUI/TelegramUI/ManagedAudioRecorder.swift @@ -314,7 +314,7 @@ final class ManagedAudioRecorderContext { self.idleTimerExtensionDisposable = (Signal { subscriber in return pushIdleTimerExtension() - } |> delay(5.0, queue: queue)).start() + } |> delay(5.0, queue: queue)).start() } deinit { @@ -401,19 +401,19 @@ final class ManagedAudioRecorderContext { strongSelf.audioSessionAcquired(headset: state.isHeadsetConnected) } } - }, deactivate: { [weak self] in - return Signal { subscriber in - queue.async { - if let strongSelf = self { - strongSelf.hasAudioSession = false - strongSelf.stop() - strongSelf.recordingState.set(.stopped) - subscriber.putCompletion() - } + }, deactivate: { [weak self] in + return Signal { subscriber in + queue.async { + if let strongSelf = self { + strongSelf.hasAudioSession = false + strongSelf.stop() + strongSelf.recordingState.set(.stopped) + subscriber.putCompletion() } - - return EmptyDisposable } + + return EmptyDisposable + } }) } } @@ -587,53 +587,57 @@ final class ManagedAudioRecorderContext { } func takeData() -> RecordedAudioData? { - var scaledSamplesMemory = malloc(100 * 2)! - var scaledSamples: UnsafeMutablePointer = scaledSamplesMemory.assumingMemoryBound(to: Int16.self) - defer { - free(scaledSamplesMemory) - } - memset(scaledSamples, 0, 100 * 2); - var waveform: Data? - - let count = self.compressedWaveformSamples.count / 2 - self.compressedWaveformSamples.withUnsafeMutableBytes { (samples: UnsafeMutablePointer) -> Void in - for i in 0 ..< count { - let sample = samples[i] - let index = i * 100 / count - if (scaledSamples[index] < sample) { - scaledSamples[index] = sample; + if self.oggWriter.writeFrame(nil, frameByteCount: 0) { + var scaledSamplesMemory = malloc(100 * 2)! + var scaledSamples: UnsafeMutablePointer = scaledSamplesMemory.assumingMemoryBound(to: Int16.self) + defer { + free(scaledSamplesMemory) + } + memset(scaledSamples, 0, 100 * 2); + var waveform: Data? + + let count = self.compressedWaveformSamples.count / 2 + self.compressedWaveformSamples.withUnsafeMutableBytes { (samples: UnsafeMutablePointer) -> Void in + for i in 0 ..< count { + let sample = samples[i] + let index = i * 100 / count + if (scaledSamples[index] < sample) { + scaledSamples[index] = sample; + } } - } - - var peak: Int16 = 0 - var sumSamples: Int64 = 0 - for i in 0 ..< 100 { - let sample = scaledSamples[i] - if peak < sample { - peak = sample + + var peak: Int16 = 0 + var sumSamples: Int64 = 0 + for i in 0 ..< 100 { + let sample = scaledSamples[i] + if peak < sample { + peak = sample + } + sumSamples += Int64(sample) } - sumSamples += Int64(sample) - } - var calculatedPeak: UInt16 = 0 - calculatedPeak = UInt16((Double(sumSamples) * 1.8 / 100.0)) - - if calculatedPeak < 2500 { - calculatedPeak = 2500 + var calculatedPeak: UInt16 = 0 + calculatedPeak = UInt16((Double(sumSamples) * 1.8 / 100.0)) + + if calculatedPeak < 2500 { + calculatedPeak = 2500 + } + + for i in 0 ..< 100 { + let sample: UInt16 = UInt16(Int64(scaledSamples[i])) + let minPeak = min(Int64(sample), Int64(calculatedPeak)) + let resultPeak = minPeak * 31 / Int64(calculatedPeak) + scaledSamples[i] = Int16(clamping: min(31, resultPeak)) + } + + let resultWaveform = AudioWaveform(samples: Data(bytes: scaledSamplesMemory, count: 100 * 2), peak: 31) + let bitstream = resultWaveform.makeBitstream() + waveform = AudioWaveform(bitstream: bitstream, bitsPerSample: 5).makeBitstream() } - for i in 0 ..< 100 { - let sample: UInt16 = UInt16(Int64(scaledSamples[i])) - let minPeak = min(Int64(sample), Int64(calculatedPeak)) - let resultPeak = minPeak * 31 / Int64(calculatedPeak) - scaledSamples[i] = Int16(clamping: min(31, resultPeak)) - } - - let resultWaveform = AudioWaveform(samples: Data(bytes: scaledSamplesMemory, count: 100 * 2), peak: 31) - let bitstream = resultWaveform.makeBitstream() - waveform = AudioWaveform(bitstream: bitstream, bitsPerSample: 5).makeBitstream() + return RecordedAudioData(compressedData: self.dataItem.data(), duration: self.oggWriter.encodedDuration(), waveform: waveform) + } else { + return nil } - - return RecordedAudioData(compressedData: self.dataItem.data(), duration: self.oggWriter.encodedDuration(), waveform: waveform) } } diff --git a/submodules/TelegramUI/TelegramUI/PasscodeEntryControllerNode.swift b/submodules/TelegramUI/TelegramUI/PasscodeEntryControllerNode.swift index 05b5f86dda..47f0c67fb8 100644 --- a/submodules/TelegramUI/TelegramUI/PasscodeEntryControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/PasscodeEntryControllerNode.swift @@ -361,12 +361,12 @@ final class PasscodeEntryControllerNode: ASDisplayNode { transition.updateFrame(node: self.keyboardNode, frame: CGRect(origin: CGPoint(), size: layout.size)) switch self.passcodeType { - case .digits6, .digits4: - self.keyboardNode.alpha = 1.0 - self.deleteButtonNode.alpha = 1.0 - case .alphanumeric: - self.keyboardNode.alpha = 0.0 - self.deleteButtonNode.alpha = 0.0 + case .digits6, .digits4: + self.keyboardNode.alpha = 1.0 + self.deleteButtonNode.alpha = 1.0 + case .alphanumeric: + self.keyboardNode.alpha = 0.0 + self.deleteButtonNode.alpha = 0.0 } let bottomInset = layout.inputHeight ?? 0.0 diff --git a/submodules/TelegramUI/TelegramUI/TextNode.swift b/submodules/TelegramUI/TelegramUI/TextNode.swift deleted file mode 100644 index 211fc1be84..0000000000 --- a/submodules/TelegramUI/TelegramUI/TextNode.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation -import UIKit -import AsyncDisplayKit -import Display -import Postbox - diff --git a/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift b/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift index 7ef0bbb743..b6c8f20dde 100644 --- a/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift +++ b/submodules/TelegramUI/TelegramUI/ThemeSettingsController.swift @@ -65,7 +65,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { case fontSize(PresentationTheme, PresentationFontSize) case chatPreview(PresentationTheme, PresentationTheme, TelegramWallpaper, PresentationFontSize, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder) case wallpaper(PresentationTheme, String) - case accentColor(PresentationTheme, String, PresentationThemeAccentColor?) + case accentColor(PresentationTheme, PresentationThemeReference, String, PresentationThemeAccentColor?) case autoNightTheme(PresentationTheme, String, String) case themeItem(PresentationTheme, PresentationStrings, [PresentationThemeReference], PresentationThemeReference, [Int64: PresentationThemeAccentColor], PresentationThemeAccentColor?) case iconHeader(PresentationTheme, String) @@ -137,8 +137,8 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { } else { return false } - case let .accentColor(lhsTheme, lhsText, lhsColor): - if case let .accentColor(rhsTheme, rhsText, rhsColor) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsColor == rhsColor { + case let .accentColor(lhsTheme, lhsCurrentTheme, lhsText, lhsColor): + if case let .accentColor(rhsTheme, rhsCurrentTheme, rhsText, rhsColor) = rhs, lhsTheme === rhsTheme, lhsCurrentTheme == rhsCurrentTheme, lhsText == rhsText, lhsColor == rhsColor { return true } else { return false @@ -230,21 +230,20 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry { return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: { arguments.openWallpaperSettings() }) - case let .accentColor(theme, _, color): + case let .accentColor(theme, currentTheme, _, color): + var defaultColor = PresentationThemeAccentColor(baseColor: .blue, value: 0.5) var colors = PresentationThemeBaseColor.allCases - if theme.overallDarkAppearance { - colors = colors.filter { $0 != .black } + if case let .builtin(name) = currentTheme { + if name == .night || name == .nightAccent { + colors = colors.filter { $0 != .black } + } + if name == .night { + colors = colors.filter { $0 != .gray } + defaultColor = PresentationThemeAccentColor(baseColor: .white, value: 0.5) + } else { + colors = colors.filter { $0 != .white } + } } - - let defaultColor: PresentationThemeAccentColor - if case let .builtin(name) = theme.name, name == .night { - colors = colors.filter { $0 != .gray } - defaultColor = PresentationThemeAccentColor(baseColor: .white, value: 0.5) - } else { - colors = colors.filter { $0 != .white } - defaultColor = PresentationThemeAccentColor(baseColor: .blue, value: 0.5) - } - return ThemeSettingsAccentColorItem(theme: theme, sectionId: self.section, colors: colors, currentColor: color ?? defaultColor, updated: { color in arguments.selectAccentColor(color) }, tag: ThemeSettingsEntryTag.accentColor) @@ -297,7 +296,7 @@ private func themeSettingsControllerEntries(presentationData: PresentationData, entries.append(.themeItem(presentationData.theme, presentationData.strings, availableThemes, themeReference, themeSpecificAccentColors, themeSpecificAccentColors[themeReference.index])) if theme.name != .builtin(.dayClassic) { - entries.append(.accentColor(presentationData.theme, strings.Appearance_AccentColor, themeSpecificAccentColors[themeReference.index])) + entries.append(.accentColor(presentationData.theme, themeReference, strings.Appearance_AccentColor, themeSpecificAccentColors[themeReference.index])) } entries.append(.wallpaper(presentationData.theme, strings.Settings_ChatBackground)) diff --git a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj index 7588fe409a..b3ea3b0d96 100644 --- a/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj +++ b/submodules/TelegramUI/TelegramUI_Xcode.xcodeproj/project.pbxproj @@ -2070,7 +2070,6 @@ D0F680091EE750EE000E5906 /* ChannelBannedMemberController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChannelBannedMemberController.swift; sourceTree = ""; }; D0F69CD61D6B87D30046BCD6 /* MediaManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaManager.swift; sourceTree = ""; }; D0F69DB91D6B88190046BCD6 /* TelegramUI.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = TelegramUI.xcconfig; path = TelegramUI/Config/TelegramUI.xcconfig; sourceTree = ""; }; - D0F69DC21D6B89DA0046BCD6 /* TextNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextNode.swift; sourceTree = ""; }; D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RadialProgressNode.swift; sourceTree = ""; }; D0F69DCD1D6B8A0D0046BCD6 /* SearchDisplayController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchDisplayController.swift; sourceTree = ""; }; D0F69DCE1D6B8A0D0046BCD6 /* SearchDisplayControllerContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchDisplayControllerContentNode.swift; sourceTree = ""; }; @@ -3993,7 +3992,6 @@ D0477D191F617E4B00412B44 /* Video */, D0F69DC41D6B89E10046BCD6 /* RadialProgressNode.swift */, D00C7CE51E378FD00080C3D5 /* RadialTimeoutNode.swift */, - D0F69DC21D6B89DA0046BCD6 /* TextNode.swift */, D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */, D0568AAC1DF198130022E7DA /* AudioWaveformNode.swift */, D0BC38621E3F9EFA0044D6FE /* EditableTokenListNode.swift */, @@ -4942,7 +4940,6 @@ D008177D22B46B7E008A895F /* TGContactModel.m in Sources */, D0EC6D301EB9F58800EBF1C3 /* RadialProgressNode.swift in Sources */, D0EC6D311EB9F58800EBF1C3 /* RadialTimeoutNode.swift in Sources */, - D0EC6D321EB9F58800EBF1C3 /* TextNode.swift in Sources */, D0BFAE5020AB2A1300793CF2 /* PeerBanTimeoutController.swift in Sources */, 09CE950A2237B93500A7D2C3 /* SettingsSearchResultItem.swift in Sources */, D0AE303922B1D3620058D3BC /* LegacyBridgeAudio.swift in Sources */, diff --git a/submodules/TelegramUI/third-party/opusenc/opusenc.m b/submodules/TelegramUI/third-party/opusenc/opusenc.m index 2cd7fdea65..d29eaa10ad 100644 --- a/submodules/TelegramUI/third-party/opusenc/opusenc.m +++ b/submodules/TelegramUI/third-party/opusenc/opusenc.m @@ -426,39 +426,24 @@ static inline int writeOggPage(ogg_page *page, TGDataItem *fileItem) pages_out++; } - op.packet = (unsigned char *)_packet; - op.bytes = nbBytes; - op.b_o_s = 0; - op.granulepos = enc_granulepos; - if (op.e_o_s) - { - /* We compute the final GP as ceil(len*48k/input_rate). When a resampling - decoder does the matching floor(len*input/48k) conversion the length will - be exactly the same as the input. - */ - op.granulepos = ((total_samples * 48000 + rate - 1) / rate) + header.preskip; - } - op.packetno = 2 + _packetId; - ogg_stream_packetin(&os, &op); - last_segments += size_segments; + if (framePcmBytes != NULL) { + op.packet = (unsigned char *)_packet; + op.bytes = nbBytes; + op.b_o_s = 0; + op.granulepos = enc_granulepos; - /* The downside of early reading is if the input is an exact - multiple of the frame_size you'll get an extra frame that needs - to get cropped off. The downside of late reading is added delay. - If your ogg_delay is 120ms or less we'll assume you want the - low delay behavior. - */ - /*if ((!op.e_o_s) && max_ogg_delay > 5760) - { - nb_samples = inopt.read_samples(inopt.readdata, input, frame_size); - total_samples += nb_samples; - if (nb_samples < frame_size) - eos = 1; - if (nb_samples == 0) - op.e_o_s = 1; + if (op.e_o_s) + { + /* We compute the final GP as ceil(len*48k/input_rate). When a resampling + decoder does the matching floor(len*input/48k) conversion the length will + be exactly the same as the input. + */ + op.granulepos = ((total_samples * 48000 + rate - 1) / rate) + header.preskip; + } + op.packetno = 2 + _packetId; + ogg_stream_packetin(&os, &op); + last_segments += size_segments; } - else - nb_samples = -1;*/ // If the stream is over or we're sure that the delayed flush will fire, go ahead and flush now to avoid adding delay while ((op.e_o_s || (enc_granulepos + (frame_size * 48000 / coding_rate) - last_granulepos > max_ogg_delay) || diff --git a/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent_Xcode.xcodeproj/project.pbxproj b/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent_Xcode.xcodeproj/project.pbxproj index 0733939be1..4c64113495 100644 --- a/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent_Xcode.xcodeproj/project.pbxproj +++ b/submodules/TelegramUniversalVideoContent/TelegramUniversalVideoContent_Xcode.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ D0C9C3D52300BA8B00FAB518 /* FrameworkBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C9C3D42300BA8B00FAB518 /* FrameworkBundle.swift */; }; D0C9C4442300DC2000FAB518 /* ChatBubbleVideoDecoration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C9C4422300DC2000FAB518 /* ChatBubbleVideoDecoration.swift */; }; D0C9C4452300DC2000FAB518 /* ChatBubbleInstantVideoDecoration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C9C4432300DC2000FAB518 /* ChatBubbleInstantVideoDecoration.swift */; }; + D0C9C5362301CCC600FAB518 /* PhotoResources.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0C9C5352301CCC600FAB518 /* PhotoResources.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -69,6 +70,7 @@ D0C9C3D42300BA8B00FAB518 /* FrameworkBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameworkBundle.swift; sourceTree = ""; }; D0C9C4422300DC2000FAB518 /* ChatBubbleVideoDecoration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBubbleVideoDecoration.swift; sourceTree = ""; }; D0C9C4432300DC2000FAB518 /* ChatBubbleInstantVideoDecoration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatBubbleInstantVideoDecoration.swift; sourceTree = ""; }; + D0C9C5352301CCC600FAB518 /* PhotoResources.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = PhotoResources.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -76,6 +78,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D0C9C5362301CCC600FAB518 /* PhotoResources.framework in Frameworks */, D0C9C3D12300BA4F00FAB518 /* RadialStatusNode.framework in Frameworks */, D0C9C3CF2300BA4400FAB518 /* TelegramAudio.framework in Frameworks */, D0C9C3CB2300BA3300FAB518 /* LegacyComponents.framework in Frameworks */, @@ -138,6 +141,7 @@ D0C9C3882300B41900FAB518 /* Frameworks */ = { isa = PBXGroup; children = ( + D0C9C5352301CCC600FAB518 /* PhotoResources.framework */, D0C9C3D02300BA4F00FAB518 /* RadialStatusNode.framework */, D0C9C3CE2300BA4400FAB518 /* TelegramAudio.framework */, D0C9C3CC2300BA3800FAB518 /* TelegramUI.framework */, diff --git a/submodules/UrlEscaping/Sources/UrlEscaping.swift b/submodules/UrlEscaping/Sources/UrlEscaping.swift index 3fd9fabd82..38f936e0bf 100644 --- a/submodules/UrlEscaping/Sources/UrlEscaping.swift +++ b/submodules/UrlEscaping/Sources/UrlEscaping.swift @@ -32,7 +32,8 @@ public extension CharacterSet { } public func isValidUrl(_ url: String) -> Bool { - if let url = URL(string: url), ["http", "https"].contains(url.scheme), let host = url.host, host.contains(".") && url.user == nil { + + if let escapedUrl = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: escapedUrl), ["http", "https"].contains(url.scheme), let host = url.host, host.contains(".") && url.user == nil { let components = host.components(separatedBy: ".") let domain = (components.first ?? "") if domain.isEmpty {