mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Temp
This commit is contained in:
parent
c31e0372f8
commit
c9aa7d70d6
@ -63,9 +63,20 @@ static int64_t makePeerId(int32_t namespace, int32_t value) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)completeWithContent:(UNNotificationContent * _Nonnull)content {
|
||||||
|
/*NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"org.telegram.Telegram-iOS.background"];
|
||||||
|
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
|
||||||
|
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:[NSURL URLWithString:@"https://telegram.org"]];
|
||||||
|
[task resume];*/
|
||||||
|
|
||||||
|
if (_contentHandler) {
|
||||||
|
_contentHandler(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
|
- (void)didReceiveNotificationRequest:(UNNotificationRequest *)request withContentHandler:(void (^)(UNNotificationContent * _Nonnull))contentHandler {
|
||||||
if (_rootPath == nil) {
|
if (_rootPath == nil) {
|
||||||
contentHandler(request.content);
|
[self completeWithContent:request.content];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,8 +300,8 @@ static int64_t makePeerId(int32_t namespace, int32_t value) {
|
|||||||
_bestAttemptContent.attachments = @[attachment];
|
_bestAttemptContent.attachments = @[attachment];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_contentHandler && _bestAttemptContent != nil) {
|
if (_bestAttemptContent != nil) {
|
||||||
_contentHandler(_bestAttemptContent);
|
[self completeWithContent:_bestAttemptContent];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BuildConfig *buildConfig = [[BuildConfig alloc] initWithBaseAppBundleId:_baseAppBundleId];
|
BuildConfig *buildConfig = [[BuildConfig alloc] initWithBaseAppBundleId:_baseAppBundleId];
|
||||||
@ -322,21 +333,21 @@ static int64_t makePeerId(int32_t namespace, int32_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strongSelf->_contentHandler && strongSelf->_bestAttemptContent != nil) {
|
if (strongSelf->_bestAttemptContent != nil) {
|
||||||
strongSelf->_contentHandler(strongSelf->_bestAttemptContent);
|
[strongSelf completeWithContent:strongSelf->_bestAttemptContent];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_contentHandler && _bestAttemptContent != nil) {
|
if (_bestAttemptContent != nil) {
|
||||||
_contentHandler(_bestAttemptContent);
|
[self completeWithContent:_bestAttemptContent];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (_contentHandler && _bestAttemptContent != nil) {
|
if (_bestAttemptContent != nil) {
|
||||||
_contentHandler(_bestAttemptContent);
|
[self completeWithContent:_bestAttemptContent];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,7 +360,7 @@ static int64_t makePeerId(int32_t namespace, int32_t value) {
|
|||||||
|
|
||||||
if (_contentHandler) {
|
if (_contentHandler) {
|
||||||
if(_bestAttemptContent) {
|
if(_bestAttemptContent) {
|
||||||
_contentHandler(_bestAttemptContent);
|
[self completeWithContent:_bestAttemptContent];
|
||||||
_bestAttemptContent = nil;
|
_bestAttemptContent = nil;
|
||||||
}
|
}
|
||||||
_contentHandler = nil;
|
_contentHandler = nil;
|
||||||
|
@ -15,6 +15,7 @@ import TelegramNotices
|
|||||||
import SearchUI
|
import SearchUI
|
||||||
import DeleteChatPeerActionSheetItem
|
import DeleteChatPeerActionSheetItem
|
||||||
import LanguageSuggestionUI
|
import LanguageSuggestionUI
|
||||||
|
import ContextUI
|
||||||
|
|
||||||
public func useSpecialTabBarIcons() -> Bool {
|
public func useSpecialTabBarIcons() -> Bool {
|
||||||
return (Date(timeIntervalSince1970: 1545642000)...Date(timeIntervalSince1970: 1546387200)).contains(Date())
|
return (Date(timeIntervalSince1970: 1545642000)...Date(timeIntervalSince1970: 1546387200)).contains(Date())
|
||||||
@ -64,6 +65,27 @@ private func fixListNodeScrolling(_ listNode: ListView, searchNode: NavigationBa
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
|
||||||
|
let controller: ViewController
|
||||||
|
weak var sourceNode: ASDisplayNode?
|
||||||
|
|
||||||
|
init(controller: ViewController, sourceNode: ASDisplayNode?) {
|
||||||
|
self.controller = controller
|
||||||
|
self.sourceNode = sourceNode
|
||||||
|
}
|
||||||
|
|
||||||
|
func transitionInfo() -> ContextControllerTakeControllerInfo? {
|
||||||
|
let sourceNode = self.sourceNode
|
||||||
|
return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in
|
||||||
|
if let sourceNode = sourceNode {
|
||||||
|
return (sourceNode, sourceNode.bounds)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class ChatListControllerImpl: TelegramBaseController, ChatListController, UIViewControllerPreviewingDelegate {
|
public class ChatListControllerImpl: TelegramBaseController, ChatListController, UIViewControllerPreviewingDelegate {
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
@ -356,6 +378,19 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
preconditionFailure("debug tap")
|
preconditionFailure("debug tap")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.customPresentPreviewingController = { [weak self] controller, sourceNode in
|
||||||
|
guard let strongSelf = self else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var items: [ContextMenuItem] = []
|
||||||
|
for i in 0 ..< 5 {
|
||||||
|
items.append(.action(ContextMenuActionItem(text: "Item \(i)", icon: { _ in nil }, action: { controller, f in
|
||||||
|
f(.default)
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
return ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .controller(ContextControllerContentSourceImpl(controller: controller, sourceNode: sourceNode)), items: items, reactionItems: [])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
@ -1068,6 +1103,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
|
||||||
|
if !self.didSetup3dTouch {
|
||||||
|
self.didSetup3dTouch = true
|
||||||
|
self.registerForPreviewingNonNative(with: self, sourceView: self.view, theme: PeekControllerTheme(presentationTheme: self.presentationData.theme))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func viewWillDisappear(_ animated: Bool) {
|
override public func viewWillDisappear(_ animated: Bool) {
|
||||||
|
@ -9,7 +9,7 @@ final class ContextContentContainerNode: ASDisplayNode {
|
|||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
|
func updateLayout(size: CGSize, scaledSize: CGSize, transition: ContainedViewLayoutTransition) {
|
||||||
guard let contentNode = self.contentNode else {
|
guard let contentNode = self.contentNode else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -17,6 +17,9 @@ final class ContextContentContainerNode: ASDisplayNode {
|
|||||||
case .extracted:
|
case .extracted:
|
||||||
break
|
break
|
||||||
case let .controller(controller):
|
case let .controller(controller):
|
||||||
|
transition.updatePosition(node: controller, position: CGPoint(x: scaledSize.width / 2.0, y: scaledSize.height / 2.0))
|
||||||
|
transition.updateBounds(node: controller, bounds: CGRect(origin: CGPoint(), size: size))
|
||||||
|
transition.updateTransformScale(node: controller, scale: scaledSize.width / size.width)
|
||||||
controller.updateLayout(size: size, transition: transition)
|
controller.updateLayout(size: size, transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,8 @@ final class ContextControllerContentNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
|
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
|
||||||
controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
transition.updateFrame(node: self.controller.displayNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
|
self.controller.containerLayoutUpdated(ContainerViewLayout(size: size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact), deviceMetrics: .iPhoneX, intrinsicInsets: UIEdgeInsets(), safeInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +339,25 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
self.clippingNode.layer.animateBoundsOriginYAdditive(from: updatedContentAreaInScreenSpace.minY, to: 0.0, duration: 0.18 * animationDurationFactor, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
self.clippingNode.layer.animateBoundsOriginYAdditive(from: updatedContentAreaInScreenSpace.minY, to: 0.0, duration: 0.18 * animationDurationFactor, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||||
}
|
}
|
||||||
case let .controller(source):
|
case let .controller(source):
|
||||||
break
|
let contentParentNode = ContextControllerContentNode(controller: source.controller)
|
||||||
|
self.contentContainerNode.contentNode = .controller(contentParentNode)
|
||||||
|
self.contentContainerNode.clipsToBounds = true
|
||||||
|
self.contentContainerNode.cornerRadius = 14.0
|
||||||
|
self.contentContainerNode.addSubnode(contentParentNode)
|
||||||
|
|
||||||
|
let transitionInfo = source.transitionInfo()
|
||||||
|
if let transitionInfo = transitionInfo, let (sourceNode, sourceNodeRect) = transitionInfo.sourceNode() {
|
||||||
|
let projectedFrame = convertFrame(sourceNodeRect, from: sourceNode.view, to: self.view)
|
||||||
|
self.originalProjectedContentViewFrame = (projectedFrame, projectedFrame)
|
||||||
|
|
||||||
|
var updatedContentAreaInScreenSpace = transitionInfo.contentAreaInScreenSpace
|
||||||
|
updatedContentAreaInScreenSpace.origin.x = 0.0
|
||||||
|
updatedContentAreaInScreenSpace.size.width = self.bounds.width
|
||||||
|
self.contentAreaInScreenSpace = updatedContentAreaInScreenSpace
|
||||||
|
|
||||||
|
//self.clippingNode.layer.animateFrame(from: updatedContentAreaInScreenSpace, to: self.clippingNode.frame, duration: 0.18 * animationDurationFactor, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||||
|
//self.clippingNode.layer.animateBoundsOriginYAdditive(from: updatedContentAreaInScreenSpace.minY, to: 0.0, duration: 0.18 * animationDurationFactor, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let validLayout = self.validLayout {
|
if let validLayout = self.validLayout {
|
||||||
@ -375,14 +393,15 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
self?.didCompleteAnimationIn = true
|
self?.didCompleteAnimationIn = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2 * animationDurationFactor)
|
|
||||||
|
|
||||||
let springDuration: Double = 0.42 * animationDurationFactor
|
let springDuration: Double = 0.42 * animationDurationFactor
|
||||||
let springDamping: CGFloat = 104.0
|
let springDamping: CGFloat = 104.0
|
||||||
self.actionsContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping)
|
|
||||||
if let contentNode = self.contentContainerNode.contentNode {
|
if let contentNode = self.contentContainerNode.contentNode {
|
||||||
switch contentNode {
|
switch contentNode {
|
||||||
case let .extracted(extracted):
|
case let .extracted(extracted):
|
||||||
|
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2 * animationDurationFactor)
|
||||||
|
self.actionsContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping)
|
||||||
|
|
||||||
if let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame {
|
if let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame {
|
||||||
let contentParentNode = extracted
|
let contentParentNode = extracted
|
||||||
let localSourceFrame = self.view.convert(originalProjectedContentViewFrame.1, to: self.scrollNode.view)
|
let localSourceFrame = self.view.convert(originalProjectedContentViewFrame.1, to: self.scrollNode.view)
|
||||||
@ -396,8 +415,23 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentContainerOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentContainerOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
||||||
contentParentNode.applyAbsoluteOffsetSpring?(-contentContainerOffset.y, springDuration, springDamping)
|
contentParentNode.applyAbsoluteOffsetSpring?(-contentContainerOffset.y, springDuration, springDamping)
|
||||||
}
|
}
|
||||||
case let .controller(controller):
|
case .controller:
|
||||||
break
|
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2 * animationDurationFactor)
|
||||||
|
self.actionsContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping)
|
||||||
|
self.contentContainerNode.allowsGroupOpacity = true
|
||||||
|
self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2 * animationDurationFactor, completion: { [weak self] _ in
|
||||||
|
self?.contentContainerNode.allowsGroupOpacity = false
|
||||||
|
})
|
||||||
|
self.contentContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping)
|
||||||
|
|
||||||
|
if let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame {
|
||||||
|
let actionsSideInset: CGFloat = 11.0
|
||||||
|
|
||||||
|
let localSourceFrame = self.view.convert(CGRect(origin: CGPoint(x: actionsSideInset, y: originalProjectedContentViewFrame.1.minY), size: CGSize(width: actionsSideInset, height: originalProjectedContentViewFrame.1.height)), to: self.scrollNode.view)
|
||||||
|
self.actionsContainerNode.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
||||||
|
let contentContainerOffset = CGPoint(x: localSourceFrame.center.x - self.contentContainerNode.frame.center.x, y: localSourceFrame.center.y - self.contentContainerNode.frame.center.y)
|
||||||
|
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentContainerOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,6 +444,10 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
|
|
||||||
switch self.source {
|
switch self.source {
|
||||||
case let .extracted(source):
|
case let .extracted(source):
|
||||||
|
guard let maybeContentNode = self.contentContainerNode.contentNode, case let .extracted(contentParentNode) = maybeContentNode else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let putBackInfo = source.putBack()
|
let putBackInfo = source.putBack()
|
||||||
|
|
||||||
if putBackInfo == nil {
|
if putBackInfo == nil {
|
||||||
@ -438,7 +476,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
var completedContentNode = false
|
var completedContentNode = false
|
||||||
var completedActionsNode = false
|
var completedActionsNode = false
|
||||||
|
|
||||||
if let putBackInfo = putBackInfo, let contentParentNode = self.contentParentNode, let parentSupernode = contentParentNode.supernode {
|
if let putBackInfo = putBackInfo, let parentSupernode = contentParentNode.supernode {
|
||||||
self.originalProjectedContentViewFrame = (convertFrame(contentParentNode.frame, from: parentSupernode.view, to: self.view), convertFrame(contentParentNode.contentRect, from: contentParentNode.view, to: self.view))
|
self.originalProjectedContentViewFrame = (convertFrame(contentParentNode.frame, from: parentSupernode.view, to: self.view), convertFrame(contentParentNode.contentRect, from: contentParentNode.view, to: self.view))
|
||||||
|
|
||||||
var updatedContentAreaInScreenSpace = putBackInfo.contentAreaInScreenSpace
|
var updatedContentAreaInScreenSpace = putBackInfo.contentAreaInScreenSpace
|
||||||
@ -449,9 +487,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: updatedContentAreaInScreenSpace.minY, duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false)
|
self.clippingNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: updatedContentAreaInScreenSpace.minY, duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
let contentParentNode = self.contentParentNode
|
contentParentNode.willUpdateIsExtractedToContextPreview?(false)
|
||||||
|
|
||||||
contentParentNode?.willUpdateIsExtractedToContextPreview?(false)
|
|
||||||
|
|
||||||
let intermediateCompletion: () -> Void = { [weak contentParentNode] in
|
let intermediateCompletion: () -> Void = { [weak contentParentNode] in
|
||||||
if completedEffect && completedContentNode && completedActionsNode {
|
if completedEffect && completedContentNode && completedActionsNode {
|
||||||
@ -518,7 +554,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
animateOutToItem = false
|
animateOutToItem = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if animateOutToItem, let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame, let contentParentNode = self.contentParentNode {
|
if animateOutToItem, let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame {
|
||||||
let localSourceFrame = self.view.convert(originalProjectedContentViewFrame.1, to: self.scrollNode.view)
|
let localSourceFrame = self.view.convert(originalProjectedContentViewFrame.1, to: self.scrollNode.view)
|
||||||
self.actionsContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y), duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false, additive: true)
|
self.actionsContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y), duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false, additive: true)
|
||||||
let contentContainerOffset = CGPoint(x: localSourceFrame.center.x - self.contentContainerNode.frame.center.x - contentParentNode.contentRect.minX, y: localSourceFrame.center.y - self.contentContainerNode.frame.center.y - contentParentNode.contentRect.minY)
|
let contentContainerOffset = CGPoint(x: localSourceFrame.center.x - self.contentContainerNode.frame.center.x - contentParentNode.contentRect.minX, y: localSourceFrame.center.y - self.contentContainerNode.frame.center.y - contentParentNode.contentRect.minY)
|
||||||
@ -532,7 +568,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
if let reactionContextNode = self.reactionContextNode {
|
if let reactionContextNode = self.reactionContextNode {
|
||||||
reactionContextNode.animateOut(to: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size), animatingOutToReaction: self.reactionContextNodeIsAnimatingOut)
|
reactionContextNode.animateOut(to: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size), animatingOutToReaction: self.reactionContextNodeIsAnimatingOut)
|
||||||
}
|
}
|
||||||
} else if let contentParentNode = self.contentParentNode {
|
} else {
|
||||||
if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree() {
|
if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree() {
|
||||||
self.contentContainerNode.view.addSubview(snapshotView)
|
self.contentContainerNode.view.addSubview(snapshotView)
|
||||||
}
|
}
|
||||||
@ -553,8 +589,138 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .controller(source):
|
case let .controller(source):
|
||||||
|
guard let maybeContentNode = self.contentContainerNode.contentNode, case let .controller(controller) = maybeContentNode else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let transitionInfo = source.transitionInfo()
|
||||||
|
|
||||||
|
if transitionInfo == nil {
|
||||||
|
result = .dismissWithoutContent
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result {
|
||||||
|
case let .custom(value):
|
||||||
|
switch value {
|
||||||
|
case let .animated(duration, curve):
|
||||||
|
transitionDuration = duration
|
||||||
|
transitionCurve = curve
|
||||||
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
self.isUserInteractionEnabled = false
|
||||||
|
self.isAnimatingOut = true
|
||||||
|
|
||||||
|
self.scrollNode.view.setContentOffset(self.scrollNode.view.contentOffset, animated: false)
|
||||||
|
|
||||||
|
var completedEffect = false
|
||||||
|
var completedContentNode = false
|
||||||
|
var completedActionsNode = false
|
||||||
|
|
||||||
|
if let transitionInfo = transitionInfo, let (sourceNode, sourceNodeRect) = transitionInfo.sourceNode() {
|
||||||
|
let projectedFrame = convertFrame(sourceNodeRect, from: sourceNode.view, to: self.view)
|
||||||
|
self.originalProjectedContentViewFrame = (projectedFrame, projectedFrame)
|
||||||
|
|
||||||
|
var updatedContentAreaInScreenSpace = transitionInfo.contentAreaInScreenSpace
|
||||||
|
updatedContentAreaInScreenSpace.origin.x = 0.0
|
||||||
|
updatedContentAreaInScreenSpace.size.width = self.bounds.width
|
||||||
|
}
|
||||||
|
|
||||||
|
let intermediateCompletion: () -> Void = {
|
||||||
|
if completedEffect && completedContentNode && completedActionsNode {
|
||||||
|
switch result {
|
||||||
|
case .default, .custom:
|
||||||
|
break
|
||||||
|
case .dismissWithoutContent:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
completion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if #available(iOS 10.0, *) {
|
||||||
|
if let propertyAnimator = self.propertyAnimator {
|
||||||
|
let propertyAnimator = propertyAnimator as? UIViewPropertyAnimator
|
||||||
|
propertyAnimator?.stopAnimation(true)
|
||||||
|
}
|
||||||
|
self.propertyAnimator = UIViewPropertyAnimator(duration: transitionDuration, curve: .easeInOut, animations: { [weak self] in
|
||||||
|
self?.effectView.effect = nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if let _ = self.propertyAnimator {
|
||||||
|
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||||
|
self.displayLinkAnimator = DisplayLinkAnimator(duration: 0.2 * animationDurationFactor, from: 0.0, to: 0.999, update: { [weak self] value in
|
||||||
|
(self?.propertyAnimator as? UIViewPropertyAnimator)?.fractionComplete = value
|
||||||
|
}, completion: {
|
||||||
|
completedEffect = true
|
||||||
|
intermediateCompletion()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
self.effectView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.05 * animationDurationFactor, delay: 0.15, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false)
|
||||||
|
} else {
|
||||||
|
UIView.animate(withDuration: 0.21 * animationDurationFactor, animations: {
|
||||||
|
if #available(iOS 9.0, *) {
|
||||||
|
self.effectView.effect = nil
|
||||||
|
} else {
|
||||||
|
self.effectView.alpha = 0.0
|
||||||
|
}
|
||||||
|
}, completion: { _ in
|
||||||
|
completedEffect = true
|
||||||
|
intermediateCompletion()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: transitionDuration * animationDurationFactor, removeOnCompletion: false)
|
||||||
|
self.actionsContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2 * animationDurationFactor, removeOnCompletion: false, completion: { _ in
|
||||||
|
completedActionsNode = true
|
||||||
|
intermediateCompletion()
|
||||||
|
})
|
||||||
|
self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2 * animationDurationFactor, removeOnCompletion: false, completion: { _ in
|
||||||
|
})
|
||||||
|
self.actionsContainerNode.layer.animateScale(from: 1.0, to: 0.1, duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false)
|
||||||
|
self.contentContainerNode.layer.animateScale(from: 1.0, to: 0.01, duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false)
|
||||||
|
|
||||||
|
let animateOutToItem: Bool
|
||||||
|
switch result {
|
||||||
|
case .default, .custom:
|
||||||
|
animateOutToItem = true
|
||||||
|
case .dismissWithoutContent:
|
||||||
|
animateOutToItem = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if animateOutToItem, let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame {
|
||||||
|
let actionsSideInset: CGFloat = 11.0
|
||||||
|
|
||||||
|
let localSourceFrame = self.view.convert(CGRect(origin: CGPoint(x: actionsSideInset, y: originalProjectedContentViewFrame.1.minY), size: CGSize(width: actionsSideInset, height: originalProjectedContentViewFrame.1.height)), to: self.scrollNode.view)
|
||||||
|
|
||||||
|
self.actionsContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y), duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false, additive: true)
|
||||||
|
let contentContainerOffset = CGPoint(x: localSourceFrame.center.x - self.contentContainerNode.frame.center.x, y: localSourceFrame.center.y - self.contentContainerNode.frame.center.y)
|
||||||
|
self.contentContainerNode.layer.animatePosition(from: CGPoint(), to: contentContainerOffset, duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false, additive: true, completion: { _ in
|
||||||
|
completedContentNode = true
|
||||||
|
intermediateCompletion()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
if let snapshotView = controller.view.snapshotContentTree() {
|
||||||
|
self.contentContainerNode.view.addSubview(snapshotView)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.contentContainerNode.allowsGroupOpacity = true
|
||||||
|
self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: transitionDuration * animationDurationFactor, removeOnCompletion: false, completion: { _ in
|
||||||
|
completedContentNode = true
|
||||||
|
intermediateCompletion()
|
||||||
|
})
|
||||||
|
|
||||||
|
if let reactionContextNode = self.reactionContextNode {
|
||||||
|
reactionContextNode.animateOut(to: nil, animatingOutToReaction: self.reactionContextNodeIsAnimatingOut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateOutToReaction(value: String, into targetNode: ASImageNode, hideNode: Bool, completion: @escaping () -> Void) {
|
func animateOutToReaction(value: String, into targetNode: ASImageNode, hideNode: Bool, completion: @escaping () -> Void) {
|
||||||
@ -646,13 +812,16 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
}
|
}
|
||||||
let actionsBottomInset: CGFloat = 11.0
|
let actionsBottomInset: CGFloat = 11.0
|
||||||
|
|
||||||
if let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame, let contentParentNode = self.contentParentNode {
|
if let contentNode = self.contentContainerNode.contentNode {
|
||||||
|
switch contentNode {
|
||||||
|
case let .extracted(contentParentNode):
|
||||||
|
if let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame {
|
||||||
let isInitialLayout = self.actionsContainerNode.frame.size.width.isZero
|
let isInitialLayout = self.actionsContainerNode.frame.size.width.isZero
|
||||||
let previousContainerFrame = self.view.convert(self.contentContainerNode.frame, from: self.scrollNode.view)
|
let previousContainerFrame = self.view.convert(self.contentContainerNode.frame, from: self.scrollNode.view)
|
||||||
|
|
||||||
let actionsSize = self.actionsContainerNode.updateLayout(constrainedWidth: layout.size.width - actionsSideInset * 2.0, transition: actionsContainerTransition)
|
let actionsSize = self.actionsContainerNode.updateLayout(constrainedWidth: layout.size.width - actionsSideInset * 2.0, transition: actionsContainerTransition)
|
||||||
let contentSize = originalProjectedContentViewFrame.1.size
|
let contentSize = originalProjectedContentViewFrame.1.size
|
||||||
self.contentContainerNode.updateLayout(size: contentSize, transition: transition)
|
self.contentContainerNode.updateLayout(size: contentSize, scaledSize: contentSize, transition: transition)
|
||||||
|
|
||||||
let maximumActionsFrameOrigin = max(60.0, layout.size.height - layout.intrinsicInsets.bottom - actionsBottomInset - actionsSize.height)
|
let maximumActionsFrameOrigin = max(60.0, layout.size.height - layout.intrinsicInsets.bottom - actionsBottomInset - actionsSize.height)
|
||||||
var originalActionsFrame = CGRect(origin: CGPoint(x: max(actionsSideInset, min(layout.size.width - actionsSize.width - actionsSideInset, originalProjectedContentViewFrame.1.minX)), y: min(originalProjectedContentViewFrame.1.maxY + contentActionsSpacing, maximumActionsFrameOrigin)), size: actionsSize)
|
var originalActionsFrame = CGRect(origin: CGPoint(x: max(actionsSideInset, min(layout.size.width - actionsSize.width - actionsSideInset, originalProjectedContentViewFrame.1.minX)), y: min(originalProjectedContentViewFrame.1.maxY + contentActionsSpacing, maximumActionsFrameOrigin)), size: actionsSize)
|
||||||
@ -697,6 +866,63 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX + contentParentNode.contentRect.minX, y: absoluteContentRect.minY + contentParentNode.contentRect.minY), size: contentParentNode.contentRect.size), transition: transition)
|
reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX + contentParentNode.contentRect.minX, y: absoluteContentRect.minY + contentParentNode.contentRect.minY), size: contentParentNode.contentRect.size), transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case let .controller(contentParentNode):
|
||||||
|
let topEdge = max(contentTopInset, self.contentAreaInScreenSpace?.minY ?? 0.0)
|
||||||
|
|
||||||
|
contentParentNode.updateLayout(size: layout.size, transition: transition)
|
||||||
|
|
||||||
|
let isInitialLayout = self.actionsContainerNode.frame.size.width.isZero
|
||||||
|
let previousContainerFrame = self.view.convert(self.contentContainerNode.frame, from: self.scrollNode.view)
|
||||||
|
|
||||||
|
let actionsSize = self.actionsContainerNode.updateLayout(constrainedWidth: layout.size.width - actionsSideInset * 2.0, transition: actionsContainerTransition)
|
||||||
|
let contentScale = (layout.size.width - actionsSideInset * 2.0) / layout.size.width
|
||||||
|
let proposedContentHeight = layout.size.height - topEdge - contentActionsSpacing - actionsSize.height - layout.intrinsicInsets.bottom - actionsBottomInset
|
||||||
|
let contentUnscaledSize = CGSize(width: layout.size.width, height: max(400.0, proposedContentHeight))
|
||||||
|
let contentSize = CGSize(width: floor(contentUnscaledSize.width * contentScale), height: floor(contentUnscaledSize.height * contentScale))
|
||||||
|
|
||||||
|
self.contentContainerNode.updateLayout(size: contentUnscaledSize, scaledSize: contentSize, transition: transition)
|
||||||
|
|
||||||
|
let maximumActionsFrameOrigin = max(60.0, layout.size.height - layout.intrinsicInsets.bottom - actionsBottomInset - actionsSize.height)
|
||||||
|
var originalActionsFrame = CGRect(origin: CGPoint(x: actionsSideInset, y: maximumActionsFrameOrigin), size: actionsSize)
|
||||||
|
var originalContentFrame = CGRect(origin: CGPoint(x: actionsSideInset, y: originalActionsFrame.minY - contentActionsSpacing - contentSize.height), size: contentSize)
|
||||||
|
if originalContentFrame.minY < topEdge {
|
||||||
|
let requiredOffset = topEdge - originalContentFrame.minY
|
||||||
|
let availableOffset = max(0.0, layout.size.height - layout.intrinsicInsets.bottom - actionsBottomInset - originalActionsFrame.maxY)
|
||||||
|
let offset = min(requiredOffset, availableOffset)
|
||||||
|
originalActionsFrame = originalActionsFrame.offsetBy(dx: 0.0, dy: offset)
|
||||||
|
originalContentFrame = originalContentFrame.offsetBy(dx: 0.0, dy: offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
let contentHeight = max(layout.size.height, max(layout.size.height, originalActionsFrame.maxY + actionsBottomInset) - originalContentFrame.minY + contentTopInset)
|
||||||
|
|
||||||
|
let scrollContentSize = CGSize(width: layout.size.width, height: contentHeight)
|
||||||
|
if self.scrollNode.view.contentSize != scrollContentSize {
|
||||||
|
self.scrollNode.view.contentSize = scrollContentSize
|
||||||
|
}
|
||||||
|
|
||||||
|
let overflowOffset = min(0.0, originalContentFrame.minY - contentTopInset)
|
||||||
|
|
||||||
|
let contentContainerFrame = originalContentFrame
|
||||||
|
transition.updateFrame(node: self.contentContainerNode, frame: contentContainerFrame.offsetBy(dx: 0.0, dy: -overflowOffset))
|
||||||
|
actionsContainerTransition.updateFrame(node: self.actionsContainerNode, frame: originalActionsFrame.offsetBy(dx: 0.0, dy: -overflowOffset))
|
||||||
|
|
||||||
|
if isInitialLayout {
|
||||||
|
self.scrollNode.view.contentOffset = CGPoint(x: 0.0, y: -overflowOffset)
|
||||||
|
let currentContainerFrame = self.view.convert(self.contentContainerNode.frame, from: self.scrollNode.view)
|
||||||
|
if overflowOffset < 0.0 {
|
||||||
|
transition.animateOffsetAdditive(node: self.scrollNode, offset: currentContainerFrame.minY - previousContainerFrame.minY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let absoluteContentRect = contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y)
|
||||||
|
|
||||||
|
if let reactionContextNode = self.reactionContextNode {
|
||||||
|
let insets = layout.insets(options: [.statusBar])
|
||||||
|
transition.updateFrame(node: reactionContextNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||||
|
reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX, y: absoluteContentRect.minY), size: contentSize), transition: transition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let previousActionsContainerNode = previousActionsContainerNode {
|
if let previousActionsContainerNode = previousActionsContainerNode {
|
||||||
if transition.isAnimated {
|
if transition.isAnimated {
|
||||||
@ -718,7 +944,10 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
if let contentParentNode = self.contentParentNode, let layout = self.validLayout {
|
guard let layout = self.validLayout else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let maybeContentNode = self.contentContainerNode.contentNode, case let .extracted(contentParentNode) = maybeContentNode {
|
||||||
let contentContainerFrame = self.contentContainerNode.frame
|
let contentContainerFrame = self.contentContainerNode.frame
|
||||||
contentParentNode.updateAbsoluteRect?(contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y), layout.size)
|
contentParentNode.updateAbsoluteRect?(contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y), layout.size)
|
||||||
}
|
}
|
||||||
@ -734,7 +963,9 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mappedPoint = self.view.convert(point, to: self.scrollNode.view)
|
let mappedPoint = self.view.convert(point, to: self.scrollNode.view)
|
||||||
if let contentParentNode = self.contentParentNode {
|
if let maybeContentNode = self.contentContainerNode.contentNode {
|
||||||
|
switch maybeContentNode {
|
||||||
|
case let .extracted(contentParentNode):
|
||||||
let contentPoint = self.view.convert(point, to: contentParentNode.contentNode.view)
|
let contentPoint = self.view.convert(point, to: contentParentNode.contentNode.view)
|
||||||
if let result = contentParentNode.contentNode.hitTest(contentPoint, with: event) {
|
if let result = contentParentNode.contentNode.hitTest(contentPoint, with: event) {
|
||||||
if result is TextSelectionNodeView {
|
if result is TextSelectionNodeView {
|
||||||
@ -743,6 +974,9 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||||||
return contentParentNode.contentNode.view
|
return contentParentNode.contentNode.view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case let .controller(controller):
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.actionsContainerNode.frame.contains(mappedPoint) {
|
if self.actionsContainerNode.frame.contains(mappedPoint) {
|
||||||
@ -765,9 +999,11 @@ public final class ContextControllerTakeViewInfo {
|
|||||||
|
|
||||||
public final class ContextControllerTakeControllerInfo {
|
public final class ContextControllerTakeControllerInfo {
|
||||||
public let contentAreaInScreenSpace: CGRect
|
public let contentAreaInScreenSpace: CGRect
|
||||||
|
public let sourceNode: () -> (ASDisplayNode, CGRect)?
|
||||||
|
|
||||||
public init(contentAreaInScreenSpace: CGRect) {
|
public init(contentAreaInScreenSpace: CGRect, sourceNode: @escaping () -> (ASDisplayNode, CGRect)?) {
|
||||||
self.contentAreaInScreenSpace = contentAreaInScreenSpace
|
self.contentAreaInScreenSpace = contentAreaInScreenSpace
|
||||||
|
self.sourceNode = sourceNode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ private func traceDeceleratingScrollView(_ view: UIView, at point: CGPoint) -> B
|
|||||||
|
|
||||||
public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer {
|
public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer {
|
||||||
private let contentAtPoint: (CGPoint) -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>?
|
private let contentAtPoint: (CGPoint) -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>?
|
||||||
private let present: (PeekControllerContent, ASDisplayNode) -> PeekController?
|
private let present: (PeekControllerContent, ASDisplayNode) -> ViewController?
|
||||||
private let updateContent: (PeekControllerContent?) -> Void
|
private let updateContent: (PeekControllerContent?) -> Void
|
||||||
private let activateBySingleTap: Bool
|
private let activateBySingleTap: Bool
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer {
|
|||||||
private var menuActivation: PeerkControllerMenuActivation?
|
private var menuActivation: PeerkControllerMenuActivation?
|
||||||
private weak var presentedController: PeekController?
|
private weak var presentedController: PeekController?
|
||||||
|
|
||||||
public init(contentAtPoint: @escaping (CGPoint) -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>?, present: @escaping (PeekControllerContent, ASDisplayNode) -> PeekController?, updateContent: @escaping (PeekControllerContent?) -> Void = { _ in }, activateBySingleTap: Bool = false) {
|
public init(contentAtPoint: @escaping (CGPoint) -> Signal<(ASDisplayNode, PeekControllerContent)?, NoError>?, present: @escaping (PeekControllerContent, ASDisplayNode) -> ViewController?, updateContent: @escaping (PeekControllerContent?) -> Void = { _ in }, activateBySingleTap: Bool = false) {
|
||||||
self.contentAtPoint = contentAtPoint
|
self.contentAtPoint = contentAtPoint
|
||||||
self.present = present
|
self.present = present
|
||||||
self.updateContent = updateContent
|
self.updateContent = updateContent
|
||||||
@ -259,6 +259,7 @@ public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let presentedController = strongSelf.present(content, sourceNode) {
|
if let presentedController = strongSelf.present(content, sourceNode) {
|
||||||
|
if let presentedController = presentedController as? PeekController {
|
||||||
if forceActivate {
|
if forceActivate {
|
||||||
strongSelf.candidateContent = nil
|
strongSelf.candidateContent = nil
|
||||||
if case .press = content.menuActivation() {
|
if case .press = content.menuActivation() {
|
||||||
@ -284,6 +285,11 @@ public final class PeekControllerGestureRecognizer: UIPanGestureRecognizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if strongSelf.state != .ended {
|
||||||
|
strongSelf.state = .ended
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if strongSelf.presentedController == nil {
|
} else if strongSelf.presentedController == nil {
|
||||||
|
@ -224,6 +224,8 @@ open class ViewControllerPresentationArguments {
|
|||||||
public var scrollToTopWithTabBar: (() -> Void)?
|
public var scrollToTopWithTabBar: (() -> Void)?
|
||||||
public var longTapWithTabBar: (() -> Void)?
|
public var longTapWithTabBar: (() -> Void)?
|
||||||
|
|
||||||
|
public var customPresentPreviewingController: ((ViewController, ASDisplayNode) -> ViewController?)?
|
||||||
|
|
||||||
open func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
open func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -491,12 +493,14 @@ open class ViewControllerPresentationArguments {
|
|||||||
|
|
||||||
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
||||||
open func registerForPreviewing(with delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, theme: PeekControllerTheme, onlyNative: Bool) {
|
open func registerForPreviewing(with delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, theme: PeekControllerTheme, onlyNative: Bool) {
|
||||||
if self.traitCollection.forceTouchCapability == .available {
|
if false, self.traitCollection.forceTouchCapability == .available {
|
||||||
let _ = super.registerForPreviewing(with: delegate, sourceView: sourceView)
|
let _ = super.registerForPreviewing(with: delegate, sourceView: sourceView)
|
||||||
} else if !onlyNative {
|
} else if !onlyNative {
|
||||||
if self.previewingContext == nil {
|
if self.previewingContext == nil {
|
||||||
let previewingContext = SimulatedViewControllerPreviewing(theme: theme, delegate: delegate, sourceView: sourceView, node: self.displayNode, present: { [weak self] c, a in
|
let previewingContext = SimulatedViewControllerPreviewing(theme: theme, delegate: delegate, sourceView: sourceView, node: self.displayNode, present: { [weak self] c, a in
|
||||||
self?.presentInGlobalOverlay(c, with: a)
|
self?.presentInGlobalOverlay(c, with: a)
|
||||||
|
}, customPresent: { [weak self] c, n in
|
||||||
|
return self?.customPresentPreviewingController?(c, n)
|
||||||
})
|
})
|
||||||
self.previewingContext = previewingContext
|
self.previewingContext = previewingContext
|
||||||
}
|
}
|
||||||
@ -505,10 +509,12 @@ open class ViewControllerPresentationArguments {
|
|||||||
|
|
||||||
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
||||||
public func registerForPreviewingNonNative(with delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, theme: PeekControllerTheme) {
|
public func registerForPreviewingNonNative(with delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, theme: PeekControllerTheme) {
|
||||||
if self.traitCollection.forceTouchCapability != .available {
|
if true || self.traitCollection.forceTouchCapability != .available {
|
||||||
if self.previewingContext == nil {
|
if self.previewingContext == nil {
|
||||||
let previewingContext = SimulatedViewControllerPreviewing(theme: theme, delegate: delegate, sourceView: sourceView, node: self.displayNode, present: { [weak self] c, a in
|
let previewingContext = SimulatedViewControllerPreviewing(theme: theme, delegate: delegate, sourceView: sourceView, node: self.displayNode, present: { [weak self] c, a in
|
||||||
self?.presentInGlobalOverlay(c, with: a)
|
self?.presentInGlobalOverlay(c, with: a)
|
||||||
|
}, customPresent: { [weak self] c, n in
|
||||||
|
return self?.customPresentPreviewingController?(c, n)
|
||||||
})
|
})
|
||||||
self.previewingContext = previewingContext
|
self.previewingContext = previewingContext
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import SwiftSignalKit
|
|||||||
|
|
||||||
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
@available(iOSApplicationExtension 9.0, iOS 9.0, *)
|
||||||
private final class ViewControllerPeekContent: PeekControllerContent {
|
private final class ViewControllerPeekContent: PeekControllerContent {
|
||||||
private let controller: ViewController
|
let controller: ViewController
|
||||||
private let menu: [PeekControllerMenuItem]
|
private let menu: [PeekControllerMenuItem]
|
||||||
|
|
||||||
init(controller: ViewController) {
|
init(controller: ViewController) {
|
||||||
@ -101,7 +101,7 @@ final class SimulatedViewControllerPreviewing: NSObject, UIViewControllerPreview
|
|||||||
|
|
||||||
var sourceRect: CGRect = CGRect()
|
var sourceRect: CGRect = CGRect()
|
||||||
|
|
||||||
init(theme: PeekControllerTheme, delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, node: ASDisplayNode, present: @escaping (ViewController, Any?) -> Void) {
|
init(theme: PeekControllerTheme, delegate: UIViewControllerPreviewingDelegate, sourceView: UIView, node: ASDisplayNode, present: @escaping (ViewController, Any?) -> Void, customPresent: ((ViewController, ASDisplayNode) -> ViewController?)?) {
|
||||||
self.delegateImpl = delegate
|
self.delegateImpl = delegate
|
||||||
self.sourceView = sourceView
|
self.sourceView = sourceView
|
||||||
self.node = node
|
self.node = node
|
||||||
@ -109,11 +109,16 @@ final class SimulatedViewControllerPreviewing: NSObject, UIViewControllerPreview
|
|||||||
self.recognizer = PeekControllerGestureRecognizer(contentAtPoint: { point in
|
self.recognizer = PeekControllerGestureRecognizer(contentAtPoint: { point in
|
||||||
return contentAtPointImpl?(point)
|
return contentAtPointImpl?(point)
|
||||||
}, present: { content, sourceNode in
|
}, present: { content, sourceNode in
|
||||||
|
if let content = content as? ViewControllerPeekContent, let controller = customPresent?(content.controller, sourceNode) {
|
||||||
|
present(controller, nil)
|
||||||
|
return controller
|
||||||
|
} else {
|
||||||
let controller = PeekController(theme: theme, content: content, sourceNode: {
|
let controller = PeekController(theme: theme, content: content, sourceNode: {
|
||||||
return sourceNode
|
return sourceNode
|
||||||
})
|
})
|
||||||
present(controller, nil)
|
present(controller, nil)
|
||||||
return controller
|
return controller
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
node.view.addGestureRecognizer(self.recognizer)
|
node.view.addGestureRecognizer(self.recognizer)
|
||||||
|
@ -1277,6 +1277,14 @@ final class SharedApplicationContext {
|
|||||||
self.isInForegroundPromise.set(true)
|
self.isInForegroundPromise.set(true)
|
||||||
self.isActiveValue = true
|
self.isActiveValue = true
|
||||||
self.isActivePromise.set(true)
|
self.isActivePromise.set(true)
|
||||||
|
|
||||||
|
let configuration = URLSessionConfiguration.background(withIdentifier: "org.telegram.Telegram-iOS.background")
|
||||||
|
let session = URLSession(configuration: configuration)
|
||||||
|
if #available(iOS 9.0, *) {
|
||||||
|
session.getAllTasks(completionHandler: { tasks in
|
||||||
|
print(tasks)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationWillTerminate(_ application: UIApplication) {
|
func applicationWillTerminate(_ application: UIApplication) {
|
||||||
@ -1741,6 +1749,11 @@ final class SharedApplicationContext {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
|
||||||
|
Logger.shared.log("App \(self.episodeId)", "handleEventsForBackgroundURLSession \(identifier)")
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
|
||||||
override var next: UIResponder? {
|
override var next: UIResponder? {
|
||||||
if let context = self.contextValue, let controller = context.context.keyShortcutsController {
|
if let context = self.contextValue, let controller = context.context.keyShortcutsController {
|
||||||
return controller
|
return controller
|
||||||
|
@ -563,7 +563,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if Namespaces.Message.allScheduled.contains(message.id.namespace) {
|
if Namespaces.Message.allScheduled.contains(message.id.namespace) {
|
||||||
reactionItems = []
|
reactionItems = []
|
||||||
}
|
}
|
||||||
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: reactionItems, recognizer: recognizer)
|
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message)), items: actions, reactionItems: reactionItems, recognizer: recognizer)
|
||||||
strongSelf.currentContextController = controller
|
strongSelf.currentContextController = controller
|
||||||
controller.reactionSelected = { [weak controller] value in
|
controller.reactionSelected = { [weak controller] value in
|
||||||
guard let strongSelf = self, let message = updatedMessages.first else {
|
guard let strongSelf = self, let message = updatedMessages.first else {
|
||||||
@ -1392,7 +1392,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: [], recognizer: nil)
|
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message)), items: actions, reactionItems: [], recognizer: nil)
|
||||||
strongSelf.currentContextController = controller
|
strongSelf.currentContextController = controller
|
||||||
strongSelf.window?.presentInGlobalOverlay(controller)
|
strongSelf.window?.presentInGlobalOverlay(controller)
|
||||||
})
|
})
|
||||||
@ -1432,7 +1432,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
f(.dismissWithoutContent)
|
f(.dismissWithoutContent)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, reactionItems: [], recognizer: nil)
|
let controller = ContextController(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, message: message)), items: actions, reactionItems: [], recognizer: nil)
|
||||||
strongSelf.currentContextController = controller
|
strongSelf.currentContextController = controller
|
||||||
strongSelf.window?.presentInGlobalOverlay(controller)
|
strongSelf.window?.presentInGlobalOverlay(controller)
|
||||||
})
|
})
|
||||||
|
@ -832,7 +832,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
}
|
}
|
||||||
strongSelf.fetchDisposable.set(visibilityAwareFetchSignal.start())
|
strongSelf.fetchDisposable.set(visibilityAwareFetchSignal.start())
|
||||||
}
|
}
|
||||||
} else if case .prefetch = automaticDownload, message.id.namespace != Namespaces.Message.SecretIncoming && message.id.namespace != Namespaces.Message.Local {
|
} else if case .prefetch = automaticDownload, message.id.namespace != Namespaces.Message.SecretIncoming /*&& message.id.namespace != Namespaces.Message.Local*/ {
|
||||||
if let file = media as? TelegramMediaFile {
|
if let file = media as? TelegramMediaFile {
|
||||||
let fetchSignal = preloadVideoResource(postbox: context.account.postbox, resourceReference: AnyMediaReference.message(message: MessageReference(message), media: file).resourceReference(file.resource), duration: 4.0)
|
let fetchSignal = preloadVideoResource(postbox: context.account.postbox, resourceReference: AnyMediaReference.message(message: MessageReference(message), media: file).resourceReference(file.resource), duration: 4.0)
|
||||||
let visibilityAwareFetchSignal = strongSelf.visibilityPromise.get()
|
let visibilityAwareFetchSignal = strongSelf.visibilityPromise.get()
|
||||||
|
@ -73,6 +73,151 @@ struct VideoConversionConfiguration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class FetchVideoLibraryMediaResourceItem {
|
||||||
|
let priority: MediaBoxFetchPriority
|
||||||
|
let signal: Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>
|
||||||
|
let next: (MediaResourceDataFetchResult) -> Void
|
||||||
|
let error: (MediaResourceDataFetchError) -> Void
|
||||||
|
let completion: () -> Void
|
||||||
|
var isActive: Bool = false
|
||||||
|
var disposable: Disposable?
|
||||||
|
|
||||||
|
init(priority: MediaBoxFetchPriority, signal: Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, next: @escaping (MediaResourceDataFetchResult) -> Void, error: @escaping (MediaResourceDataFetchError) -> Void, completion: @escaping () -> Void) {
|
||||||
|
self.priority = priority
|
||||||
|
self.signal = signal
|
||||||
|
self.next = next
|
||||||
|
self.error = error
|
||||||
|
self.completion = completion
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.disposable?.dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let fetchVideoLimit: Int = 2
|
||||||
|
|
||||||
|
private final class FetchVideoLibraryMediaResourceContextImpl {
|
||||||
|
private let queue: Queue
|
||||||
|
var items: [FetchVideoLibraryMediaResourceItem] = []
|
||||||
|
|
||||||
|
init(queue: Queue) {
|
||||||
|
self.queue = queue
|
||||||
|
}
|
||||||
|
|
||||||
|
func add(priority: MediaBoxFetchPriority, signal: Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>, next: @escaping (MediaResourceDataFetchResult) -> Void, error: @escaping (MediaResourceDataFetchError) -> Void, completion: @escaping () -> Void) -> Disposable {
|
||||||
|
let queue = self.queue
|
||||||
|
|
||||||
|
let item = FetchVideoLibraryMediaResourceItem(priority: priority, signal: signal, next: next, error: error, completion: completion)
|
||||||
|
self.items.append(item)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
return ActionDisposable { [weak self, weak item] in
|
||||||
|
queue.async {
|
||||||
|
guard let strongSelf = self, let item = item else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i in 0 ..< strongSelf.items.count {
|
||||||
|
if strongSelf.items[i] === item {
|
||||||
|
strongSelf.items[i].disposable?.dispose()
|
||||||
|
strongSelf.items.remove(at: i)
|
||||||
|
strongSelf.update()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func update() {
|
||||||
|
let queue = self.queue
|
||||||
|
|
||||||
|
var activeCount = 0
|
||||||
|
for item in self.items {
|
||||||
|
if item.isActive {
|
||||||
|
activeCount += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while activeCount < fetchVideoLimit {
|
||||||
|
var maxPriorityIndex: Int?
|
||||||
|
for i in 0 ..< self.items.count {
|
||||||
|
if !self.items[i].isActive {
|
||||||
|
if let maxPriorityIndexValue = maxPriorityIndex {
|
||||||
|
if self.items[i].priority.rawValue > self.items[maxPriorityIndexValue].priority.rawValue {
|
||||||
|
maxPriorityIndex = i
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maxPriorityIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let maxPriorityIndex = maxPriorityIndex {
|
||||||
|
let item = self.items[maxPriorityIndex]
|
||||||
|
item.isActive = true
|
||||||
|
activeCount += 1
|
||||||
|
assert(item.disposable == nil)
|
||||||
|
item.disposable = self.items[maxPriorityIndex].signal.start(next: { [weak item] value in
|
||||||
|
queue.async {
|
||||||
|
item?.next(value)
|
||||||
|
}
|
||||||
|
}, error: { [weak item] value in
|
||||||
|
queue.async {
|
||||||
|
item?.error(value)
|
||||||
|
}
|
||||||
|
}, completed: { [weak self, weak item] in
|
||||||
|
queue.async {
|
||||||
|
guard let strongSelf = self, let item = item else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for i in 0 ..< strongSelf.items.count {
|
||||||
|
if strongSelf.items[i] === item {
|
||||||
|
strongSelf.items.remove(at: i)
|
||||||
|
item.completion()
|
||||||
|
strongSelf.update()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class FetchVideoLibraryMediaResourceContext {
|
||||||
|
private let queue = Queue()
|
||||||
|
private let impl: QueueLocalObject<FetchVideoLibraryMediaResourceContextImpl>
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let queue = self.queue
|
||||||
|
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||||
|
return FetchVideoLibraryMediaResourceContextImpl(queue: queue)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrap(priority: MediaBoxFetchPriority, signal: Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError>) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||||
|
return Signal { subscriber in
|
||||||
|
let disposable = MetaDisposable()
|
||||||
|
self.impl.with { impl in
|
||||||
|
disposable.set(impl.add(priority: priority, signal: signal, next: { value in
|
||||||
|
subscriber.putNext(value)
|
||||||
|
}, error: { error in
|
||||||
|
subscriber.putError(error)
|
||||||
|
}, completion: {
|
||||||
|
subscriber.putCompletion()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return disposable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private let throttlingContext = FetchVideoLibraryMediaResourceContext()
|
||||||
|
|
||||||
public func fetchVideoLibraryMediaResource(postbox: Postbox, resource: VideoLibraryMediaResource) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
public func fetchVideoLibraryMediaResource(postbox: Postbox, resource: VideoLibraryMediaResource) -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> {
|
||||||
return postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
return postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
||||||
|> take(1)
|
|> take(1)
|
||||||
@ -82,9 +227,8 @@ public func fetchVideoLibraryMediaResource(postbox: Postbox, resource: VideoLibr
|
|||||||
|> introduceError(MediaResourceDataFetchError.self)
|
|> introduceError(MediaResourceDataFetchError.self)
|
||||||
|> mapToSignal { appConfiguration -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> in
|
|> mapToSignal { appConfiguration -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> in
|
||||||
let config = VideoConversionConfiguration.with(appConfiguration: appConfiguration)
|
let config = VideoConversionConfiguration.with(appConfiguration: appConfiguration)
|
||||||
return Signal { subscriber in
|
let signal = Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> { subscriber in
|
||||||
subscriber.putNext(.reset)
|
subscriber.putNext(.reset)
|
||||||
|
|
||||||
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [resource.localIdentifier], options: nil)
|
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [resource.localIdentifier], options: nil)
|
||||||
var requestId: PHImageRequestID?
|
var requestId: PHImageRequestID?
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
@ -189,6 +333,7 @@ public func fetchVideoLibraryMediaResource(postbox: Postbox, resource: VideoLibr
|
|||||||
disposable.dispose()
|
disposable.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return throttlingContext.wrap(priority: .default, signal: signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +346,7 @@ func fetchLocalFileVideoMediaResource(postbox: Postbox, resource: LocalFileVideo
|
|||||||
|> introduceError(MediaResourceDataFetchError.self)
|
|> introduceError(MediaResourceDataFetchError.self)
|
||||||
|> mapToSignal { appConfiguration -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> in
|
|> mapToSignal { appConfiguration -> Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> in
|
||||||
let config = VideoConversionConfiguration.with(appConfiguration: appConfiguration)
|
let config = VideoConversionConfiguration.with(appConfiguration: appConfiguration)
|
||||||
return Signal { subscriber in
|
let signal = Signal<MediaResourceDataFetchResult, MediaResourceDataFetchError> { subscriber in
|
||||||
subscriber.putNext(.reset)
|
subscriber.putNext(.reset)
|
||||||
|
|
||||||
let avAsset = AVURLAsset(url: URL(fileURLWithPath: resource.path))
|
let avAsset = AVURLAsset(url: URL(fileURLWithPath: resource.path))
|
||||||
@ -267,6 +412,7 @@ func fetchLocalFileVideoMediaResource(postbox: Postbox, resource: LocalFileVideo
|
|||||||
disposable.dispose()
|
disposable.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return throttlingContext.wrap(priority: .default, signal: signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user