diff --git a/submodules/LegacyComponents/Sources/AVURLAsset+TGMediaItem.m b/submodules/LegacyComponents/Sources/AVURLAsset+TGMediaItem.m index b4f03a5cb8..e2310c1e6c 100644 --- a/submodules/LegacyComponents/Sources/AVURLAsset+TGMediaItem.m +++ b/submodules/LegacyComponents/Sources/AVURLAsset+TGMediaItem.m @@ -17,7 +17,7 @@ - (CGSize)originalSize { - AVAssetTrack *track = self.tracks.firstObject; + AVAssetTrack *track = [self tracksWithMediaType:AVMediaTypeVideo].firstObject; return CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size; } diff --git a/submodules/LegacyComponents/Sources/TGCameraCapturedVideo.m b/submodules/LegacyComponents/Sources/TGCameraCapturedVideo.m index c8a9f6ee35..e9433f57f5 100644 --- a/submodules/LegacyComponents/Sources/TGCameraCapturedVideo.m +++ b/submodules/LegacyComponents/Sources/TGCameraCapturedVideo.m @@ -164,7 +164,7 @@ return [_originalAsset originalSize]; } - AVAssetTrack *track = _cachedAVAsset.tracks.firstObject; + AVAssetTrack *track = [_cachedAVAsset tracksWithMediaType:AVMediaTypeVideo].firstObject; _cachedSize = CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size; return _cachedSize; } diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetModernImageSignals.m b/submodules/LegacyComponents/Sources/TGMediaAssetModernImageSignals.m index 01a415d803..b7ca6ce4cf 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetModernImageSignals.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetModernImageSignals.m @@ -457,7 +457,7 @@ { return [[SSignal alloc] initWithGenerator:^id(SSubscriber *subscriber) { - AVAssetTrack *track = avAsset.tracks.firstObject; + AVAssetTrack *track = [avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject; if (track == nil) { [subscriber putError:nil]; diff --git a/submodules/MediaPickerUI/Sources/MediaGroupsAlbumItem.swift b/submodules/MediaPickerUI/Sources/MediaGroupsAlbumItem.swift index 319427a2c6..8caeec2bae 100644 --- a/submodules/MediaPickerUI/Sources/MediaGroupsAlbumItem.swift +++ b/submodules/MediaPickerUI/Sources/MediaGroupsAlbumItem.swift @@ -20,6 +20,7 @@ class MediaGroupsAlbumItem: ListViewItem, ListViewItemWithHeader { case animated case depthEffect case livePhotos + case hidden var image: UIImage? { switch self { @@ -43,6 +44,8 @@ class MediaGroupsAlbumItem: ListViewItem, ListViewItemWithHeader { return UIImage(bundleImageName: "Chat/Attach Menu/Portrait") case .livePhotos: return UIImage(bundleImageName: "Chat/Attach Menu/LivePhoto") + case .hidden: + return UIImage(bundleImageName: "Chat/Attach Menu/Hidden") } } } diff --git a/submodules/MediaPickerUI/Sources/MediaGroupsScreen.swift b/submodules/MediaPickerUI/Sources/MediaGroupsScreen.swift index 7dbe9a19e0..f394b1228f 100644 --- a/submodules/MediaPickerUI/Sources/MediaGroupsScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaGroupsScreen.swift @@ -105,9 +105,9 @@ private enum MediaGroupsEntry: Comparable, Identifiable { case .smartAlbumBursts: icon = .bursts case .smartAlbumDepthEffect: - icon = .selfPortraits - case .smartAlbumLivePhotos: icon = .depthEffect + case .smartAlbumLivePhotos: + icon = .livePhotos case .smartAlbumPanoramas: icon = .panoramas case .smartAlbumScreenshots: @@ -120,6 +120,8 @@ private enum MediaGroupsEntry: Comparable, Identifiable { icon = .timelapses case .smartAlbumVideos: icon = .videos + case .smartAlbumAllHidden: + icon = .hidden default: icon = nil } @@ -248,7 +250,8 @@ public final class MediaGroupsScreen: ViewController { .smartAlbumSelfPortraits, .smartAlbumSlomoVideos, .smartAlbumTimelapses, - .smartAlbumVideos + .smartAlbumVideos, + .smartAlbumAllHidden ] if #available(iOS 11, *) { supportedAlbums.append(.smartAlbumAnimated) diff --git a/submodules/ShareItems/Sources/ShareItems.swift b/submodules/ShareItems/Sources/ShareItems.swift index 50639b606d..9dedf94b50 100644 --- a/submodules/ShareItems/Sources/ShareItems.swift +++ b/submodules/ShareItems/Sources/ShareItems.swift @@ -110,33 +110,45 @@ private func preparedShareItem(account: Account, to peerId: PeerId, value: [Stri } var finalDuration: Double = CMTimeGetSeconds(asset.duration) - let preset = adjustments?.preset ?? TGMediaVideoConversionPresetCompressedMedium - let finalDimensions = TGMediaVideoConverter.dimensions(for: asset.originalSize, adjustments: adjustments, preset: preset) + func loadValues(_ avAsset: AVURLAsset) -> Signal { + return Signal { subscriber in + avAsset.loadValuesAsynchronously(forKeys: ["tracks", "duration", "playable"]) { + subscriber.putNext(avAsset) + } + return EmptyDisposable + } + } - var resourceAdjustments: VideoMediaResourceAdjustments? - if let adjustments = adjustments { - if adjustments.trimApplied() { - finalDuration = adjustments.trimEndValue - adjustments.trimStartValue + return loadValues(asset) + |> mapToSignal { asset -> Signal in + let preset = adjustments?.preset ?? TGMediaVideoConversionPresetCompressedMedium + let finalDimensions = TGMediaVideoConverter.dimensions(for: asset.originalSize, adjustments: adjustments, preset: preset) + + var resourceAdjustments: VideoMediaResourceAdjustments? + if let adjustments = adjustments { + if adjustments.trimApplied() { + finalDuration = adjustments.trimEndValue - adjustments.trimStartValue + } + + let adjustmentsData = MemoryBuffer(data: NSKeyedArchiver.archivedData(withRootObject: adjustments.dictionary()!)) + let digest = MemoryBuffer(data: adjustmentsData.md5Digest()) + resourceAdjustments = VideoMediaResourceAdjustments(data: adjustmentsData, digest: digest) } - let adjustmentsData = MemoryBuffer(data: NSKeyedArchiver.archivedData(withRootObject: adjustments.dictionary()!)) - let digest = MemoryBuffer(data: adjustmentsData.md5Digest()) - resourceAdjustments = VideoMediaResourceAdjustments(data: adjustmentsData, digest: digest) - } - - let estimatedSize = TGMediaVideoConverter.estimatedSize(for: preset, duration: finalDuration, hasAudio: true) - - let resource = LocalFileVideoMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: asset.url.path, adjustments: resourceAdjustments) - return standaloneUploadedFile(account: account, peerId: peerId, text: "", source: .resource(.standalone(resource: resource)), mimeType: "video/mp4", attributes: [.Video(duration: Int(finalDuration), size: PixelDimensions(width: Int32(finalDimensions.width), height: Int32(finalDimensions.height)), flags: flags)], hintFileIsLarge: estimatedSize > 10 * 1024 * 1024) - |> mapError { _ -> Void in - return Void() - } - |> mapToSignal { event -> Signal in - switch event { - case let .progress(value): - return .single(.progress(value)) - case let .result(media): - return .single(.done(.media(media))) + let estimatedSize = TGMediaVideoConverter.estimatedSize(for: preset, duration: finalDuration, hasAudio: true) + + let resource = LocalFileVideoMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: asset.url.path, adjustments: resourceAdjustments) + return standaloneUploadedFile(account: account, peerId: peerId, text: "", source: .resource(.standalone(resource: resource)), mimeType: "video/mp4", attributes: [.Video(duration: Int(finalDuration), size: PixelDimensions(width: Int32(finalDimensions.width), height: Int32(finalDimensions.height)), flags: flags)], hintFileIsLarge: estimatedSize > 10 * 1024 * 1024) + |> mapError { _ -> Void in + return Void() + } + |> mapToSignal { event -> Signal in + switch event { + case let .progress(value): + return .single(.progress(value)) + case let .result(media): + return .single(.done(.media(media))) + } } } } else if let data = value["data"] as? Data { diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Contents.json index 0dd1dc8086..6e0c0392be 100644 --- a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Video.pdf", + "filename" : "videocamera_30.pdf", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Video.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Video.pdf deleted file mode 100644 index 40cb0010b4..0000000000 Binary files a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/Video.pdf and /dev/null differ diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/videocamera_30.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/videocamera_30.pdf new file mode 100644 index 0000000000..501115e076 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/videocamera_30.pdf @@ -0,0 +1,99 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 3.000000 7.000000 cm +0.000000 0.000000 0.000000 scn +0.435974 13.815962 m +0.000000 12.960315 0.000000 11.840210 0.000000 9.600000 c +0.000000 6.400000 l +0.000000 4.159790 0.000000 3.039685 0.435974 2.184038 c +0.819467 1.431390 1.431390 0.819468 2.184038 0.435974 c +3.039685 0.000000 4.159790 0.000000 6.400000 0.000000 c +10.599999 0.000000 l +12.840210 0.000000 13.960315 0.000000 14.815962 0.435974 c +15.568610 0.819468 16.180532 1.431390 16.564026 2.184038 c +17.000000 3.039685 17.000000 4.159790 17.000000 6.400000 c +17.000000 9.600000 l +17.000000 11.840210 17.000000 12.960315 16.564026 13.815962 c +16.180532 14.568610 15.568610 15.180532 14.815962 15.564026 c +13.960315 16.000000 12.840210 16.000000 10.600000 16.000000 c +6.400000 16.000000 l +4.159790 16.000000 3.039685 16.000000 2.184038 15.564026 c +1.431390 15.180532 0.819467 14.568610 0.435974 13.815962 c +h +24.993134 13.144460 m +24.920448 13.905111 24.279696 14.500000 23.500000 14.500000 c +23.175446 14.500000 22.859644 14.394733 22.600000 14.200000 c +18.799999 10.600000 l +18.667856 10.491791 l +18.244949 10.114210 18.000000 9.572287 18.000000 9.000000 c +18.000000 7.000000 l +18.007282 6.829359 l +18.055601 6.264485 18.342171 5.743371 18.799999 5.400000 c +22.600000 1.799999 l +22.719688 1.718817 l +23.371820 1.320574 24.232182 1.476244 24.700001 2.100000 c +24.894733 2.359645 25.000000 2.675445 25.000000 3.000000 c +25.000000 13.000000 l +24.993134 13.144460 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1496 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001586 00000 n +0000001609 00000 n +0000001782 00000 n +0000001856 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1915 +%%EOF \ No newline at end of file diff --git a/submodules/WebSearchUI/Sources/WebSearchController.swift b/submodules/WebSearchUI/Sources/WebSearchController.swift index ca03c963ca..257188e1da 100644 --- a/submodules/WebSearchUI/Sources/WebSearchController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchController.swift @@ -79,18 +79,20 @@ final class WebSearchControllerInteraction { let setSearchQuery: (String) -> Void let deleteRecentQuery: (String) -> Void let toggleSelection: (ChatContextResult, Bool) -> Void - let sendSelected: (ChatContextResultCollection, ChatContextResult?) -> Void + let sendSelected: (ChatContextResult?, Bool, Int32?) -> Void + let schedule: () -> Void let avatarCompleted: (UIImage) -> Void let selectionState: TGMediaSelectionContext? let editingState: TGMediaEditingContext var hiddenMediaId: String? - init(openResult: @escaping (ChatContextResult) -> Void, setSearchQuery: @escaping (String) -> Void, deleteRecentQuery: @escaping (String) -> Void, toggleSelection: @escaping (ChatContextResult, Bool) -> Void, sendSelected: @escaping (ChatContextResultCollection, ChatContextResult?) -> Void, avatarCompleted: @escaping (UIImage) -> Void, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext) { + init(openResult: @escaping (ChatContextResult) -> Void, setSearchQuery: @escaping (String) -> Void, deleteRecentQuery: @escaping (String) -> Void, toggleSelection: @escaping (ChatContextResult, Bool) -> Void, sendSelected: @escaping (ChatContextResult?, Bool, Int32?) -> Void, schedule: @escaping () -> Void, avatarCompleted: @escaping (UIImage) -> Void, selectionState: TGMediaSelectionContext?, editingState: TGMediaEditingContext) { self.openResult = openResult self.setSearchQuery = setSearchQuery self.deleteRecentQuery = deleteRecentQuery self.toggleSelection = toggleSelection self.sendSelected = sendSelected + self.schedule = schedule self.avatarCompleted = avatarCompleted self.selectionState = selectionState self.editingState = editingState @@ -162,6 +164,8 @@ public final class WebSearchController: ViewController { } } + public var presentSchedulePicker: (Bool, @escaping (Int32) -> Void) -> Void = { _, _ in } + public var dismissed: () -> Void = { } public var searchingUpdated: (Bool) -> Void = { _ in } @@ -283,8 +287,8 @@ public final class WebSearchController: ViewController { let item = LegacyWebSearchItem(result: result) strongSelf.controllerInteraction?.selectionState?.setItem(item, selected: value) } - }, sendSelected: { results, current in - if let selectionState = selectionState { + }, sendSelected: { [weak self] current, silently, scheduleTime in + if let selectionState = selectionState, let results = self?.controllerNode.currentExternalResults { if let current = current { let currentItem = LegacyWebSearchItem(result: current) selectionState.setItem(currentItem, selected: true) @@ -293,6 +297,12 @@ public final class WebSearchController: ViewController { sendSelected(results, selectionState, editingState, false) } } + }, schedule: { [weak self] in + if let strongSelf = self { + strongSelf.presentSchedulePicker(false, { [weak self] time in + self?.controllerInteraction?.sendSelected(nil, false, time) + }) + } }, avatarCompleted: { result in if case let .avatar(_, avatarCompleted) = mode { avatarCompleted(result) @@ -592,10 +602,10 @@ public class WebSearchPickerContext: AttachmentMediaPickerContext { } public func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { -// self.interaction?.sendSelected(nil, silently, nil, true) + self.interaction?.sendSelected(nil, silently, nil) } public func schedule() { -// self.interaction?.schedule() + self.interaction?.schedule() } } diff --git a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift index 3645eacf80..503b287671 100644 --- a/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift +++ b/submodules/WebSearchUI/Sources/WebSearchControllerNode.swift @@ -162,7 +162,7 @@ class WebSearchControllerNode: ASDisplayNode { private var enqueuedTransitions: [(WebSearchTransition, Bool)] = [] private var dequeuedInitialTransitionOnLayout = false - private var currentExternalResults: ChatContextResultCollection? + private(set) var currentExternalResults: ChatContextResultCollection? private var currentProcessedResults: ChatContextResultCollection? private var currentEntries: [WebSearchEntry]? private var hasMore = false @@ -718,9 +718,8 @@ class WebSearchControllerNode: ASDisplayNode { } @objc private func sendPressed() { - if let results = self.currentExternalResults { - self.controllerInteraction.sendSelected(results, nil) - } + self.controllerInteraction.sendSelected(nil, false, nil) + self.cancel?() } @@ -741,8 +740,8 @@ class WebSearchControllerNode: ASDisplayNode { }, transitionView: { [weak self] result in return self?.transitionNode(for: result)?.transitionView() }, completed: { [weak self] result in - if let strongSelf = self, let results = strongSelf.currentExternalResults { - strongSelf.controllerInteraction.sendSelected(results, result) + if let strongSelf = self { + strongSelf.controllerInteraction.sendSelected(result, false, nil) strongSelf.cancel?() } }, presentStickers: self.presentStickers, getCaptionPanelView: self.getCaptionPanelView, present: present) @@ -761,8 +760,8 @@ class WebSearchControllerNode: ASDisplayNode { let controller = WebSearchGalleryController(context: self.context, peer: self.peer, selectionState: self.controllerInteraction.selectionState, editingState: self.controllerInteraction.editingState, entries: entries, centralIndex: centralIndex, replaceRootController: { (controller, _) in }, baseNavigationController: nil, sendCurrent: { [weak self] result in - if let strongSelf = self, let results = strongSelf.currentExternalResults { - strongSelf.controllerInteraction.sendSelected(results, result) + if let strongSelf = self { + strongSelf.controllerInteraction.sendSelected(result, false, nil) strongSelf.cancel?() } })