mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
Merge branch 'master' of github.com:peter-iakovlev/TelegramUI
# Conflicts: # TelegramUI/TelegramController.swift
This commit is contained in:
commit
b0815c344e
@ -993,6 +993,7 @@
|
||||
D0EC6EA61EB9FC2400EBF1C3 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D07551901DDA4FC70073E051 /* libc++.tbd */; };
|
||||
D0EC6EBD1EBA100F00EBF1C3 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0EC6EBC1EBA100F00EBF1C3 /* CoreAudio.framework */; };
|
||||
D0EC6FFD1EBA1F2400EBF1C3 /* OngoingCallThreadLocalContext.mm in Sources */ = {isa = PBXBuildFile; fileRef = D0EC6FFC1EBA1F2400EBF1C3 /* OngoingCallThreadLocalContext.mm */; };
|
||||
D0EEE9A12165585F001292A6 /* DocumentPreviewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EEE9A02165585F001292A6 /* DocumentPreviewController.swift */; };
|
||||
D0F0AAE01EC1E12C005EE2A5 /* PresentationCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0AADF1EC1E12C005EE2A5 /* PresentationCall.swift */; };
|
||||
D0F0AAE21EC20EF8005EE2A5 /* CallControllerStatusNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0AAE11EC20EF8005EE2A5 /* CallControllerStatusNode.swift */; };
|
||||
D0F0AAE41EC21AAA005EE2A5 /* CallControllerButtonsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0AAE31EC21AAA005EE2A5 /* CallControllerButtonsNode.swift */; };
|
||||
@ -1970,6 +1971,7 @@
|
||||
D0EC6FFC1EBA1F2400EBF1C3 /* OngoingCallThreadLocalContext.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = OngoingCallThreadLocalContext.mm; sourceTree = "<group>"; };
|
||||
D0ED5D4A1DC806D7007CBB15 /* ApplicationSpecificData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationSpecificData.swift; sourceTree = "<group>"; };
|
||||
D0EE97191D88BCA0006C18E1 /* ChatInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatInfo.swift; sourceTree = "<group>"; };
|
||||
D0EEE9A02165585F001292A6 /* DocumentPreviewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPreviewController.swift; sourceTree = "<group>"; };
|
||||
D0EF40DC1E72F00E000DFCD4 /* SelectivePrivacySettingsPeersController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectivePrivacySettingsPeersController.swift; sourceTree = "<group>"; };
|
||||
D0EF40DE1E73100D000DFCD4 /* ChatHistoryNavigationStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatHistoryNavigationStack.swift; sourceTree = "<group>"; };
|
||||
D0EFD8951DDE8249009E508A /* LegacyLocationPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyLocationPicker.swift; sourceTree = "<group>"; };
|
||||
@ -3779,6 +3781,14 @@
|
||||
name = "Peer Info";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0EEE99F2165583B001292A6 /* Document */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D0EEE9A02165585F001292A6 /* DocumentPreviewController.swift */,
|
||||
);
|
||||
name = Document;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D0F53BF51E79592300117362 /* Sign Up */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -4132,6 +4142,7 @@
|
||||
D0B7F8DF1D8A17D20045D939 /* Collection */,
|
||||
D0F69E4F1D6B8BC40046BCD6 /* Gallery */,
|
||||
D0575AF81EA0FD94006F2541 /* Avatar Gallery */,
|
||||
D0EEE99F2165583B001292A6 /* Document */,
|
||||
D0104F261F471702004E4881 /* Instant Page Gallery */,
|
||||
D0F69E671D6B8C030046BCD6 /* Map Input */,
|
||||
D07827CC1E03F32C00071108 /* Instant Page */,
|
||||
@ -5210,6 +5221,7 @@
|
||||
D06CF82920D0119500AC4CFF /* SecureIdAuthListFieldNode.swift in Sources */,
|
||||
D0EC6DCD1EB9F58900EBF1C3 /* ChatInputContextPanelNode.swift in Sources */,
|
||||
D0F8C399201774AF00236FC5 /* FeedGroupingControllerNode.swift in Sources */,
|
||||
D0EEE9A12165585F001292A6 /* DocumentPreviewController.swift in Sources */,
|
||||
D0EC6DCE1EB9F58900EBF1C3 /* HorizontalStickersChatContextPanelNode.swift in Sources */,
|
||||
D0BCC3D2203F0A6C008126C2 /* StringForMessageTimestampStatus.swift in Sources */,
|
||||
D0EC6DCF1EB9F58900EBF1C3 /* HorizontalStickerGridItem.swift in Sources */,
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<key>TelegramUI.xcscheme</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>3</integer>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
|
||||
@ -315,7 +315,8 @@ private let hasApplePaySupport: Bool = PKPaymentAuthorizationViewController.canM
|
||||
private var applePayProviders = Set<String>([
|
||||
"stripe",
|
||||
"sberbank",
|
||||
"yandex"
|
||||
"yandex",
|
||||
"privatbank"
|
||||
])
|
||||
|
||||
private func availablePaymentMethods(current: BotCheckoutPaymentMethod?, supportsApplePay: Bool) -> [BotCheckoutPaymentMethod] {
|
||||
|
||||
@ -2647,27 +2647,29 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
self.interfaceInteraction = interfaceInteraction
|
||||
self.chatDisplayNode.interfaceInteraction = interfaceInteraction
|
||||
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(self.account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
for id in ids {
|
||||
if case let .chat(messageId, media) = id {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
}
|
||||
}
|
||||
|
||||
//if controllerInteraction.hiddenMedia != messageIdAndMedia {
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
if let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
for id in ids {
|
||||
if case let .chat(messageId, media) = id {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}))
|
||||
|
||||
//if controllerInteraction.hiddenMedia != messageIdAndMedia {
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
self.chatDisplayNode.dismissAsOverlay = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
@ -3692,8 +3694,11 @@ public final class ChatController: TelegramController, UIViewControllerPreviewin
|
||||
self.audioRecorderFeedback = HapticFeedback()
|
||||
self.audioRecorderFeedback?.prepareTap()
|
||||
}
|
||||
self.audioRecorder.set(applicationContext.mediaManager.audioRecorder(beginWithTone: beginWithTone, applicationBindings: applicationContext.applicationBindings, beganWithTone: { _ in
|
||||
}))
|
||||
|
||||
if let mediaManager = applicationContext.mediaManager {
|
||||
self.audioRecorder.set(mediaManager.audioRecorder(beginWithTone: beginWithTone, applicationBindings: applicationContext.applicationBindings, beganWithTone: { _ in
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
|
||||
private let deleteButton: UIButton
|
||||
private let actionButton: UIButton
|
||||
private let textNode: ASTextNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private let authorNameNode: ASTextNode
|
||||
private let dateNode: ASTextNode
|
||||
private let backwardButton: HighlightableButtonNode
|
||||
@ -138,7 +138,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
self.deleteButton.setImage(deleteImage, for: [.normal])
|
||||
self.actionButton.setImage(actionImage, for: [.normal])
|
||||
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.maximumNumberOfLines = 10
|
||||
self.textNode.isLayerBacked = true
|
||||
self.authorNameNode = ASTextNode()
|
||||
self.authorNameNode.maximumNumberOfLines = 1
|
||||
@ -295,7 +296,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode {
|
||||
let sideInset: CGFloat = 8.0 + leftInset
|
||||
let topInset: CGFloat = 8.0
|
||||
let textBottomInset: CGFloat = 8.0
|
||||
let textSize = self.textNode.measure(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: CGFloat.greatestFiniteMagnitude))
|
||||
panelHeight += textSize.height + topInset + textBottomInset
|
||||
textFrame = CGRect(origin: CGPoint(x: sideInset, y: topInset), size: textSize)
|
||||
}
|
||||
|
||||
@ -328,7 +328,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
var inlineImageDimensions: CGSize?
|
||||
var inlineImageSize: CGSize?
|
||||
var updateInlineImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
var textCutout: TextNodeCutout?
|
||||
var textCutout = TextNodeCutout()
|
||||
var initialWidth: CGFloat = CGFloat.greatestFiniteMagnitude
|
||||
var refineContentImageLayout: ((CGSize, ImageCorners) -> (CGFloat, (CGFloat) -> (CGSize, (ContainedViewLayoutTransition) -> ChatMessageInteractiveMediaNode)))?
|
||||
var refineContentFileLayout: ((CGSize) -> (CGFloat, (CGFloat) -> (CGSize, () -> ChatMessageInteractiveFileNode)))?
|
||||
@ -435,7 +435,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
inlineImageSize = CGSize(width: 54.0, height: 54.0)
|
||||
|
||||
if let inlineImageSize = inlineImageSize {
|
||||
textCutout = TextNodeCutout(position: .TopRight, size: CGSize(width: inlineImageSize.width + 10.0, height: inlineImageSize.height + 10.0))
|
||||
textCutout.topRight = CGSize(width: inlineImageSize.width + 10.0, height: inlineImageSize.height + 10.0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,23 +508,28 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
updatedAdditionalImageBadge = currentAdditionalImageBadgeNode ?? ChatMessageInteractiveMediaBadge()
|
||||
}
|
||||
|
||||
let (textLayout, textApply) = textAsyncLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 12, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: textCutout, insets: UIEdgeInsets()))
|
||||
var upatedTextCutout = textCutout
|
||||
if statusInText, let (statusSize, _) = statusSizeAndApply {
|
||||
upatedTextCutout.bottomRight = statusSize
|
||||
}
|
||||
|
||||
let (textLayout, textApply) = textAsyncLayout(TextNodeLayoutArguments(attributedString: textString, backgroundColor: nil, maximumNumberOfLines: 12, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: upatedTextCutout, insets: UIEdgeInsets()))
|
||||
|
||||
var textFrame = CGRect(origin: CGPoint(), size: textLayout.size)
|
||||
|
||||
var statusFrame: CGRect?
|
||||
|
||||
if statusInText, let (statusSize, _) = statusSizeAndApply {
|
||||
var frame = CGRect(origin: CGPoint(), size: statusSize)
|
||||
var frame = CGRect(origin: CGPoint(x: textFrame.maxX - statusSize.width, y: textFrame.maxY - statusSize.height), size: statusSize)
|
||||
|
||||
let trailingLineWidth = textLayout.trailingLineWidth
|
||||
/*let trailingLineWidth = textLayout.trailingLineWidth
|
||||
if textLayout.size.width - trailingLineWidth >= statusSize.width {
|
||||
frame.origin = CGPoint(x: textFrame.maxX - statusSize.width, y: textFrame.maxY - statusSize.height)
|
||||
} else if trailingLineWidth + statusSize.width < textConstrainedSize.width {
|
||||
frame.origin = CGPoint(x: textFrame.minX + trailingLineWidth, y: textFrame.maxY - statusSize.height)
|
||||
} else {
|
||||
frame.origin = CGPoint(x: textFrame.maxX - statusSize.width, y: textFrame.maxY)
|
||||
}
|
||||
}*/
|
||||
|
||||
if let inlineImageSize = inlineImageSize {
|
||||
if frame.origin.y < inlineImageSize.height + 4.0 {
|
||||
|
||||
@ -101,7 +101,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
}
|
||||
case .playbackStatus:
|
||||
if let account = self.account, let applicationContext = account.applicationContext as? TelegramApplicationContext, let message = self.message, let type = peerMessageMediaPlayerType(message) {
|
||||
applicationContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: type)
|
||||
applicationContext.mediaManager?.playlistControl(.playback(.togglePlayPause), type: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -418,7 +418,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
waveformScrubbingNode.hitTestSlop = UIEdgeInsetsMake(-10.0, 0.0, -10.0, 0.0)
|
||||
waveformScrubbingNode.seek = { timestamp in
|
||||
if let strongSelf = self, let account = strongSelf.account, let message = strongSelf.message, let type = peerMessageMediaPlayerType(message) {
|
||||
account.telegramApplicationContext.mediaManager.playlistControl(.seek(timestamp), type: type)
|
||||
account.telegramApplicationContext.mediaManager?.playlistControl(.seek(timestamp), type: type)
|
||||
}
|
||||
}
|
||||
waveformScrubbingNode.status = strongSelf.playbackStatus.get()
|
||||
|
||||
@ -328,28 +328,30 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
videoNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
let videoNode = UniversalVideoNode(postbox: item.account.postbox, audioSession: item.account.telegramApplicationContext.mediaManager.audioSession, manager: item.account.telegramApplicationContext.mediaManager.universalVideoManager, decoration: ChatBubbleInstantVideoDecoration(diameter: displaySize.width + 2.0, backgroundImage: instantVideoBackgroundImage, tapped: {
|
||||
if let strongSelf = self {
|
||||
if let item = strongSelf.item {
|
||||
if strongSelf.infoBackgroundNode.alpha.isZero {
|
||||
item.account.telegramApplicationContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: .voice)
|
||||
} else {
|
||||
//let _ = item.controllerInteraction.openMessage(item.message)
|
||||
if let mediaManager = item.account.telegramApplicationContext.mediaManager {
|
||||
let videoNode = UniversalVideoNode(postbox: item.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: ChatBubbleInstantVideoDecoration(diameter: displaySize.width + 2.0, backgroundImage: instantVideoBackgroundImage, tapped: {
|
||||
if let strongSelf = self {
|
||||
if let item = strongSelf.item {
|
||||
if strongSelf.infoBackgroundNode.alpha.isZero {
|
||||
item.account.telegramApplicationContext.mediaManager?.playlistControl(.playback(.togglePlayPause), type: .voice)
|
||||
} else {
|
||||
//let _ = item.controllerInteraction.openMessage(item.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}), content: NativeVideoContent(id: .message(item.message.id, item.message.stableId, telegramFile.fileId), fileReference: .message(message: MessageReference(item.message), media: telegramFile), streamVideo: false, enableSound: false), priority: .embedded, autoplay: true)
|
||||
let previousVideoNode = strongSelf.videoNode
|
||||
strongSelf.videoNode = videoNode
|
||||
strongSelf.insertSubnode(videoNode, belowSubnode: previousVideoNode ?? strongSelf.dateAndStatusNode)
|
||||
videoNode.canAttachContent = strongSelf.shouldAcquireVideoContext
|
||||
}), content: NativeVideoContent(id: .message(item.message.id, item.message.stableId, telegramFile.fileId), fileReference: .message(message: MessageReference(item.message), media: telegramFile), streamVideo: false, enableSound: false), priority: .embedded, autoplay: true)
|
||||
let previousVideoNode = strongSelf.videoNode
|
||||
strongSelf.videoNode = videoNode
|
||||
strongSelf.insertSubnode(videoNode, belowSubnode: previousVideoNode ?? strongSelf.dateAndStatusNode)
|
||||
videoNode.canAttachContent = strongSelf.shouldAcquireVideoContext
|
||||
|
||||
if isSecretMedia {
|
||||
let updatedSecretPlaceholderSignal = chatSecretMessageVideo(account: item.account, videoReference: .message(message: MessageReference(item.message), media: telegramFile))
|
||||
strongSelf.secretVideoPlaceholder.setSignal(updatedSecretPlaceholderSignal)
|
||||
if strongSelf.secretVideoPlaceholder.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.secretVideoPlaceholderBackground, belowSubnode: videoNode)
|
||||
strongSelf.insertSubnode(strongSelf.secretVideoPlaceholder, belowSubnode: videoNode)
|
||||
if isSecretMedia {
|
||||
let updatedSecretPlaceholderSignal = chatSecretMessageVideo(account: item.account, videoReference: .message(message: MessageReference(item.message), media: telegramFile))
|
||||
strongSelf.secretVideoPlaceholder.setSignal(updatedSecretPlaceholderSignal)
|
||||
if strongSelf.secretVideoPlaceholder.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.secretVideoPlaceholderBackground, belowSubnode: videoNode)
|
||||
strongSelf.insertSubnode(strongSelf.secretVideoPlaceholder, belowSubnode: videoNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
strongSelf.secretVideoPlaceholder.removeFromSupernode()
|
||||
@ -548,7 +550,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
|
||||
if let item = self.item, let videoNode = self.videoNode, videoNode.frame.contains(location) {
|
||||
if let _ = self.item, let videoNode = self.videoNode, videoNode.frame.contains(location) {
|
||||
self.activateVideoPlayback()
|
||||
return
|
||||
}
|
||||
@ -572,7 +574,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
return
|
||||
}
|
||||
if self.infoBackgroundNode.alpha.isZero {
|
||||
item.account.telegramApplicationContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: .voice)
|
||||
item.account.telegramApplicationContext.mediaManager?.playlistControl(.playback(.togglePlayPause), type: .voice)
|
||||
} else {
|
||||
let _ = item.controllerInteraction.openMessage(item.message)
|
||||
}
|
||||
|
||||
@ -384,9 +384,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode {
|
||||
strongSelf.videoNode = nil
|
||||
}
|
||||
|
||||
if replaceVideoNode, let updatedVideoFile = updateVideoFile {
|
||||
if replaceVideoNode, let updatedVideoFile = updateVideoFile, let mediaManager = account.telegramApplicationContext.mediaManager {
|
||||
let cornerRadius: CGFloat = arguments.corners.topLeft.radius
|
||||
let videoNode = UniversalVideoNode(postbox: account.postbox, audioSession: account.telegramApplicationContext.mediaManager.audioSession, manager: account.telegramApplicationContext.mediaManager.universalVideoManager, decoration: ChatBubbleVideoDecoration(cornerRadius: cornerRadius, nativeSize: nativeSize), content: NativeVideoContent(id: .message(message.id, message.stableId, updatedVideoFile.fileId), fileReference: .message(message: MessageReference(message), media: updatedVideoFile), enableSound: false, fetchAutomatically: false), priority: .embedded)
|
||||
let videoNode = UniversalVideoNode(postbox: account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: ChatBubbleVideoDecoration(cornerRadius: cornerRadius, nativeSize: nativeSize), content: NativeVideoContent(id: .message(message.id, message.stableId, updatedVideoFile.fileId), fileReference: .message(message: MessageReference(message), media: updatedVideoFile), enableSound: false, fetchAutomatically: false), priority: .embedded)
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
|
||||
strongSelf.videoNode = videoNode
|
||||
|
||||
@ -168,7 +168,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
var cutout: TextNodeCutout?
|
||||
if let statusSize = statusSize {
|
||||
cutout = TextNodeCutout(position: .BottomRight, size: statusSize)
|
||||
cutout = TextNodeCutout(bottomRight: statusSize)
|
||||
}
|
||||
|
||||
let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: cutout, insets: UIEdgeInsets()))
|
||||
@ -178,16 +178,14 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
|
||||
var statusFrame: CGRect?
|
||||
if let statusSize = statusSize {
|
||||
var frame = CGRect(origin: CGPoint(), size: statusSize)
|
||||
var frame = CGRect(origin: CGPoint(x: textFrame.maxX - statusSize.width, y: textFrame.maxY - statusSize.height), size: statusSize)
|
||||
|
||||
let trailingLineWidth = textLayout.trailingLineWidth
|
||||
/*let trailingLineWidth = textLayout.trailingLineWidth
|
||||
if textSize.width - trailingLineWidth >= statusSize.width {
|
||||
frame.origin = CGPoint(x: textFrame.maxX - statusSize.width, y: textFrame.maxY - statusSize.height)
|
||||
} else if trailingLineWidth + statusSize.width < textConstrainedSize.width {
|
||||
frame.origin = CGPoint(x: textFrame.minX + trailingLineWidth, y: textFrame.maxY - statusSize.height)
|
||||
} else {
|
||||
frame.origin = CGPoint(x: textFrame.maxX - statusSize.width, y: textFrame.maxY)
|
||||
}
|
||||
}*/
|
||||
statusFrame = frame
|
||||
}
|
||||
|
||||
|
||||
@ -397,27 +397,30 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
|
||||
self.historyDisposable = appliedTransition.start()
|
||||
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(self.account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
for id in ids {
|
||||
if case let .chat(messageId, media) = id {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
|
||||
if let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
for id in ids {
|
||||
if case let .chat(messageId, media) = id {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if controllerInteraction.hiddenMedia != messageIdAndMedia {
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
strongSelf.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
|
||||
//if controllerInteraction.hiddenMedia != messageIdAndMedia {
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
strongSelf.listNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? ChatMessageItemView {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}))
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
||||
@ -109,8 +109,8 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
||||
if self.mediaPlayer != nil {
|
||||
self.mediaPlayer?.pause()
|
||||
}
|
||||
if let account = self.account {
|
||||
let mediaPlayer = MediaPlayer(audioSessionManager: account.telegramApplicationContext.mediaManager.audioSession, postbox: account.postbox, resourceReference: .standalone(resource: recordedMediaPreview.resource), streamable: false, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true)
|
||||
if let account = self.account, let mediaManager = account.telegramApplicationContext.mediaManager {
|
||||
let mediaPlayer = MediaPlayer(audioSessionManager: mediaManager.audioSession, postbox: account.postbox, resourceReference: .standalone(resource: recordedMediaPreview.resource), streamable: false, video: false, preferSoftwareDecoding: false, enableSound: true, fetchAutomatically: true)
|
||||
self.mediaPlayer = mediaPlayer
|
||||
self.durationLabel.defaultDuration = Double(recordedMediaPreview.duration)
|
||||
self.durationLabel.status = mediaPlayer.status
|
||||
|
||||
@ -4,7 +4,7 @@ import AsyncDisplayKit
|
||||
|
||||
final class ChatRequestInProgressTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let titleNode: ASTextNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
|
||||
private var theme: PresentationTheme?
|
||||
private var strings: PresentationStrings?
|
||||
@ -13,7 +13,7 @@ final class ChatRequestInProgressTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.isLayerBacked = true
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
|
||||
super.init()
|
||||
@ -38,7 +38,7 @@ final class ChatRequestInProgressTitlePanelNode: ChatTitleAccessoryPanelNode {
|
||||
|
||||
let panelHeight: CGFloat = 40.0
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: width - leftInset - rightInset, height: 100.0))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: width - leftInset - rightInset, height: 100.0))
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: floor((panelHeight - titleSize.height) / 2.0)), size: titleSize))
|
||||
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelHeight - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel)))
|
||||
|
||||
@ -14,7 +14,7 @@ enum ChatTitleContent {
|
||||
private final class ChatTitleNetworkStatusNode: ASDisplayNode {
|
||||
private var theme: PresentationTheme
|
||||
|
||||
private let titleNode: ASTextNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let activityIndicator: ActivityIndicator
|
||||
|
||||
var title: String = "" {
|
||||
@ -28,11 +28,10 @@ private final class ChatTitleNetworkStatusNode: ASDisplayNode {
|
||||
init(theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.isLayerBacked = true
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
self.titleNode.isOpaque = false
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
|
||||
@ -57,7 +56,7 @@ private final class ChatTitleNetworkStatusNode: ASDisplayNode {
|
||||
let indicatorSize = self.activityIndicator.bounds.size
|
||||
let indicatorPadding = indicatorSize.width + 6.0
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: max(1.0, size.width - indicatorPadding), height: size.height))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: max(1.0, size.width - indicatorPadding), height: size.height))
|
||||
let combinedHeight = titleSize.height
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: indicatorPadding + floor((size.width - titleSize.width - indicatorPadding) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
|
||||
@ -81,11 +80,11 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
private var dateTimeFormat: PresentationDateTimeFormat
|
||||
|
||||
private let contentContainer: ASDisplayNode
|
||||
private let titleNode: ASTextNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let titleLeftIconNode: ASImageNode
|
||||
private let titleRightIconNode: ASImageNode
|
||||
private let infoNode: ASTextNode
|
||||
private let typingNode: ASTextNode
|
||||
private let infoNode: ImmediateTextNode
|
||||
private let typingNode: ImmediateTextNode
|
||||
private var typingIndicator: TGModernConversationTitleActivityIndicator?
|
||||
private let button: HighlightTrackingButtonNode
|
||||
|
||||
@ -428,10 +427,9 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
|
||||
self.contentContainer = ASDisplayNode()
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
self.titleNode.isOpaque = false
|
||||
|
||||
self.titleLeftIconNode = ASImageNode()
|
||||
@ -444,16 +442,14 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
self.titleRightIconNode.displayWithoutProcessing = true
|
||||
self.titleRightIconNode.displaysAsynchronously = false
|
||||
|
||||
self.infoNode = ASTextNode()
|
||||
self.infoNode = ImmediateTextNode()
|
||||
self.infoNode.displaysAsynchronously = false
|
||||
self.infoNode.maximumNumberOfLines = 1
|
||||
self.infoNode.truncationMode = .byTruncatingTail
|
||||
self.infoNode.isOpaque = false
|
||||
|
||||
self.typingNode = ASTextNode()
|
||||
self.typingNode = ImmediateTextNode()
|
||||
self.typingNode.displaysAsynchronously = false
|
||||
self.typingNode.maximumNumberOfLines = 1
|
||||
self.typingNode.truncationMode = .byTruncatingTail
|
||||
self.typingNode.isOpaque = false
|
||||
|
||||
self.button = HighlightTrackingButtonNode()
|
||||
@ -548,9 +544,9 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
}
|
||||
|
||||
if size.height > 40.0 {
|
||||
let titleSize = self.titleNode.measure(CGSize(width: clearBounds.width - leftIconWidth - rightIconWidth, height: size.height))
|
||||
let infoSize = self.infoNode.measure(clearBounds.size)
|
||||
let typingSize = self.typingNode.measure(clearBounds.size)
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: clearBounds.width - leftIconWidth - rightIconWidth, height: size.height))
|
||||
let infoSize = self.infoNode.updateLayout(clearBounds.size)
|
||||
let typingSize = self.typingNode.updateLayout(clearBounds.size)
|
||||
let titleInfoSpacing: CGFloat = 0.0
|
||||
|
||||
var titleFrame: CGRect
|
||||
@ -590,9 +586,9 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 3.0, y: titleFrame.minY + 7.0), size: image.size)
|
||||
}
|
||||
} else {
|
||||
let titleSize = self.titleNode.measure(CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - rightIconWidth), height: size.height))
|
||||
let infoSize = self.infoNode.measure(CGSize(width: floor(clearBounds.width / 2.0), height: size.height))
|
||||
let typingSize = self.typingNode.measure(CGSize(width: floor(clearBounds.width / 2.0), height: size.height))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - rightIconWidth), height: size.height))
|
||||
let infoSize = self.infoNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height))
|
||||
let typingSize = self.typingNode.updateLayout(CGSize(width: floor(clearBounds.width / 2.0), height: size.height))
|
||||
|
||||
let titleInfoSpacing: CGFloat = 8.0
|
||||
let combinedWidth = titleSize.width + leftIconWidth + rightIconWidth + infoSize.width + titleInfoSpacing
|
||||
|
||||
@ -222,6 +222,142 @@ private final class DeviceContactDataModernContext: DeviceContactDataContext {
|
||||
}
|
||||
}
|
||||
|
||||
private func withAddressBook(_ f: (ABAddressBook) -> Void) {
|
||||
let addressBookRef = ABAddressBookCreateWithOptions(nil, nil)
|
||||
|
||||
if let addressBook = addressBookRef?.takeRetainedValue() {
|
||||
f(addressBook)
|
||||
}
|
||||
}
|
||||
|
||||
private final class DeviceContactDataLegacyContext: DeviceContactDataContext {
|
||||
var currentContacts: [DeviceContactStableId: DeviceContactBasicData] = [:]
|
||||
|
||||
init(queue: Queue, updated: @escaping ([DeviceContactStableId: DeviceContactBasicData]) -> Void) {
|
||||
self.currentContacts = self.retrieveContacts()
|
||||
updated(self.currentContacts)
|
||||
/*let handle = NotificationCenter.default.addObserver(forName: NSNotification.Name.CNContactStoreDidChange, object: nil, queue: nil, using: { [weak self] _ in
|
||||
queue.async {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let contacts = strongSelf.retrieveContacts()
|
||||
if strongSelf.currentContacts != contacts {
|
||||
strongSelf.currentContacts = contacts
|
||||
updated(strongSelf.currentContacts)
|
||||
}
|
||||
}
|
||||
})*/
|
||||
//self.updateHandle = handle
|
||||
}
|
||||
|
||||
deinit {
|
||||
/*if let updateHandle = updateHandle {
|
||||
NotificationCenter.default.removeObserver(updateHandle)
|
||||
}*/
|
||||
}
|
||||
|
||||
private func retrieveContacts() -> [DeviceContactStableId: DeviceContactBasicData] {
|
||||
var result: [DeviceContactStableId: DeviceContactBasicData] = [:]
|
||||
withAddressBook { addressBook in
|
||||
guard let peopleRef = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() else {
|
||||
return
|
||||
}
|
||||
|
||||
for recordRef in peopleRef as NSArray {
|
||||
let record = recordRef as ABRecord
|
||||
let (stableId, basicData) = DeviceContactDataLegacyContext.parseContact(record)
|
||||
result[stableId] = basicData
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private func getContactById(stableId: String) -> ABRecord? {
|
||||
let recordId: ABRecordID
|
||||
if stableId.hasPrefix("ab-"), let idValue = Int(String(stableId[stableId.index(stableId.startIndex, offsetBy: 3)])) {
|
||||
recordId = Int32(clamping: idValue)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result: ABRecord?
|
||||
withAddressBook { addressBook in
|
||||
result = ABAddressBookGetPersonWithRecordID(addressBook, recordId)?.takeUnretainedValue()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private static func parseContact(_ contact: ABRecord) -> (DeviceContactStableId, DeviceContactBasicData) {
|
||||
let stableId = "ab-\(ABRecordGetRecordID(contact))"
|
||||
var firstName = ""
|
||||
var lastName = ""
|
||||
if let value = ABRecordCopyValue(contact, kABPersonFirstNameProperty)?.takeRetainedValue() {
|
||||
firstName = value as! CFString as String
|
||||
}
|
||||
if let value = ABRecordCopyValue(contact, kABPersonLastNameProperty)?.takeRetainedValue() {
|
||||
lastName = value as! CFString as String
|
||||
}
|
||||
|
||||
var phoneNumbers: [DeviceContactPhoneNumberData] = []
|
||||
if let value = ABRecordCopyValue(contact, kABPersonPhoneProperty)?.takeRetainedValue() {
|
||||
let phones = value as ABMultiValue
|
||||
let count = ABMultiValueGetCount(phones)
|
||||
for i in 0 ..< count {
|
||||
if let phoneRef = ABMultiValueCopyValueAtIndex(phones, i)?.takeRetainedValue() {
|
||||
let phone = phoneRef as! CFString as String
|
||||
var label = ""
|
||||
if let labelRef = ABMultiValueCopyLabelAtIndex(phones, i)?.takeRetainedValue() {
|
||||
label = labelRef as String
|
||||
}
|
||||
phoneNumbers.append(DeviceContactPhoneNumberData(label: label, value: phone))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (stableId, DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: phoneNumbers))
|
||||
}
|
||||
|
||||
func getExtendedContactData(stableId: DeviceContactStableId) -> DeviceContactExtendedData? {
|
||||
if let contact = self.getContactById(stableId: stableId) {
|
||||
let basicData = DeviceContactDataLegacyContext.parseContact(contact).1
|
||||
return DeviceContactExtendedData(basicData: basicData, middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [])
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func appendContactData(_ contactData: DeviceContactExtendedData, to stableId: DeviceContactStableId) -> DeviceContactExtendedData? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createContactWithData(_ contactData: DeviceContactExtendedData) -> (DeviceContactStableId, DeviceContactExtendedData)? {
|
||||
var result: (DeviceContactStableId, DeviceContactExtendedData)?
|
||||
withAddressBook { addressBook in
|
||||
let contact = ABPersonCreate()?.takeRetainedValue()
|
||||
ABRecordSetValue(contact, kABPersonFirstNameProperty, contactData.basicData.firstName as CFString, nil)
|
||||
ABRecordSetValue(contact, kABPersonLastNameProperty, contactData.basicData.lastName as CFString, nil)
|
||||
|
||||
let phones = ABMultiValueCreateMutable(ABPropertyType(kABMultiStringPropertyType))?.takeRetainedValue()
|
||||
for phone in contactData.basicData.phoneNumbers {
|
||||
ABMultiValueAddValueAndLabel(phones, phone.value as CFString, phone.label as CFString, nil)
|
||||
}
|
||||
ABRecordSetValue(contact, kABPersonPhoneProperty, phones, nil)
|
||||
|
||||
if ABAddressBookAddRecord(addressBook, contact, nil) {
|
||||
ABAddressBookSave(addressBook, nil)
|
||||
|
||||
let stableId = "ab-\(ABRecordGetRecordID(contact))"
|
||||
if let contact = self.getContactById(stableId: stableId) {
|
||||
let parsedContact = DeviceContactDataLegacyContext.parseContact(contact).1
|
||||
result = (stableId, DeviceContactExtendedData(basicData: parsedContact, middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: []))
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
private final class ExtendedContactDataContext {
|
||||
var value: DeviceContactExtendedData?
|
||||
let subscribers = Bag<(DeviceContactExtendedData) -> Void>()
|
||||
@ -273,8 +409,20 @@ private final class DeviceContactDataManagerImpl {
|
||||
strongSelf.updateAll(stableIdToBasicContactData)
|
||||
})
|
||||
} else {
|
||||
|
||||
strongSelf.dataContext = DeviceContactDataLegacyContext(queue: strongSelf.queue, updated: { stableIdToBasicContactData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.updateAll(stableIdToBasicContactData)
|
||||
})
|
||||
}
|
||||
|
||||
/*strongSelf.dataContext = DeviceContactDataLegacyContext(queue: strongSelf.queue, updated: { stableIdToBasicContactData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.updateAll(stableIdToBasicContactData)
|
||||
})*/
|
||||
} else {
|
||||
strongSelf.updateAll([:])
|
||||
}
|
||||
|
||||
103
TelegramUI/DocumentPreviewController.swift
Normal file
103
TelegramUI/DocumentPreviewController.swift
Normal file
@ -0,0 +1,103 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import QuickLook
|
||||
import Display
|
||||
|
||||
private final class DocumentPreviewItem: NSObject, QLPreviewItem {
|
||||
private let url: URL
|
||||
private let title: String
|
||||
|
||||
var previewItemURL: URL? {
|
||||
return self.url
|
||||
}
|
||||
|
||||
var previewItemTitle: String? {
|
||||
return self.title
|
||||
}
|
||||
|
||||
init(url: URL, title: String) {
|
||||
self.url = url
|
||||
self.title = title
|
||||
}
|
||||
}
|
||||
|
||||
final class DocumentPreviewController: UINavigationController, QLPreviewControllerDelegate, QLPreviewControllerDataSource {
|
||||
private let postbox: Postbox
|
||||
private let file: TelegramMediaFile
|
||||
|
||||
private var item: DocumentPreviewItem?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, postbox: Postbox, file: TelegramMediaFile) {
|
||||
self.postbox = postbox
|
||||
self.file = file
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
self.navigationBar.barTintColor = theme.rootController.navigationBar.backgroundColor
|
||||
self.navigationBar.tintColor = theme.rootController.navigationBar.accentTextColor
|
||||
self.navigationBar.shadowImage = generateImage(CGSize(width: 1.0, height: 1.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(theme.rootController.navigationBar.separatorColor.cgColor)
|
||||
context.fill(CGRect(origin: CGPoint(), size: CGSize(width: 1.0, height: UIScreenPixel)))
|
||||
})
|
||||
self.navigationBar.isTranslucent = false
|
||||
self.navigationBar.titleTextAttributes = [NSAttributedStringKey.font: Font.semibold(17.0), NSAttributedStringKey.foregroundColor: theme.rootController.navigationBar.primaryTextColor]
|
||||
|
||||
let controller = QLPreviewController(nibName: nil, bundle: nil)
|
||||
controller.navigation_setDismiss({ [weak self] in
|
||||
//self?.cancelPressed()
|
||||
}, rootController: self)
|
||||
controller.delegate = self
|
||||
controller.dataSource = self
|
||||
controller.navigationItem.setLeftBarButton(UIBarButtonItem(title: strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false)
|
||||
self.setViewControllers([controller], animated: false)
|
||||
|
||||
var pathExtension: String?
|
||||
if let fileName = self.file.fileName {
|
||||
let pathExtensionCandidate = (fileName as NSString).pathExtension
|
||||
if !pathExtensionCandidate.isEmpty {
|
||||
pathExtension = pathExtensionCandidate
|
||||
}
|
||||
}
|
||||
|
||||
if let path = self.postbox.mediaBox.completedResourcePath(self.file.resource, pathExtension: pathExtension) {
|
||||
self.item = DocumentPreviewItem(url: URL(fileURLWithPath: path), title: self.file.fileName ?? strings.Message_File)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func cancelPressed() {
|
||||
self.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
|
||||
if self.item != nil {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
|
||||
if let item = self.item {
|
||||
return item
|
||||
} else {
|
||||
assertionFailure()
|
||||
return DocumentPreviewItem(url: URL(fileURLWithPath: ""), title: "")
|
||||
}
|
||||
}
|
||||
|
||||
func previewControllerWillDismiss(_ controller: QLPreviewController) {
|
||||
self.cancelPressed()
|
||||
}
|
||||
|
||||
func previewControllerDidDismiss(_ controller: QLPreviewController) {
|
||||
//self.cancelPressed()
|
||||
}
|
||||
}
|
||||
@ -10,8 +10,8 @@ final class EditAccessoryPanelNode: AccessoryPanelNode {
|
||||
|
||||
let closeButton: ASButtonNode
|
||||
let lineNode: ASImageNode
|
||||
let titleNode: ASTextNode
|
||||
let textNode: ASTextNode
|
||||
let titleNode: ImmediateTextNode
|
||||
let textNode: ImmediateTextNode
|
||||
let imageNode: TransformImageNode
|
||||
|
||||
private let activityIndicator: ActivityIndicator
|
||||
@ -68,13 +68,11 @@ final class EditAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.lineNode.displaysAsynchronously = false
|
||||
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.truncationMode = .byTruncatingTail
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.maximumNumberOfLines = 1
|
||||
self.textNode.displaysAsynchronously = false
|
||||
self.textNode.isUserInteractionEnabled = true
|
||||
@ -308,10 +306,10 @@ final class EditAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
self.imageNode.frame = CGRect(origin: CGPoint(x: leftInset + 9.0, y: 8.0), size: CGSize(width: 35.0, height: 35.0))
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset + imageTextInset, y: 7.0), size: titleSize)
|
||||
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset + imageTextInset, y: 25.0), size: textSize)
|
||||
|
||||
self.tapNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: bounds.width - leftInset - rightInset - closeButtonSize.width - 4.0, height: bounds.height))
|
||||
|
||||
@ -19,10 +19,14 @@ private func internalMessageFileMediaPlaybackStatus(account: Account, file: Tele
|
||||
}
|
||||
|
||||
if let (playlistId, itemId) = peerMessagesMediaPlaylistAndItemId(message, isRecentActions: isRecentActions) {
|
||||
return account.telegramApplicationContext.mediaManager.filteredPlaylistState(playlistId: playlistId, itemId: itemId, type: playerType)
|
||||
if let mediaManager = account.telegramApplicationContext.mediaManager {
|
||||
return mediaManager.filteredPlaylistState(playlistId: playlistId, itemId: itemId, type: playerType)
|
||||
|> mapToSignal { state -> Signal<MediaPlayerStatus?, NoError> in
|
||||
return .single(state?.status)
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
@ -64,8 +64,8 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
|
||||
let closeButton: ASButtonNode
|
||||
let lineNode: ASImageNode
|
||||
let titleNode: ASTextNode
|
||||
let textNode: ASTextNode
|
||||
let titleNode: ImmediateTextNode
|
||||
let textNode: ImmediateTextNode
|
||||
|
||||
var theme: PresentationTheme
|
||||
|
||||
@ -83,13 +83,11 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.lineNode.displaysAsynchronously = false
|
||||
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.truncationMode = .byTruncatingTail
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.maximumNumberOfLines = 1
|
||||
self.textNode.displaysAsynchronously = false
|
||||
|
||||
@ -174,10 +172,10 @@ final class ForwardAccessoryPanelNode: AccessoryPanelNode {
|
||||
|
||||
self.lineNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 8.0), size: CGSize(width: 2.0, height: bounds.size.height - 10.0))
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 7.0), size: titleSize)
|
||||
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset, y: 25.0), size: textSize)
|
||||
}
|
||||
|
||||
|
||||
@ -72,26 +72,9 @@ private func mediaForMessage(message: Message) -> Media? {
|
||||
}
|
||||
|
||||
private let internalExtensions = Set<String>([
|
||||
"txt",
|
||||
"doc",
|
||||
"docx",
|
||||
"xls",
|
||||
"xlsx",
|
||||
"ppt",
|
||||
"pptx",
|
||||
"php",
|
||||
"cpp",
|
||||
"h",
|
||||
"swift",
|
||||
"m",
|
||||
"mm",
|
||||
"java",
|
||||
"jpg",
|
||||
"png",
|
||||
"jpeg",
|
||||
"json",
|
||||
"rs",
|
||||
"cs"
|
||||
"jpeg"
|
||||
])
|
||||
|
||||
private let internalNotSupportedExtensions = Set<String>([
|
||||
@ -99,17 +82,12 @@ private let internalNotSupportedExtensions = Set<String>([
|
||||
])
|
||||
|
||||
private let internalMimeTypes = Set<String>([
|
||||
"application/pdf",
|
||||
"application/postscript",
|
||||
"application/text"
|
||||
])
|
||||
|
||||
private let internalMimePrefixes: [String] = [
|
||||
"image/jpeg",
|
||||
"image/jpg",
|
||||
"image/png",
|
||||
"text/",
|
||||
"application/vnd.ms-"
|
||||
"image/png"
|
||||
]
|
||||
|
||||
private let supportedVideoMimeTypes = Set<String>([
|
||||
@ -455,13 +433,15 @@ class GalleryController: ViewController {
|
||||
}
|
||||
}))
|
||||
|
||||
self.hiddenMediaManagerIndex = account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.addSource(self._hiddenMedia.get() |> map { messageIdAndMedia in
|
||||
if let (messageId, media) = messageIdAndMedia {
|
||||
return .chat(messageId, media)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
if let mediaManager = account.telegramApplicationContext.mediaManager {
|
||||
self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(self._hiddenMedia.get() |> map { messageIdAndMedia in
|
||||
if let (messageId, media) = messageIdAndMedia {
|
||||
return .chat(messageId, media)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
@ -471,8 +451,8 @@ class GalleryController: ViewController {
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
self.centralItemAttributesDisposable.dispose()
|
||||
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex {
|
||||
self.account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex, let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -347,10 +347,6 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if let applicationContext = item.account.applicationContext as? TelegramApplicationContext {
|
||||
strongSelf.videoNode.acquireContext(account: item.account, mediaManager: applicationContext.mediaManager, id: ChatContextResultManagedMediaId(result: item.result), resource: videoResource, priority: 1)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -130,7 +130,7 @@ final class InstantPageAudioNode: ASDisplayNode, InstantPageNode {
|
||||
self.scrubbingNode.seek = { [weak self] timestamp in
|
||||
if let strongSelf = self {
|
||||
if let _ = strongSelf.playbackState {
|
||||
strongSelf.account.telegramApplicationContext.mediaManager.playlistControl(.seek(timestamp), type: strongSelf.playlistType)
|
||||
strongSelf.account.telegramApplicationContext.mediaManager?.playlistControl(.seek(timestamp), type: strongSelf.playlistType)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,12 +174,12 @@ final class InstantPageAudioNode: ASDisplayNode, InstantPageNode {
|
||||
}
|
||||
})*/
|
||||
|
||||
self.scrubbingNode.status = account.telegramApplicationContext.mediaManager.filteredPlaylistState(playlistId: InstantPageMediaPlaylistId(webpageId: webPage.webpageId), itemId: InstantPageMediaPlaylistItemId(index: self.media.index), type: self.playlistType)
|
||||
self.scrubbingNode.status = account.telegramApplicationContext.mediaManager!.filteredPlaylistState(playlistId: InstantPageMediaPlaylistId(webpageId: webPage.webpageId), itemId: InstantPageMediaPlaylistItemId(index: self.media.index), type: self.playlistType)
|
||||
|> map { playbackState -> MediaPlayerStatus in
|
||||
return playbackState?.status ?? MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .paused)
|
||||
}
|
||||
|
||||
self.playerStatusDisposable = (account.telegramApplicationContext.mediaManager.filteredPlaylistState(playlistId: InstantPageMediaPlaylistId(webpageId: webPage.webpageId), itemId: InstantPageMediaPlaylistItemId(index: self.media.index), type: playlistType)
|
||||
self.playerStatusDisposable = (account.telegramApplicationContext.mediaManager!.filteredPlaylistState(playlistId: InstantPageMediaPlaylistId(webpageId: webPage.webpageId), itemId: InstantPageMediaPlaylistItemId(index: self.media.index), type: playlistType)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] playbackState in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -246,7 +246,7 @@ final class InstantPageAudioNode: ASDisplayNode, InstantPageNode {
|
||||
|
||||
@objc func buttonPressed() {
|
||||
if let _ = self.playbackState {
|
||||
self.account.telegramApplicationContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: self.playlistType)
|
||||
self.account.telegramApplicationContext.mediaManager?.playlistControl(.playback(.togglePlayPause), type: self.playlistType)
|
||||
} else {
|
||||
self.openMedia(self.media)
|
||||
}
|
||||
|
||||
@ -783,7 +783,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.account.telegramApplicationContext.mediaManager.setPlaylist(InstantPageMediaPlaylist(webPage: webPage, items: medias, initialItemIndex: initialIndex), type: file.isVoice ? .voice : .music)
|
||||
self.account.telegramApplicationContext.mediaManager?.setPlaylist(InstantPageMediaPlaylist(webPage: webPage, items: medias, initialItemIndex: initialIndex), type: file.isVoice ? .voice : .music)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ final class InstantPagePlayableVideoNode: ASDisplayNode, InstantPageNode {
|
||||
self.interactive = interactive
|
||||
self.openMedia = openMedia
|
||||
|
||||
self.videoNode = UniversalVideoNode(postbox: account.postbox, audioSession: account.telegramApplicationContext.mediaManager.audioSession, manager: account.telegramApplicationContext.mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: NativeVideoContent(id: .instantPage(webPage.webpageId, media.media.id!), fileReference: .webPage(webPage: WebpageReference(webPage), media: media.media as! TelegramMediaFile), loopVideo: true, enableSound: false, fetchAutomatically: true), priority: .embedded, autoplay: true)
|
||||
self.videoNode = UniversalVideoNode(postbox: account.postbox, audioSession: account.telegramApplicationContext.mediaManager!.audioSession, manager: account.telegramApplicationContext.mediaManager!.universalVideoManager, decoration: GalleryVideoDecoration(), content: NativeVideoContent(id: .instantPage(webPage.webpageId, media.media.id!), fileReference: .webPage(webPage: WebpageReference(webPage), media: media.media as! TelegramMediaFile), loopVideo: true, enableSound: false, fetchAutomatically: true), priority: .embedded, autoplay: true)
|
||||
|
||||
super.init()
|
||||
|
||||
|
||||
@ -96,7 +96,7 @@ class ItemListActivityTextItemNode: ListViewItemNode {
|
||||
titleString.addAttributes([NSAttributedStringKey.font: titleFont], range: NSMakeRange(0, titleString.length))
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - 22.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: TextNodeCutout(position: .TopLeft, size: CGSize(width: activityWidth, height: 4.0)), insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - 22.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: TextNodeCutout(topLeft: CGSize(width: activityWidth, height: 4.0)), insets: UIEdgeInsets()))
|
||||
|
||||
let contentSize: CGSize
|
||||
let insets: UIEdgeInsets
|
||||
|
||||
@ -777,7 +777,7 @@ final class ListMessageFileItemNode: ListMessageNode {
|
||||
}
|
||||
case .playbackStatus:
|
||||
if let account = self.account, let applicationContext = account.applicationContext as? TelegramApplicationContext {
|
||||
applicationContext.mediaManager.playlistControl(.playback(.togglePlayPause))
|
||||
applicationContext.mediaManager?.playlistControl(.playback(.togglePlayPause))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ final class ListMessageSnippetItemNode: ListMessageNode {
|
||||
|
||||
let (descriptionNodeLayout, descriptionNodeApply) = descriptionNodeMakeLayout(TextNodeLayoutArguments(attributedString: descriptionText, backgroundColor: nil, maximumNumberOfLines: 3, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - params.rightInset - 12.0, height: CGFloat.infinity), alignment: .natural, lineSpacing: 0.3, cutout: nil, insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)))
|
||||
|
||||
let (linkNodeLayout, linkNodeApply) = linkNodeMakeLayout(TextNodeLayoutArguments(attributedString: linkText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - params.rightInset - 12.0, height: CGFloat.infinity), alignment: .natural, lineSpacing: 0.3, cutout: isInstantView ? TextNodeCutout(position: .TopLeft, size: CGSize(width: 14.0, height: 8.0)) : nil, insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)))
|
||||
let (linkNodeLayout, linkNodeApply) = linkNodeMakeLayout(TextNodeLayoutArguments(attributedString: linkText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - params.rightInset - 12.0, height: CGFloat.infinity), alignment: .natural, lineSpacing: 0.3, cutout: isInstantView ? TextNodeCutout(topLeft: CGSize(width: 14.0, height: 8.0)) : nil, insets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0)))
|
||||
var instantViewImage: UIImage?
|
||||
if isInstantView {
|
||||
instantViewImage = PresentationResourcesChat.sharedMediaInstantViewIcon(item.theme)
|
||||
|
||||
@ -625,7 +625,6 @@ public final class ManagedAudioSession {
|
||||
case .builtin:
|
||||
resetToBuiltin = true
|
||||
case .speaker:
|
||||
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
|
||||
if type == .voiceCall {
|
||||
if let routes = AVAudioSession.sharedInstance().availableInputs {
|
||||
for route in routes {
|
||||
@ -636,6 +635,7 @@ public final class ManagedAudioSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
try AVAudioSession.sharedInstance().overrideOutputAudioPort(.speaker)
|
||||
case .headphones:
|
||||
break
|
||||
case let .port(port):
|
||||
|
||||
@ -131,7 +131,8 @@ public final class MediaManager: NSObject {
|
||||
|
||||
super.init()
|
||||
|
||||
let combinedPlayersSignal: Signal<(SharedMediaPlayerItemPlaybackState, MediaManagerPlayerType)?, NoError> = combineLatest(self.voiceMediaPlayerState, self.musicMediaPlayerState) |> map { voice, music -> (SharedMediaPlayerItemPlaybackState, MediaManagerPlayerType)? in
|
||||
let combinedPlayersSignal: Signal<(SharedMediaPlayerItemPlaybackState, MediaManagerPlayerType)?, NoError> = combineLatest(queue: Queue.mainQueue(), self.voiceMediaPlayerState, self.musicMediaPlayerState)
|
||||
|> map { voice, music -> (SharedMediaPlayerItemPlaybackState, MediaManagerPlayerType)? in
|
||||
if let voice = voice {
|
||||
return (voice, .voice)
|
||||
} else if let music = music {
|
||||
@ -339,7 +340,7 @@ public final class MediaManager: NSObject {
|
||||
}))
|
||||
|
||||
|
||||
let shouldKeepAudioSession: Signal<Bool, NoError> = combineLatest(self.globalMediaPlayerState |> deliverOnMainQueue, inForeground |> deliverOnMainQueue)
|
||||
let shouldKeepAudioSession: Signal<Bool, NoError> = combineLatest(queue: Queue.mainQueue(), self.globalMediaPlayerState, inForeground)
|
||||
|> map { stateAndType, inForeground -> Bool in
|
||||
var isPlaying = false
|
||||
if let (state, _) = stateAndType {
|
||||
|
||||
@ -216,7 +216,7 @@ private func playSound(account: Account, sound: PeerMessageSound, defaultSound:
|
||||
return Signal { subscriber in
|
||||
var currentPlayer: AudioPlayerWrapper?
|
||||
var deactivateImpl: (() -> Void)?
|
||||
let session = account.telegramApplicationContext.mediaManager.audioSession.push(audioSessionType: .play, activate: { _ in
|
||||
let session = account.telegramApplicationContext.mediaManager?.audioSession.push(audioSessionType: .play, activate: { _ in
|
||||
if let url = Bundle.main.url(forResource: fileNameForNotificationSound(sound, defaultSound: defaultSound), withExtension: "m4a") {
|
||||
currentPlayer = AudioPlayerWrapper(url: url, completed: {
|
||||
deactivateImpl?()
|
||||
@ -230,10 +230,10 @@ private func playSound(account: Account, sound: PeerMessageSound, defaultSound:
|
||||
return .complete()
|
||||
})
|
||||
deactivateImpl = {
|
||||
session.dispose()
|
||||
session?.dispose()
|
||||
}
|
||||
return ActionDisposable {
|
||||
session.dispose()
|
||||
session?.dispose()
|
||||
currentPlayer?.stop()
|
||||
currentPlayer = nil
|
||||
}
|
||||
|
||||
@ -217,8 +217,10 @@ func openChatMessage(account: Account, message: Message, standalone: Bool, rever
|
||||
dismissInput()
|
||||
present(controller, nil)
|
||||
return true
|
||||
case .document:
|
||||
present(ShareController(account: account, subject: .messages([message]), showInChat: nil, externalShare: true, immediateExternalShare: true), nil)
|
||||
case let .document(file):
|
||||
let presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
|
||||
navigationController?.view.window?.rootViewController?.present(DocumentPreviewController(theme: presentationData.theme, strings: presentationData.strings, postbox: account.postbox, file: file), animated: true, completion: nil)
|
||||
//present(ShareController(account: account, subject: .messages([message]), showInChat: nil, externalShare: true, immediateExternalShare: true), nil)
|
||||
return true
|
||||
case let .audio(file):
|
||||
let location: PeerMessagesPlaylistLocation
|
||||
@ -245,7 +247,7 @@ func openChatMessage(account: Account, message: Message, standalone: Bool, rever
|
||||
}
|
||||
playerType = (file.isVoice || file.isInstantVideo) ? .voice : .music
|
||||
}
|
||||
account.telegramApplicationContext.mediaManager.setPlaylist(PeerMessagesMediaPlaylist(postbox: account.postbox, network: account.network, location: location), type: playerType)
|
||||
account.telegramApplicationContext.mediaManager?.setPlaylist(PeerMessagesMediaPlaylist(postbox: account.postbox, network: account.network, location: location), type: playerType)
|
||||
return true
|
||||
case let .gallery(gallery):
|
||||
dismissInput()
|
||||
|
||||
@ -440,10 +440,10 @@ public func openExternalUrl(account: Account, context: OpenURLContext = .generic
|
||||
navigationController.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
|
||||
navigateToChatController(navigationController: navigationController, account: account, chatLocation: .peer(peerId))
|
||||
}
|
||||
case .withBotStartPayload:
|
||||
case let .withBotStartPayload(payload):
|
||||
if let navigationController = navigationController {
|
||||
navigationController.view.window?.rootViewController?.dismiss(animated: true, completion: nil)
|
||||
navigateToChatController(navigationController: navigationController, account: account, chatLocation: .peer(peerId))
|
||||
navigateToChatController(navigationController: navigationController, account: account, chatLocation: .peer(peerId), botStart: payload)
|
||||
}
|
||||
}
|
||||
}, present: { c, a in
|
||||
|
||||
@ -75,7 +75,7 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec
|
||||
|
||||
self.contentNode = ASDisplayNode()
|
||||
|
||||
self.controlsNode = OverlayPlayerControlsNode(postbox: account.postbox, theme: self.presentationData.theme, status: account.telegramApplicationContext.mediaManager.musicMediaPlayerState)
|
||||
self.controlsNode = OverlayPlayerControlsNode(postbox: account.postbox, theme: self.presentationData.theme, status: account.telegramApplicationContext.mediaManager!.musicMediaPlayerState)
|
||||
|
||||
self.historyBackgroundNode = ASDisplayNode()
|
||||
self.historyBackgroundNode.isLayerBacked = true
|
||||
@ -142,7 +142,7 @@ final class OverlayPlayerControllerNode: ViewControllerTracingNode, UIGestureRec
|
||||
|
||||
self.controlsNode.control = { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
strongSelf.account.telegramApplicationContext.mediaManager.playlistControl(action, type: strongSelf.type)
|
||||
strongSelf.account.telegramApplicationContext.mediaManager?.playlistControl(action, type: strongSelf.type)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -462,30 +462,32 @@ public class PeerMediaCollectionController: TelegramController {
|
||||
self.displayNode = PeerMediaCollectionControllerNode(account: self.account, peerId: self.peerId, messageId: self.messageId, controllerInteraction: self.controllerInteraction!, interfaceInteraction: self.interfaceInteraction!, navigationBar: self.navigationBar, requestDeactivateSearch: { [weak self] in
|
||||
self?.deactivateSearch()
|
||||
})
|
||||
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(self.account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
for id in ids {
|
||||
if case let .chat(messageId, media) = id {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
|
||||
if let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
self.galleryHiddenMesageAndMediaDisposable.set(mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
|
||||
if let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction {
|
||||
var messageIdAndMedia: [MessageId: [Media]] = [:]
|
||||
|
||||
for id in ids {
|
||||
if case let .chat(messageId, media) = id {
|
||||
messageIdAndMedia[messageId] = [media]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if controllerInteraction.hiddenMedia != messageIdAndMedia {
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
strongSelf.mediaCollectionDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? GridMessageItemNode {
|
||||
itemNode.updateHiddenMedia()
|
||||
} else if let itemNode = itemNode as? ListMessageNode {
|
||||
itemNode.updateHiddenMedia()
|
||||
|
||||
//if controllerInteraction.hiddenMedia != messageIdAndMedia {
|
||||
controllerInteraction.hiddenMedia = messageIdAndMedia
|
||||
|
||||
strongSelf.mediaCollectionDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||
if let itemNode = itemNode as? GridMessageItemNode {
|
||||
itemNode.updateHiddenMedia()
|
||||
} else if let itemNode = itemNode as? ListMessageNode {
|
||||
itemNode.updateHiddenMedia()
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
self.ready.set(combineLatest(self.mediaCollectionDisplayNode.historyNode.historyState.get(), self._peerReady.get()) |> map { $1 })
|
||||
|
||||
|
||||
@ -540,17 +540,15 @@ func rawMessagePhoto(postbox: Postbox, photoReference: ImageMediaReference) -> S
|
||||
}
|
||||
}
|
||||
|
||||
func chatMessagePhoto(postbox: Postbox, photoReference: ImageMediaReference) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||
return chatMessagePhotoInternal(postbox: postbox, photoReference: photoReference)
|
||||
public func chatMessagePhoto(postbox: Postbox, photoReference: ImageMediaReference) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||
return chatMessagePhotoInternal(photoData: chatMessagePhotoDatas(postbox: postbox, photoReference: photoReference))
|
||||
|> map { _, generate in
|
||||
return generate
|
||||
}
|
||||
}
|
||||
|
||||
func chatMessagePhotoInternal(postbox: Postbox, photoReference: ImageMediaReference) -> Signal<(() -> CGSize?, (TransformImageArguments) -> DrawingContext?), NoError> {
|
||||
let signal = chatMessagePhotoDatas(postbox: postbox, photoReference: photoReference)
|
||||
|
||||
return signal
|
||||
public func chatMessagePhotoInternal(photoData: Signal<(Data?, Data?, Bool), NoError>) -> Signal<(() -> CGSize?, (TransformImageArguments) -> DrawingContext?), NoError> {
|
||||
return photoData
|
||||
|> map { (thumbnailData, fullSizeData, fullSizeComplete) in
|
||||
return ({
|
||||
return nil
|
||||
@ -1432,7 +1430,7 @@ func chatMessagePhotoStatus(account: Account, messageId: MessageId, photoReferen
|
||||
}
|
||||
}
|
||||
|
||||
func chatMessagePhotoInteractiveFetched(account: Account, photoReference: ImageMediaReference) -> Signal<FetchResourceSourceType, NoError> {
|
||||
public func chatMessagePhotoInteractiveFetched(account: Account, photoReference: ImageMediaReference) -> Signal<FetchResourceSourceType, NoError> {
|
||||
if let largestRepresentation = largestRepresentationForPhoto(photoReference.media) {
|
||||
return fetchedMediaResource(postbox: account.postbox, reference: photoReference.resourceReference(largestRepresentation.resource), statsCategory: .image)
|
||||
} else {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Foundation
|
||||
import AsyncDisplayKit
|
||||
|
||||
enum RadialStatusNodeState: Equatable {
|
||||
public enum RadialStatusNodeState: Equatable {
|
||||
case none
|
||||
case download(UIColor)
|
||||
case play(UIColor)
|
||||
@ -11,7 +11,7 @@ enum RadialStatusNodeState: Equatable {
|
||||
case customIcon(UIImage)
|
||||
case secretTimeout(color: UIColor, icon: UIImage?, beginTime: Double, timeout: Double)
|
||||
|
||||
static func ==(lhs: RadialStatusNodeState, rhs: RadialStatusNodeState) -> Bool {
|
||||
public static func ==(lhs: RadialStatusNodeState, rhs: RadialStatusNodeState) -> Bool {
|
||||
switch lhs {
|
||||
case .none:
|
||||
if case .none = rhs {
|
||||
@ -99,13 +99,13 @@ enum RadialStatusNodeState: Equatable {
|
||||
node.progress = value
|
||||
return node
|
||||
}
|
||||
case let .secretTimeout(color, icon, beginTime, timeout):
|
||||
return RadialStatusSecretTimeoutContentNode(color: color, beginTime: beginTime, timeout: timeout, icon: icon)
|
||||
case let .secretTimeout(color, icon, beginTime, timeout):
|
||||
return RadialStatusSecretTimeoutContentNode(color: color, beginTime: beginTime, timeout: timeout, icon: icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class RadialStatusNode: ASControlNode {
|
||||
public final class RadialStatusNode: ASControlNode {
|
||||
private var backgroundNodeColor: UIColor
|
||||
|
||||
private(set) var state: RadialStatusNodeState = .none
|
||||
@ -114,13 +114,13 @@ final class RadialStatusNode: ASControlNode {
|
||||
private var contentNode: RadialStatusContentNode?
|
||||
private var nextContentNode: RadialStatusContentNode?
|
||||
|
||||
init(backgroundNodeColor: UIColor) {
|
||||
public init(backgroundNodeColor: UIColor) {
|
||||
self.backgroundNodeColor = backgroundNodeColor
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
func transitionToState(_ state: RadialStatusNodeState, animated: Bool = true, completion: @escaping () -> Void) {
|
||||
public func transitionToState(_ state: RadialStatusNodeState, animated: Bool = true, completion: @escaping () -> Void) {
|
||||
if self.state != state {
|
||||
self.state = state
|
||||
|
||||
@ -221,7 +221,7 @@ final class RadialStatusNode: ASControlNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
override public func layout() {
|
||||
self.backgroundNode?.frame = self.bounds
|
||||
if let contentNode = self.contentNode {
|
||||
contentNode.frame = self.bounds
|
||||
|
||||
@ -13,8 +13,8 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
|
||||
let closeButton: ASButtonNode
|
||||
let lineNode: ASImageNode
|
||||
let titleNode: ASTextNode
|
||||
let textNode: ASTextNode
|
||||
let titleNode: ImmediateTextNode
|
||||
let textNode: ImmediateTextNode
|
||||
let imageNode: TransformImageNode
|
||||
|
||||
var theme: PresentationTheme
|
||||
@ -34,13 +34,11 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
self.lineNode.displaysAsynchronously = false
|
||||
self.lineNode.image = PresentationResourcesChat.chatInputPanelVerticalSeparatorLineImage(theme)
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.truncationMode = .byTruncatingTail
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 1
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.truncationMode = .byTruncatingTail
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.maximumNumberOfLines = 1
|
||||
self.textNode.displaysAsynchronously = false
|
||||
|
||||
@ -216,10 +214,10 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
self.imageNode.frame = CGRect(origin: CGPoint(x: leftInset + 9.0, y: 8.0), size: CGSize(width: 35.0, height: 35.0))
|
||||
|
||||
let titleSize = self.titleNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
let titleSize = self.titleNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
self.titleNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset + imageTextInset, y: 7.0), size: titleSize)
|
||||
|
||||
let textSize = self.textNode.measure(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: bounds.size.width - leftInset - textLineInset - rightInset - textRightInset - imageTextInset, height: bounds.size.height))
|
||||
self.textNode.frame = CGRect(origin: CGPoint(x: leftInset + textLineInset + imageTextInset, y: 25.0), size: textSize)
|
||||
}
|
||||
|
||||
|
||||
@ -158,13 +158,16 @@ public final class SecretMediaPreviewController: ViewController {
|
||||
}
|
||||
}))
|
||||
|
||||
self.hiddenMediaManagerIndex = account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.addSource(self._hiddenMedia.get() |> map { messageIdAndMedia in
|
||||
if let (messageId, media) = messageIdAndMedia {
|
||||
return .chat(messageId, media)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
if let mediaManager = account.telegramApplicationContext.mediaManager {
|
||||
self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(self._hiddenMedia.get()
|
||||
|> map { messageIdAndMedia in
|
||||
if let (messageId, media) = messageIdAndMedia {
|
||||
return .chat(messageId, media)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
self.screenCaptureEventsDisposable = (screenCaptureEvents()
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
@ -181,8 +184,8 @@ public final class SecretMediaPreviewController: ViewController {
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
self.markMessageAsConsumedDisposable.dispose()
|
||||
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex {
|
||||
self.account.telegramApplicationContext.mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||
if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex, let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex)
|
||||
}
|
||||
self.screenCaptureEventsDisposable?.dispose()
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ public final class TelegramApplicationContext {
|
||||
let fetchManager: FetchManager
|
||||
public var callManager: PresentationCallManager?
|
||||
|
||||
public let mediaManager: MediaManager
|
||||
public let mediaManager: MediaManager?
|
||||
|
||||
let locationManager: DeviceLocationManager?
|
||||
public let liveLocationManager: LiveLocationManager?
|
||||
@ -106,7 +106,11 @@ public final class TelegramApplicationContext {
|
||||
private var storedPassword: (String, CFAbsoluteTime, SwiftSignalKit.Timer)?
|
||||
|
||||
public init(applicationBindings: TelegramApplicationBindings, accountManager: AccountManager, account: Account?, initialPresentationDataAndSettings: InitialPresentationDataAndSettings, postbox: Postbox) {
|
||||
self.mediaManager = MediaManager(postbox: postbox, inForeground: applicationBindings.applicationInForeground)
|
||||
if account != nil {
|
||||
self.mediaManager = MediaManager(postbox: postbox, inForeground: applicationBindings.applicationInForeground)
|
||||
} else {
|
||||
self.mediaManager = nil
|
||||
}
|
||||
|
||||
if applicationBindings.isMainApp {
|
||||
self.locationManager = DeviceLocationManager(queue: Queue.mainQueue())
|
||||
@ -218,7 +222,7 @@ public final class TelegramApplicationContext {
|
||||
}
|
||||
|
||||
public func attachOverlayMediaController(_ controller: OverlayMediaController) {
|
||||
self.mediaManager.overlayMediaManager.attachOverlayMediaController(controller)
|
||||
self.mediaManager?.overlayMediaManager.attachOverlayMediaController(controller)
|
||||
}
|
||||
|
||||
public func storeSecureIdPassword(password: String) {
|
||||
|
||||
@ -88,8 +88,8 @@ public class TelegramController: ViewController {
|
||||
|
||||
super.init(navigationBarPresentationData: navigationBarPresentationData)
|
||||
|
||||
if case .none = mediaAccessoryPanelVisibility {} else {
|
||||
self.mediaStatusDisposable = (account.telegramApplicationContext.mediaManager.globalMediaPlayerState
|
||||
if case .none = mediaAccessoryPanelVisibility {} else if let mediaManager = account.telegramApplicationContext.mediaManager {
|
||||
self.mediaStatusDisposable = (mediaManager.globalMediaPlayerState
|
||||
|> deliverOnMainQueue).start(next: { [weak self] playlistStateAndType in
|
||||
if let strongSelf = self {
|
||||
if !arePlaylistItemsEqual(strongSelf.playlistStateAndType?.0, playlistStateAndType?.0.item) ||
|
||||
@ -379,8 +379,12 @@ public class TelegramController: ViewController {
|
||||
transition.updateFrame(layer: mediaAccessoryPanel.layer, frame: panelFrame)
|
||||
mediaAccessoryPanel.updateLayout(size: panelFrame.size, transition: transition)
|
||||
mediaAccessoryPanel.containerNode.headerNode.playbackItem = item
|
||||
mediaAccessoryPanel.containerNode.headerNode.playbackStatus = self.account.telegramApplicationContext.mediaManager.globalMediaPlayerState |> map { state in
|
||||
return state?.0.status ?? MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .paused)
|
||||
|
||||
if let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
mediaAccessoryPanel.containerNode.headerNode.playbackStatus = mediaManager.globalMediaPlayerState
|
||||
|> map { state in
|
||||
return state?.0.status ?? MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .paused)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let (mediaAccessoryPanel, _) = self.mediaAccessoryPanel {
|
||||
@ -398,7 +402,7 @@ public class TelegramController: ViewController {
|
||||
mediaAccessoryPanel.containerNode.headerNode.displayScrubber = type != .voice
|
||||
mediaAccessoryPanel.close = { [weak self] in
|
||||
if let strongSelf = self, let (_, _, type) = strongSelf.playlistStateAndType {
|
||||
strongSelf.account.telegramApplicationContext.mediaManager.setPlaylist(nil, type: type)
|
||||
strongSelf.account.telegramApplicationContext.mediaManager?.setPlaylist(nil, type: type)
|
||||
}
|
||||
}
|
||||
mediaAccessoryPanel.toggleRate = {
|
||||
@ -424,12 +428,12 @@ public class TelegramController: ViewController {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.account.telegramApplicationContext.mediaManager.playlistControl(.setBaseRate(baseRate), type: type)
|
||||
strongSelf.account.telegramApplicationContext.mediaManager?.playlistControl(.setBaseRate(baseRate), type: type)
|
||||
})
|
||||
}
|
||||
mediaAccessoryPanel.togglePlayPause = { [weak self] in
|
||||
if let strongSelf = self, let (_, _, type) = strongSelf.playlistStateAndType {
|
||||
strongSelf.account.telegramApplicationContext.mediaManager.playlistControl(.playback(.togglePlayPause), type: type)
|
||||
strongSelf.account.telegramApplicationContext.mediaManager?.playlistControl(.playback(.togglePlayPause), type: type)
|
||||
}
|
||||
}
|
||||
mediaAccessoryPanel.tapAction = { [weak self] in
|
||||
@ -456,8 +460,11 @@ public class TelegramController: ViewController {
|
||||
self.mediaAccessoryPanel = (mediaAccessoryPanel, type)
|
||||
mediaAccessoryPanel.updateLayout(size: panelFrame.size, transition: .immediate)
|
||||
mediaAccessoryPanel.containerNode.headerNode.playbackItem = item
|
||||
mediaAccessoryPanel.containerNode.headerNode.playbackStatus = self.account.telegramApplicationContext.mediaManager.globalMediaPlayerState |> map { state in
|
||||
return state?.0.status ?? MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .paused)
|
||||
if let mediaManager = self.account.telegramApplicationContext.mediaManager {
|
||||
mediaAccessoryPanel.containerNode.headerNode.playbackStatus = mediaManager.globalMediaPlayerState
|
||||
|> map { state in
|
||||
return state?.0.status ?? MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .paused)
|
||||
}
|
||||
}
|
||||
mediaAccessoryPanel.animateIn(transition: transition)
|
||||
}
|
||||
|
||||
@ -223,14 +223,14 @@ private final class LegacyComponentsGlobalsProviderImpl: NSObject, LegacyCompone
|
||||
default:
|
||||
convertedType = .play
|
||||
}
|
||||
let disposable = legacyAccount.telegramApplicationContext.mediaManager.audioSession.push(audioSessionType: convertedType, once: true, activate: { _ in
|
||||
let disposable = legacyAccount.telegramApplicationContext.mediaManager?.audioSession.push(audioSessionType: convertedType, once: true, activate: { _ in
|
||||
}, deactivate: {
|
||||
interrupted?()
|
||||
return .complete()
|
||||
})
|
||||
|
||||
return SBlockDisposable(block: {
|
||||
disposable.dispose()
|
||||
disposable?.dispose()
|
||||
})
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -37,7 +37,7 @@ public class TransformImageNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
func setSignal(_ signal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>, dispatchOnDisplayLink: Bool = true) {
|
||||
public func setSignal(_ signal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>, dispatchOnDisplayLink: Bool = true) {
|
||||
let argumentsPromise = self.argumentsPromise
|
||||
|
||||
let result = combineLatest(signal, argumentsPromise.get())
|
||||
|
||||
@ -255,7 +255,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
self.footerContentNode.scrubberView = nil
|
||||
}
|
||||
|
||||
let videoNode = UniversalVideoNode(postbox: item.account.postbox, audioSession: item.account.telegramApplicationContext.mediaManager.audioSession, manager: item.account.telegramApplicationContext.mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: item.content, priority: .gallery)
|
||||
guard let mediaManager = item.account.telegramApplicationContext.mediaManager else {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
let videoNode = UniversalVideoNode(postbox: item.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: item.content, priority: .gallery)
|
||||
let videoSize = CGSize(width: item.content.dimensions.width * 2.0, height: item.content.dimensions.height * 2.0)
|
||||
videoNode.updateLayout(size: videoSize, transition: .immediate)
|
||||
videoNode.ownsContentNodeUpdated = { [weak self] value in
|
||||
@ -439,7 +443,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
let transform = CATransform3DScale(videoNode.layer.transform, transformedFrame.size.width / videoNode.layer.bounds.size.width, transformedFrame.size.height / videoNode.layer.bounds.size.height, 1.0)
|
||||
videoNode.layer.animate(from: NSValue(caTransform3D: transform), to: NSValue(caTransform3D: videoNode.layer.transform), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25)
|
||||
|
||||
self.account.telegramApplicationContext.mediaManager.setOverlayVideoNode(nil)
|
||||
self.account.telegramApplicationContext.mediaManager?.setOverlayVideoNode(nil)
|
||||
} else {
|
||||
var transformedFrame = node.0.view.convert(node.0.view.bounds, to: videoNode.view)
|
||||
let transformedSuperFrame = node.0.view.convert(node.0.view.bounds, to: videoNode.view.superview)
|
||||
@ -696,9 +700,9 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
if let item = self.item, let _ = self.videoNode {
|
||||
let account = self.account
|
||||
let baseNavigationController = self.baseNavigationController()
|
||||
let mediaManager = self.account.telegramApplicationContext.mediaManager
|
||||
let mediaManager = self.account.telegramApplicationContext.mediaManager!
|
||||
var expandImpl: (() -> Void)?
|
||||
let overlayNode = OverlayUniversalVideoNode(account: self.account, audioSession: self.account.telegramApplicationContext.mediaManager.audioSession, manager: self.account.telegramApplicationContext.mediaManager.universalVideoManager, content: item.content, expand: {
|
||||
let overlayNode = OverlayUniversalVideoNode(account: self.account, audioSession: self.account.telegramApplicationContext.mediaManager!.audioSession, manager: self.account.telegramApplicationContext.mediaManager!.universalVideoManager, content: item.content, expand: {
|
||||
expandImpl?()
|
||||
}, close: { [weak mediaManager] in
|
||||
mediaManager?.setOverlayVideoNode(nil)
|
||||
@ -734,7 +738,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
break
|
||||
}
|
||||
}
|
||||
account.telegramApplicationContext.mediaManager.setOverlayVideoNode(overlayNode)
|
||||
account.telegramApplicationContext.mediaManager?.setOverlayVideoNode(overlayNode)
|
||||
if overlayNode.supernode != nil {
|
||||
self.beginCustomDismiss()
|
||||
self.animateOut(toOverlay: overlayNode, completion: { [weak self] in
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user