mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '43cb778ef5a6744598dfeca2ea69446e10153796' into beta
This commit is contained in:
commit
c7cc323ef5
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -457,7 +457,7 @@
|
||||
{
|
||||
return [[SSignal alloc] initWithGenerator:^id<SDisposable>(SSubscriber *subscriber)
|
||||
{
|
||||
AVAssetTrack *track = avAsset.tracks.firstObject;
|
||||
AVAssetTrack *track = [avAsset tracksWithMediaType:AVMediaTypeVideo].firstObject;
|
||||
if (track == nil)
|
||||
{
|
||||
[subscriber putError:nil];
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<AVURLAsset, Void> {
|
||||
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<PreparedShareItem, Void> 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<PreparedShareItem, Void> 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<PreparedShareItem, Void> 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 {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Video.pdf",
|
||||
"filename" : "videocamera_30.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
Binary file not shown.
99
submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/videocamera_30.pdf
vendored
Normal file
99
submodules/TelegramUI/Images.xcassets/Peer Info/ButtonVideo.imageset/videocamera_30.pdf
vendored
Normal 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
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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?()
|
||||
}
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user