Merge commit '43cb778ef5a6744598dfeca2ea69446e10153796' into beta

This commit is contained in:
Ali 2022-03-01 21:41:02 +04:00
commit c7cc323ef5
11 changed files with 171 additions and 45 deletions

View File

@ -17,7 +17,7 @@
- (CGSize)originalSize - (CGSize)originalSize
{ {
AVAssetTrack *track = self.tracks.firstObject; AVAssetTrack *track = [self tracksWithMediaType:AVMediaTypeVideo].firstObject;
return CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size; return CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size;
} }

View File

@ -164,7 +164,7 @@
return [_originalAsset originalSize]; return [_originalAsset originalSize];
} }
AVAssetTrack *track = _cachedAVAsset.tracks.firstObject; AVAssetTrack *track = [_cachedAVAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
_cachedSize = CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size; _cachedSize = CGRectApplyAffineTransform((CGRect){ CGPointZero, track.naturalSize }, track.preferredTransform).size;
return _cachedSize; return _cachedSize;
} }

View File

@ -457,7 +457,7 @@
{ {
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber) return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
{ {
AVAssetTrack *track = avAsset.tracks.firstObject; AVAssetTrack *track = [avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
if (track == nil) if (track == nil)
{ {
[subscriber putError:nil]; [subscriber putError:nil];

View File

@ -20,6 +20,7 @@ class MediaGroupsAlbumItem: ListViewItem, ListViewItemWithHeader {
case animated case animated
case depthEffect case depthEffect
case livePhotos case livePhotos
case hidden
var image: UIImage? { var image: UIImage? {
switch self { switch self {
@ -43,6 +44,8 @@ class MediaGroupsAlbumItem: ListViewItem, ListViewItemWithHeader {
return UIImage(bundleImageName: "Chat/Attach Menu/Portrait") return UIImage(bundleImageName: "Chat/Attach Menu/Portrait")
case .livePhotos: case .livePhotos:
return UIImage(bundleImageName: "Chat/Attach Menu/LivePhoto") return UIImage(bundleImageName: "Chat/Attach Menu/LivePhoto")
case .hidden:
return UIImage(bundleImageName: "Chat/Attach Menu/Hidden")
} }
} }
} }

View File

@ -105,9 +105,9 @@ private enum MediaGroupsEntry: Comparable, Identifiable {
case .smartAlbumBursts: case .smartAlbumBursts:
icon = .bursts icon = .bursts
case .smartAlbumDepthEffect: case .smartAlbumDepthEffect:
icon = .selfPortraits
case .smartAlbumLivePhotos:
icon = .depthEffect icon = .depthEffect
case .smartAlbumLivePhotos:
icon = .livePhotos
case .smartAlbumPanoramas: case .smartAlbumPanoramas:
icon = .panoramas icon = .panoramas
case .smartAlbumScreenshots: case .smartAlbumScreenshots:
@ -120,6 +120,8 @@ private enum MediaGroupsEntry: Comparable, Identifiable {
icon = .timelapses icon = .timelapses
case .smartAlbumVideos: case .smartAlbumVideos:
icon = .videos icon = .videos
case .smartAlbumAllHidden:
icon = .hidden
default: default:
icon = nil icon = nil
} }
@ -248,7 +250,8 @@ public final class MediaGroupsScreen: ViewController {
.smartAlbumSelfPortraits, .smartAlbumSelfPortraits,
.smartAlbumSlomoVideos, .smartAlbumSlomoVideos,
.smartAlbumTimelapses, .smartAlbumTimelapses,
.smartAlbumVideos .smartAlbumVideos,
.smartAlbumAllHidden
] ]
if #available(iOS 11, *) { if #available(iOS 11, *) {
supportedAlbums.append(.smartAlbumAnimated) supportedAlbums.append(.smartAlbumAnimated)

View File

@ -110,33 +110,45 @@ private func preparedShareItem(account: Account, to peerId: PeerId, value: [Stri
} }
var finalDuration: Double = CMTimeGetSeconds(asset.duration) var finalDuration: Double = CMTimeGetSeconds(asset.duration)
let preset = adjustments?.preset ?? TGMediaVideoConversionPresetCompressedMedium func loadValues(_ avAsset: AVURLAsset) -> Signal<AVURLAsset, Void> {
let finalDimensions = TGMediaVideoConverter.dimensions(for: asset.originalSize, adjustments: adjustments, preset: preset) return Signal { subscriber in
avAsset.loadValuesAsynchronously(forKeys: ["tracks", "duration", "playable"]) {
subscriber.putNext(avAsset)
}
return EmptyDisposable
}
}
var resourceAdjustments: VideoMediaResourceAdjustments? return loadValues(asset)
if let adjustments = adjustments { |> mapToSignal { asset -> Signal<PreparedShareItem, Void> in
if adjustments.trimApplied() { let preset = adjustments?.preset ?? TGMediaVideoConversionPresetCompressedMedium
finalDuration = adjustments.trimEndValue - adjustments.trimStartValue 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 estimatedSize = TGMediaVideoConverter.estimatedSize(for: preset, duration: finalDuration, hasAudio: true)
let digest = MemoryBuffer(data: adjustmentsData.md5Digest())
resourceAdjustments = VideoMediaResourceAdjustments(data: adjustmentsData, digest: digest) 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
let estimatedSize = TGMediaVideoConverter.estimatedSize(for: preset, duration: finalDuration, hasAudio: true) return Void()
}
let resource = LocalFileVideoMediaResource(randomId: Int64.random(in: Int64.min ... Int64.max), path: asset.url.path, adjustments: resourceAdjustments) |> mapToSignal { event -> Signal<PreparedShareItem, Void> in
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) switch event {
|> mapError { _ -> Void in case let .progress(value):
return Void() return .single(.progress(value))
} case let .result(media):
|> mapToSignal { event -> Signal<PreparedShareItem, Void> in return .single(.done(.media(media)))
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 { } else if let data = value["data"] as? Data {

View File

@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "Video.pdf", "filename" : "videocamera_30.pdf",
"idiom" : "universal" "idiom" : "universal"
} }
], ],

View File

@ -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

View File

@ -79,18 +79,20 @@ final class WebSearchControllerInteraction {
let setSearchQuery: (String) -> Void let setSearchQuery: (String) -> Void
let deleteRecentQuery: (String) -> Void let deleteRecentQuery: (String) -> Void
let toggleSelection: (ChatContextResult, Bool) -> 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 avatarCompleted: (UIImage) -> Void
let selectionState: TGMediaSelectionContext? let selectionState: TGMediaSelectionContext?
let editingState: TGMediaEditingContext let editingState: TGMediaEditingContext
var hiddenMediaId: String? 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.openResult = openResult
self.setSearchQuery = setSearchQuery self.setSearchQuery = setSearchQuery
self.deleteRecentQuery = deleteRecentQuery self.deleteRecentQuery = deleteRecentQuery
self.toggleSelection = toggleSelection self.toggleSelection = toggleSelection
self.sendSelected = sendSelected self.sendSelected = sendSelected
self.schedule = schedule
self.avatarCompleted = avatarCompleted self.avatarCompleted = avatarCompleted
self.selectionState = selectionState self.selectionState = selectionState
self.editingState = editingState 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 dismissed: () -> Void = { }
public var searchingUpdated: (Bool) -> Void = { _ in } public var searchingUpdated: (Bool) -> Void = { _ in }
@ -283,8 +287,8 @@ public final class WebSearchController: ViewController {
let item = LegacyWebSearchItem(result: result) let item = LegacyWebSearchItem(result: result)
strongSelf.controllerInteraction?.selectionState?.setItem(item, selected: value) strongSelf.controllerInteraction?.selectionState?.setItem(item, selected: value)
} }
}, sendSelected: { results, current in }, sendSelected: { [weak self] current, silently, scheduleTime in
if let selectionState = selectionState { if let selectionState = selectionState, let results = self?.controllerNode.currentExternalResults {
if let current = current { if let current = current {
let currentItem = LegacyWebSearchItem(result: current) let currentItem = LegacyWebSearchItem(result: current)
selectionState.setItem(currentItem, selected: true) selectionState.setItem(currentItem, selected: true)
@ -293,6 +297,12 @@ public final class WebSearchController: ViewController {
sendSelected(results, selectionState, editingState, false) 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 }, avatarCompleted: { result in
if case let .avatar(_, avatarCompleted) = mode { if case let .avatar(_, avatarCompleted) = mode {
avatarCompleted(result) avatarCompleted(result)
@ -592,10 +602,10 @@ public class WebSearchPickerContext: AttachmentMediaPickerContext {
} }
public func send(silently: Bool, mode: AttachmentMediaPickerSendMode) { public func send(silently: Bool, mode: AttachmentMediaPickerSendMode) {
// self.interaction?.sendSelected(nil, silently, nil, true) self.interaction?.sendSelected(nil, silently, nil)
} }
public func schedule() { public func schedule() {
// self.interaction?.schedule() self.interaction?.schedule()
} }
} }

View File

@ -162,7 +162,7 @@ class WebSearchControllerNode: ASDisplayNode {
private var enqueuedTransitions: [(WebSearchTransition, Bool)] = [] private var enqueuedTransitions: [(WebSearchTransition, Bool)] = []
private var dequeuedInitialTransitionOnLayout = false private var dequeuedInitialTransitionOnLayout = false
private var currentExternalResults: ChatContextResultCollection? private(set) var currentExternalResults: ChatContextResultCollection?
private var currentProcessedResults: ChatContextResultCollection? private var currentProcessedResults: ChatContextResultCollection?
private var currentEntries: [WebSearchEntry]? private var currentEntries: [WebSearchEntry]?
private var hasMore = false private var hasMore = false
@ -718,9 +718,8 @@ class WebSearchControllerNode: ASDisplayNode {
} }
@objc private func sendPressed() { @objc private func sendPressed() {
if let results = self.currentExternalResults { self.controllerInteraction.sendSelected(nil, false, nil)
self.controllerInteraction.sendSelected(results, nil)
}
self.cancel?() self.cancel?()
} }
@ -741,8 +740,8 @@ class WebSearchControllerNode: ASDisplayNode {
}, transitionView: { [weak self] result in }, transitionView: { [weak self] result in
return self?.transitionNode(for: result)?.transitionView() return self?.transitionNode(for: result)?.transitionView()
}, completed: { [weak self] result in }, completed: { [weak self] result in
if let strongSelf = self, let results = strongSelf.currentExternalResults { if let strongSelf = self {
strongSelf.controllerInteraction.sendSelected(results, result) strongSelf.controllerInteraction.sendSelected(result, false, nil)
strongSelf.cancel?() strongSelf.cancel?()
} }
}, presentStickers: self.presentStickers, getCaptionPanelView: self.getCaptionPanelView, present: present) }, 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 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 }, baseNavigationController: nil, sendCurrent: { [weak self] result in
if let strongSelf = self, let results = strongSelf.currentExternalResults { if let strongSelf = self {
strongSelf.controllerInteraction.sendSelected(results, result) strongSelf.controllerInteraction.sendSelected(result, false, nil)
strongSelf.cancel?() strongSelf.cancel?()
} }
}) })