mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
UI fixes
This commit is contained in:
@@ -238,7 +238,7 @@ public final class AuthorizationSequenceController: NavigationController {
|
|||||||
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
|
let _ = (strongSelf.account.postbox.transaction { transaction -> Void in
|
||||||
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
|
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
|
||||||
}).start()
|
}).start()
|
||||||
})]), on: .root, blockInteraction: false)
|
})]), on: .root, blockInteraction: false, completion: {})
|
||||||
})
|
})
|
||||||
], actionLayout: .vertical)
|
], actionLayout: .vertical)
|
||||||
contentNode.textAttributeAction = (NSAttributedStringKey(rawValue: TelegramTextAttributes.URL), { value in
|
contentNode.textAttributeAction = (NSAttributedStringKey(rawValue: TelegramTextAttributes.URL), { value in
|
||||||
@@ -251,7 +251,7 @@ public final class AuthorizationSequenceController: NavigationController {
|
|||||||
controller?.dismissAnimated()
|
controller?.dismissAnimated()
|
||||||
}
|
}
|
||||||
strongSelf.view.endEditing(true)
|
strongSelf.view.endEditing(true)
|
||||||
strongSelf.currentWindow?.present(controller, on: .root, blockInteraction: false)
|
strongSelf.currentWindow?.present(controller, on: .root, blockInteraction: false, completion: {})
|
||||||
}
|
}
|
||||||
presentAlertAgainImpl = {
|
presentAlertAgainImpl = {
|
||||||
presentAlertImpl()
|
presentAlertImpl()
|
||||||
|
|||||||
@@ -88,7 +88,20 @@ private func preparedChatMediaInputGridEntryTransition(account: Account, view: I
|
|||||||
} else if !toEntries.isEmpty {
|
} else if !toEntries.isEmpty {
|
||||||
if let collectionId = collectionId {
|
if let collectionId = collectionId {
|
||||||
for i in 0 ..< toEntries.count {
|
for i in 0 ..< toEntries.count {
|
||||||
if case let .collectionIndex(collectionIndex) = toEntries[i].index, collectionIndex.collectionId == collectionId {
|
var indexMatches = false
|
||||||
|
switch toEntries[i].index {
|
||||||
|
case let .collectionIndex(collectionIndex):
|
||||||
|
if collectionIndex.collectionId == collectionId {
|
||||||
|
indexMatches = true
|
||||||
|
}
|
||||||
|
case .peerSpecificSetup:
|
||||||
|
if collectionId.namespace == ChatMediaInputPanelAuxiliaryNamespace.peerSpecific.rawValue {
|
||||||
|
indexMatches = true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if indexMatches {
|
||||||
var directionHint: GridNodePreviousItemsTransitionDirectionHint = .up
|
var directionHint: GridNodePreviousItemsTransitionDirectionHint = .up
|
||||||
if !fromEntries.isEmpty && fromEntries[0].index < toEntries[i].index {
|
if !fromEntries.isEmpty && fromEntries[0].index < toEntries[i].index {
|
||||||
directionHint = .down
|
directionHint = .down
|
||||||
@@ -537,49 +550,49 @@ final class ChatMediaInputNode: ChatInputNode {
|
|||||||
self.addSubnode(self.collectionListContainer)
|
self.addSubnode(self.collectionListContainer)
|
||||||
|
|
||||||
let itemCollectionsView = self.itemCollectionsViewPosition.get()
|
let itemCollectionsView = self.itemCollectionsViewPosition.get()
|
||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|> mapToSignal { position -> Signal<(ItemCollectionsView, StickerPacksCollectionUpdate), NoError> in
|
|> mapToSignal { position -> Signal<(ItemCollectionsView, StickerPacksCollectionUpdate), NoError> in
|
||||||
switch position {
|
switch position {
|
||||||
case .initial:
|
case .initial:
|
||||||
var firstTime = true
|
var firstTime = true
|
||||||
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: nil, count: 50)
|
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: nil, count: 50)
|
||||||
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
||||||
let update: StickerPacksCollectionUpdate
|
let update: StickerPacksCollectionUpdate
|
||||||
if firstTime {
|
if firstTime {
|
||||||
firstTime = false
|
firstTime = false
|
||||||
update = .initial
|
update = .initial
|
||||||
} else {
|
} else {
|
||||||
update = .generic
|
update = .generic
|
||||||
}
|
|
||||||
return (view, update)
|
|
||||||
}
|
|
||||||
case let .scroll(aroundIndex):
|
|
||||||
var firstTime = true
|
|
||||||
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: aroundIndex, count: 300)
|
|
||||||
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
|
||||||
let update: StickerPacksCollectionUpdate
|
|
||||||
if firstTime {
|
|
||||||
firstTime = false
|
|
||||||
update = .scroll
|
|
||||||
} else {
|
|
||||||
update = .generic
|
|
||||||
}
|
|
||||||
return (view, update)
|
|
||||||
}
|
|
||||||
case let .navigate(index, collectionId):
|
|
||||||
var firstTime = true
|
|
||||||
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: index, count: 300)
|
|
||||||
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
|
||||||
let update: StickerPacksCollectionUpdate
|
|
||||||
if firstTime {
|
|
||||||
firstTime = false
|
|
||||||
update = .navigate(index, collectionId)
|
|
||||||
} else {
|
|
||||||
update = .generic
|
|
||||||
}
|
|
||||||
return (view, update)
|
|
||||||
}
|
}
|
||||||
}
|
return (view, update)
|
||||||
|
}
|
||||||
|
case let .scroll(aroundIndex):
|
||||||
|
var firstTime = true
|
||||||
|
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: aroundIndex, count: 300)
|
||||||
|
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
||||||
|
let update: StickerPacksCollectionUpdate
|
||||||
|
if firstTime {
|
||||||
|
firstTime = false
|
||||||
|
update = .scroll
|
||||||
|
} else {
|
||||||
|
update = .generic
|
||||||
|
}
|
||||||
|
return (view, update)
|
||||||
|
}
|
||||||
|
case let .navigate(index, collectionId):
|
||||||
|
var firstTime = true
|
||||||
|
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: index, count: 300)
|
||||||
|
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
||||||
|
let update: StickerPacksCollectionUpdate
|
||||||
|
if firstTime {
|
||||||
|
firstTime = false
|
||||||
|
update = .navigate(index, collectionId)
|
||||||
|
} else {
|
||||||
|
update = .generic
|
||||||
|
}
|
||||||
|
return (view, update)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let previousEntries = Atomic<([ChatMediaInputPanelEntry], [ChatMediaInputGridEntry])>(value: ([], []))
|
let previousEntries = Atomic<([ChatMediaInputPanelEntry], [ChatMediaInputGridEntry])>(value: ([], []))
|
||||||
@@ -666,8 +679,12 @@ final class ChatMediaInputNode: ChatInputNode {
|
|||||||
|
|
||||||
if let topVisibleSection = visibleItems.topSectionVisible as? ChatMediaInputStickerGridSection {
|
if let topVisibleSection = visibleItems.topSectionVisible as? ChatMediaInputStickerGridSection {
|
||||||
topVisibleCollectionId = topVisibleSection.collectionId
|
topVisibleCollectionId = topVisibleSection.collectionId
|
||||||
} else if let topVisible = visibleItems.topVisible, let item = topVisible.1 as? ChatMediaInputStickerGridItem {
|
} else if let topVisible = visibleItems.topVisible {
|
||||||
topVisibleCollectionId = item.index.collectionId
|
if let item = topVisible.1 as? ChatMediaInputStickerGridItem {
|
||||||
|
topVisibleCollectionId = item.index.collectionId
|
||||||
|
} else if let _ = topVisible.1 as? StickerPanePeerSpecificSetupGridItem {
|
||||||
|
topVisibleCollectionId = ItemCollectionId(namespace: ChatMediaInputPanelAuxiliaryNamespace.peerSpecific.rawValue, id: 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let collectionId = topVisibleCollectionId {
|
if let collectionId = topVisibleCollectionId {
|
||||||
if strongSelf.inputNodeInteraction.highlightedItemCollectionId != collectionId {
|
if strongSelf.inputNodeInteraction.highlightedItemCollectionId != collectionId {
|
||||||
|
|||||||
@@ -161,27 +161,59 @@ final class InstantImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
let transformedSelfFrame = node.0.view.convert(node.0.view.bounds, to: self.view)
|
let transformedSelfFrame = node.0.view.convert(node.0.view.bounds, to: self.view)
|
||||||
let transformedCopyViewFinalFrame = self.imageNode.view.convert(self.imageNode.view.bounds, to: self.view)
|
let transformedCopyViewFinalFrame = self.imageNode.view.convert(self.imageNode.view.bounds, to: self.view)
|
||||||
|
|
||||||
|
let surfaceCopyView = node.1()!
|
||||||
let copyView = node.1()!
|
let copyView = node.1()!
|
||||||
|
|
||||||
|
addToTransitionSurface(surfaceCopyView)
|
||||||
|
|
||||||
|
var transformedSurfaceFrame: CGRect?
|
||||||
|
var transformedSurfaceFinalFrame: CGRect?
|
||||||
|
if let contentSurface = surfaceCopyView.superview {
|
||||||
|
transformedSurfaceFrame = node.0.view.convert(node.0.view.bounds, to: contentSurface)
|
||||||
|
transformedSurfaceFinalFrame = self.imageNode.view.convert(self.imageNode.view.bounds, to: contentSurface)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let transformedSurfaceFrame = transformedSurfaceFrame {
|
||||||
|
surfaceCopyView.frame = transformedSurfaceFrame
|
||||||
|
}
|
||||||
|
|
||||||
self.view.insertSubview(copyView, belowSubview: self.scrollNode.view)
|
self.view.insertSubview(copyView, belowSubview: self.scrollNode.view)
|
||||||
copyView.frame = transformedSelfFrame
|
copyView.frame = transformedSelfFrame
|
||||||
|
|
||||||
copyView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { [weak copyView] _ in
|
copyView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, removeOnCompletion: false)
|
||||||
|
|
||||||
|
surfaceCopyView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
|
||||||
|
|
||||||
|
let positionDuration: Double = 0.21
|
||||||
|
|
||||||
|
copyView.layer.animatePosition(from: CGPoint(x: transformedSelfFrame.midX, y: transformedSelfFrame.midY), to: CGPoint(x: transformedCopyViewFinalFrame.midX, y: transformedCopyViewFinalFrame.midY), duration: positionDuration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { [weak copyView] _ in
|
||||||
copyView?.removeFromSuperview()
|
copyView?.removeFromSuperview()
|
||||||
})
|
})
|
||||||
|
|
||||||
copyView.layer.animatePosition(from: CGPoint(x: transformedSelfFrame.midX, y: transformedSelfFrame.midY), to: CGPoint(x: transformedCopyViewFinalFrame.midX, y: transformedCopyViewFinalFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
|
||||||
let scale = CGSize(width: transformedCopyViewFinalFrame.size.width / transformedSelfFrame.size.width, height: transformedCopyViewFinalFrame.size.height / transformedSelfFrame.size.height)
|
let scale = CGSize(width: transformedCopyViewFinalFrame.size.width / transformedSelfFrame.size.width, height: transformedCopyViewFinalFrame.size.height / transformedSelfFrame.size.height)
|
||||||
copyView.layer.animate(from: NSValue(caTransform3D: CATransform3DIdentity), to: NSValue(caTransform3D: CATransform3DMakeScale(scale.width, scale.height, 1.0)), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25, removeOnCompletion: false)
|
copyView.layer.animate(from: NSValue(caTransform3D: CATransform3DIdentity), to: NSValue(caTransform3D: CATransform3DMakeScale(scale.width, scale.height, 1.0)), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25, removeOnCompletion: false)
|
||||||
|
|
||||||
self.imageNode.layer.animatePosition(from: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), to: self.imageNode.layer.position, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring)
|
if let transformedSurfaceFrame = transformedSurfaceFrame, let transformedSurfaceFinalFrame = transformedSurfaceFinalFrame {
|
||||||
|
surfaceCopyView.layer.animatePosition(from: CGPoint(x: transformedSurfaceFrame.midX, y: transformedSurfaceFrame.midY), to: CGPoint(x: transformedCopyViewFinalFrame.midX, y: transformedCopyViewFinalFrame.midY), duration: positionDuration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { [weak surfaceCopyView] _ in
|
||||||
|
surfaceCopyView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
let scale = CGSize(width: transformedSurfaceFinalFrame.size.width / transformedSurfaceFrame.size.width, height: transformedSurfaceFinalFrame.size.height / transformedSurfaceFrame.size.height)
|
||||||
|
surfaceCopyView.layer.animate(from: NSValue(caTransform3D: CATransform3DIdentity), to: NSValue(caTransform3D: CATransform3DMakeScale(scale.width, scale.height, 1.0)), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25, removeOnCompletion: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.imageNode.layer.animatePosition(from: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), to: self.imageNode.layer.position, duration: positionDuration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
self.imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
self.imageNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1)
|
||||||
|
|
||||||
transformedFrame.origin = CGPoint()
|
transformedFrame.origin = CGPoint()
|
||||||
self.imageNode.layer.animateBounds(from: transformedFrame, to: self.imageNode.layer.bounds, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring)
|
self.imageNode.layer.animateBounds(from: transformedFrame, to: self.imageNode.layer.bounds, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
|
||||||
|
/*self.statusNodeContainer.layer.animatePosition(from: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), to: self.statusNodeContainer.position, duration: positionDuration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
self.statusNodeContainer.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring)
|
||||||
|
self.statusNodeContainer.layer.animateScale(from: 0.5, to: 1.0, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
override func animateOut(to node: (ASDisplayNode, () -> UIView?), addToTransitionSurface: (UIView) -> Void, completion: @escaping () -> Void) {
|
override func animateOut(to node: (ASDisplayNode, () -> UIView?), addToTransitionSurface: (UIView) -> Void, completion: @escaping () -> Void) {
|
||||||
|
self.fetchDisposable.set(nil)
|
||||||
|
|
||||||
var transformedFrame = node.0.view.convert(node.0.view.bounds, to: self.imageNode.view)
|
var transformedFrame = node.0.view.convert(node.0.view.bounds, to: self.imageNode.view)
|
||||||
let transformedSuperFrame = node.0.view.convert(node.0.view.bounds, to: self.imageNode.view.superview)
|
let transformedSuperFrame = node.0.view.convert(node.0.view.bounds, to: self.imageNode.view.superview)
|
||||||
let transformedSelfFrame = node.0.view.convert(node.0.view.bounds, to: self.view)
|
let transformedSelfFrame = node.0.view.convert(node.0.view.bounds, to: self.view)
|
||||||
@@ -192,18 +224,30 @@ final class InstantImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
var copyCompleted = false
|
var copyCompleted = false
|
||||||
|
|
||||||
let copyView = node.1()!
|
let copyView = node.1()!
|
||||||
|
let surfaceCopyView = node.1()!
|
||||||
|
|
||||||
|
addToTransitionSurface(surfaceCopyView)
|
||||||
|
|
||||||
|
var transformedSurfaceFrame: CGRect?
|
||||||
|
var transformedSurfaceCopyViewInitialFrame: CGRect?
|
||||||
|
if let contentSurface = surfaceCopyView.superview {
|
||||||
|
transformedSurfaceFrame = node.0.view.convert(node.0.view.bounds, to: contentSurface)
|
||||||
|
transformedSurfaceCopyViewInitialFrame = self.imageNode.view.convert(self.imageNode.view.bounds, to: contentSurface)
|
||||||
|
}
|
||||||
|
|
||||||
self.view.insertSubview(copyView, belowSubview: self.scrollNode.view)
|
self.view.insertSubview(copyView, belowSubview: self.scrollNode.view)
|
||||||
copyView.frame = transformedSelfFrame
|
copyView.frame = transformedSelfFrame
|
||||||
|
|
||||||
let intermediateCompletion = { [weak copyView] in
|
let intermediateCompletion = { [weak copyView, weak surfaceCopyView] in
|
||||||
if positionCompleted && boundsCompleted && copyCompleted {
|
if positionCompleted && boundsCompleted && copyCompleted {
|
||||||
copyView?.removeFromSuperview()
|
copyView?.removeFromSuperview()
|
||||||
|
surfaceCopyView?.removeFromSuperview()
|
||||||
completion()
|
completion()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
copyView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.1, removeOnCompletion: false)
|
copyView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, removeOnCompletion: false)
|
||||||
|
surfaceCopyView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.025, removeOnCompletion: false)
|
||||||
|
|
||||||
copyView.layer.animatePosition(from: CGPoint(x: transformedCopyViewInitialFrame.midX, y: transformedCopyViewInitialFrame.midY), to: CGPoint(x: transformedSelfFrame.midX, y: transformedSelfFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
copyView.layer.animatePosition(from: CGPoint(x: transformedCopyViewInitialFrame.midX, y: transformedCopyViewInitialFrame.midY), to: CGPoint(x: transformedSelfFrame.midX, y: transformedSelfFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
let scale = CGSize(width: transformedCopyViewInitialFrame.size.width / transformedSelfFrame.size.width, height: transformedCopyViewInitialFrame.size.height / transformedSelfFrame.size.height)
|
let scale = CGSize(width: transformedCopyViewInitialFrame.size.width / transformedSelfFrame.size.width, height: transformedCopyViewInitialFrame.size.height / transformedSelfFrame.size.height)
|
||||||
@@ -212,18 +256,27 @@ final class InstantImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
intermediateCompletion()
|
intermediateCompletion()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if let transformedSurfaceFrame = transformedSurfaceFrame, let transformedCopyViewInitialFrame = transformedSurfaceCopyViewInitialFrame {
|
||||||
|
surfaceCopyView.layer.animatePosition(from: CGPoint(x: transformedCopyViewInitialFrame.midX, y: transformedCopyViewInitialFrame.midY), to: CGPoint(x: transformedSurfaceFrame.midX, y: transformedSurfaceFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
|
let scale = CGSize(width: transformedCopyViewInitialFrame.size.width / transformedSurfaceFrame.size.width, height: transformedCopyViewInitialFrame.size.height / transformedSurfaceFrame.size.height)
|
||||||
|
surfaceCopyView.layer.animate(from: NSValue(caTransform3D: CATransform3DMakeScale(scale.width, scale.height, 1.0)), to: NSValue(caTransform3D: CATransform3DIdentity), keyPath: "transform", timingFunction: kCAMediaTimingFunctionSpring, duration: 0.25, removeOnCompletion: false)
|
||||||
|
}
|
||||||
|
|
||||||
self.imageNode.layer.animatePosition(from: self.imageNode.layer.position, to: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
self.imageNode.layer.animatePosition(from: self.imageNode.layer.position, to: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||||
positionCompleted = true
|
positionCompleted = true
|
||||||
intermediateCompletion()
|
intermediateCompletion()
|
||||||
})
|
})
|
||||||
|
|
||||||
self.imageNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
|
self.imageNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.08, removeOnCompletion: false)
|
||||||
|
|
||||||
transformedFrame.origin = CGPoint()
|
transformedFrame.origin = CGPoint()
|
||||||
self.imageNode.layer.animateBounds(from: self.imageNode.layer.bounds, to: transformedFrame, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
self.imageNode.layer.animateBounds(from: self.imageNode.layer.bounds, to: transformedFrame, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||||
boundsCompleted = true
|
boundsCompleted = true
|
||||||
intermediateCompletion()
|
intermediateCompletion()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*self.statusNodeContainer.layer.animatePosition(from: self.statusNodeContainer.position, to: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
|
||||||
|
self.statusNodeContainer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, timingFunction: kCAMediaTimingFunctionEaseIn, removeOnCompletion: false)*/
|
||||||
}
|
}
|
||||||
|
|
||||||
override func visibilityUpdated(isVisible: Bool) {
|
override func visibilityUpdated(isVisible: Bool) {
|
||||||
|
|||||||
@@ -1195,7 +1195,10 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
for (_, itemNode) in strongSelf.visibleItemsWithNodes {
|
for (_, itemNode) in strongSelf.visibleItemsWithNodes {
|
||||||
if let transitionNode = itemNode.transitionNode(media: entry.media) {
|
if let transitionNode = itemNode.transitionNode(media: entry.media) {
|
||||||
return GalleryTransitionArguments(transitionNode: transitionNode, addToTransitionSurface: { _ in
|
return GalleryTransitionArguments(transitionNode: transitionNode, addToTransitionSurface: { view in
|
||||||
|
if let strongSelf = self {
|
||||||
|
strongSelf.scrollNode.view.superview?.insertSubview(view, aboveSubview: strongSelf.scrollNode.view)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,7 @@ private final class LegacyImagePickerController: LegacyController, TGLegacyCamer
|
|||||||
}
|
}
|
||||||
|
|
||||||
func legacyImagePicker(theme: PresentationTheme, completion: @escaping (UIImage?) -> Void) -> ViewController {
|
func legacyImagePicker(theme: PresentationTheme, completion: @escaping (UIImage?) -> Void) -> ViewController {
|
||||||
var dismissImpl: (() -> Void)?
|
|
||||||
let legacyController = LegacyImagePickerController(presentation: .modal(animateIn: true), theme: theme, completion: { image in
|
let legacyController = LegacyImagePickerController(presentation: .modal(animateIn: true), theme: theme, completion: { image in
|
||||||
dismissImpl?()
|
|
||||||
completion(image)
|
completion(image)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -41,9 +39,5 @@ func legacyImagePicker(theme: PresentationTheme, completion: @escaping (UIImage?
|
|||||||
|
|
||||||
legacyController.bind(controller: imagePickerController)
|
legacyController.bind(controller: imagePickerController)
|
||||||
|
|
||||||
dismissImpl = { [weak legacyController] in
|
|
||||||
legacyController?.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
return legacyController
|
return legacyController
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,12 +121,14 @@ public struct AudioSessionActivationState {
|
|||||||
public class ManagedAudioSessionControl {
|
public class ManagedAudioSessionControl {
|
||||||
private let setupImpl: (Bool) -> Void
|
private let setupImpl: (Bool) -> Void
|
||||||
private let activateImpl: (ManagedAudioSessionControlActivate) -> Void
|
private let activateImpl: (ManagedAudioSessionControlActivate) -> Void
|
||||||
|
private let setupAndActivateImpl: (Bool, ManagedAudioSessionControlActivate) -> Void
|
||||||
private let setOutputModeImpl: (AudioSessionOutputMode) -> Void
|
private let setOutputModeImpl: (AudioSessionOutputMode) -> Void
|
||||||
|
|
||||||
fileprivate init(setupImpl: @escaping (Bool) -> Void, activateImpl: @escaping (ManagedAudioSessionControlActivate) -> Void, setOutputModeImpl: @escaping (AudioSessionOutputMode) -> Void) {
|
fileprivate init(setupImpl: @escaping (Bool) -> Void, activateImpl: @escaping (ManagedAudioSessionControlActivate) -> Void, setOutputModeImpl: @escaping (AudioSessionOutputMode) -> Void, setupAndActivateImpl: @escaping (Bool, ManagedAudioSessionControlActivate) -> Void) {
|
||||||
self.setupImpl = setupImpl
|
self.setupImpl = setupImpl
|
||||||
self.activateImpl = activateImpl
|
self.activateImpl = activateImpl
|
||||||
self.setOutputModeImpl = setOutputModeImpl
|
self.setOutputModeImpl = setOutputModeImpl
|
||||||
|
self.setupAndActivateImpl = setupAndActivateImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
public func setup(synchronous: Bool = false) {
|
public func setup(synchronous: Bool = false) {
|
||||||
@@ -137,6 +139,10 @@ public class ManagedAudioSessionControl {
|
|||||||
self.activateImpl(ManagedAudioSessionControlActivate(completion))
|
self.activateImpl(ManagedAudioSessionControlActivate(completion))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func setupAndActivate(synchronous: Bool = false, _ completion: @escaping (AudioSessionActivationState) -> Void) {
|
||||||
|
self.setupAndActivateImpl(synchronous, ManagedAudioSessionControlActivate(completion))
|
||||||
|
}
|
||||||
|
|
||||||
public func setOutputMode(_ mode: AudioSessionOutputMode) {
|
public func setOutputMode(_ mode: AudioSessionOutputMode) {
|
||||||
self.setOutputModeImpl(mode)
|
self.setOutputModeImpl(mode)
|
||||||
}
|
}
|
||||||
@@ -349,8 +355,7 @@ public final class ManagedAudioSession {
|
|||||||
|
|
||||||
func push(audioSessionType: ManagedAudioSessionType, outputMode: AudioSessionOutputMode = .system, once: Bool = false, activate: @escaping (AudioSessionActivationState) -> Void, deactivate: @escaping () -> Signal<Void, NoError>) -> Disposable {
|
func push(audioSessionType: ManagedAudioSessionType, outputMode: AudioSessionOutputMode = .system, once: Bool = false, activate: @escaping (AudioSessionActivationState) -> Void, deactivate: @escaping () -> Signal<Void, NoError>) -> Disposable {
|
||||||
return self.push(audioSessionType: audioSessionType, once: once, manualActivate: { control in
|
return self.push(audioSessionType: audioSessionType, once: once, manualActivate: { control in
|
||||||
control.setup()
|
control.setupAndActivate(synchronous: false, { state in
|
||||||
control.activate({ state in
|
|
||||||
activate(state)
|
activate(state)
|
||||||
})
|
})
|
||||||
}, deactivate: deactivate)
|
}, deactivate: deactivate)
|
||||||
@@ -361,21 +366,21 @@ public final class ManagedAudioSession {
|
|||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
queue.async {
|
queue.async {
|
||||||
self.holders.append(HolderRecord(id: id, audioSessionType: audioSessionType, control: ManagedAudioSessionControl(setupImpl: { [weak self] synchronous in
|
self.holders.append(HolderRecord(id: id, audioSessionType: audioSessionType, control: ManagedAudioSessionControl(setupImpl: { [weak self] synchronous in
|
||||||
if let strongSelf = self {
|
let f: () -> Void = {
|
||||||
let f: () -> Void = {
|
if let strongSelf = self {
|
||||||
for holder in strongSelf.holders {
|
for holder in strongSelf.holders {
|
||||||
if holder.id == id && holder.active {
|
if holder.id == id && holder.active {
|
||||||
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode)
|
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode, activateNow: false)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if synchronous {
|
|
||||||
strongSelf.queue.sync(f)
|
if synchronous {
|
||||||
} else {
|
queue.sync(f)
|
||||||
strongSelf.queue.async(f)
|
} else {
|
||||||
}
|
queue.async(f)
|
||||||
}
|
}
|
||||||
}, activateImpl: { [weak self] completion in
|
}, activateImpl: { [weak self] completion in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
@@ -405,6 +410,26 @@ public final class ManagedAudioSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, setupAndActivateImpl: { [weak self] synchronous, completion in
|
||||||
|
queue.async {
|
||||||
|
let f: () -> Void = {
|
||||||
|
if let strongSelf = self {
|
||||||
|
for holder in strongSelf.holders {
|
||||||
|
if holder.id == id && holder.active {
|
||||||
|
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode, activateNow: true)
|
||||||
|
completion.f(AudioSessionActivationState(isHeadsetConnected: strongSelf.isHeadsetPluggedInValue))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if synchronous {
|
||||||
|
queue.sync(f)
|
||||||
|
} else {
|
||||||
|
queue.async(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
}), activate: { [weak self] state in
|
}), activate: { [weak self] state in
|
||||||
manualActivate(state)
|
manualActivate(state)
|
||||||
queue.async {
|
queue.async {
|
||||||
@@ -575,7 +600,7 @@ public final class ManagedAudioSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setup(type: ManagedAudioSessionType, outputMode: AudioSessionOutputMode) {
|
private func setup(type: ManagedAudioSessionType, outputMode: AudioSessionOutputMode, activateNow: Bool) {
|
||||||
self.deactivateTimer?.invalidate()
|
self.deactivateTimer?.invalidate()
|
||||||
self.deactivateTimer = nil
|
self.deactivateTimer = nil
|
||||||
|
|
||||||
@@ -600,9 +625,13 @@ public final class ManagedAudioSession {
|
|||||||
case .record, .voiceCall:
|
case .record, .voiceCall:
|
||||||
options.insert(.allowBluetooth)
|
options.insert(.allowBluetooth)
|
||||||
}
|
}
|
||||||
try AVAudioSession.sharedInstance().setCategory(nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue), with: options)
|
|
||||||
print("ManagedAudioSession setting active \(type != .none)")
|
print("ManagedAudioSession setting active \(type != .none)")
|
||||||
try AVAudioSession.sharedInstance().setMode(type == .voiceCall ? AVAudioSessionModeVoiceChat : AVAudioSessionModeDefault)
|
if #available(iOSApplicationExtension 11.0, *) {
|
||||||
|
try AVAudioSession.sharedInstance().setCategory(nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue), mode: type == .voiceCall ? AVAudioSessionModeVoiceChat : AVAudioSessionModeDefault, routeSharingPolicy: .default, options: options)
|
||||||
|
} else {
|
||||||
|
try AVAudioSession.sharedInstance().setCategory(nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue), with: options)
|
||||||
|
try AVAudioSession.sharedInstance().setMode(type == .voiceCall ? AVAudioSessionModeVoiceChat : AVAudioSessionModeDefault)
|
||||||
|
}
|
||||||
} catch let error {
|
} catch let error {
|
||||||
print("ManagedAudioSession setup error \(error)")
|
print("ManagedAudioSession setup error \(error)")
|
||||||
}
|
}
|
||||||
@@ -618,6 +647,10 @@ public final class ManagedAudioSession {
|
|||||||
subscriber(true)
|
subscriber(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if activateNow {
|
||||||
|
self.activate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupOutputMode(_ outputMode: AudioSessionOutputMode, type: ManagedAudioSessionType) throws {
|
private func setupOutputMode(_ outputMode: AudioSessionOutputMode, type: ManagedAudioSessionType) throws {
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSaving) {
|
|||||||
|
|
||||||
+ (void)setupLoggingFunction:(void (* _Nullable)(NSString * _Nullable))loggingFunction;
|
+ (void)setupLoggingFunction:(void (* _Nullable)(NSString * _Nullable))loggingFunction;
|
||||||
+ (void)applyServerConfig:(NSString * _Nullable)data;
|
+ (void)applyServerConfig:(NSString * _Nullable)data;
|
||||||
|
+ (int32_t)maxLayer;
|
||||||
|
|
||||||
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallState);
|
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallState);
|
||||||
@property (nonatomic, copy) void (^ _Nullable callEnded)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile);
|
@property (nonatomic, copy) void (^ _Nullable callEnded)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile);
|
||||||
|
|||||||
@@ -224,6 +224,10 @@ static int callControllerDataSavingForType(OngoingCallDataSaving type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (int32_t)maxLayer {
|
||||||
|
return tgvoip::VoIPController::connectionMaxLayer;
|
||||||
|
}
|
||||||
|
|
||||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueue> _Nonnull)queue proxy:(VoipProxyServer * _Nullable)proxy networkType:(OngoingCallNetworkType)networkType dataSaving:(OngoingCallDataSaving)dataSaving {
|
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueue> _Nonnull)queue proxy:(VoipProxyServer * _Nullable)proxy networkType:(OngoingCallNetworkType)networkType dataSaving:(OngoingCallDataSaving)dataSaving {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self != nil) {
|
if (self != nil) {
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ public func openExternalUrl(account: Account, context: OpenURLContext = .generic
|
|||||||
|
|
||||||
c.presentationArguments = a
|
c.presentationArguments = a
|
||||||
|
|
||||||
account.telegramApplicationContext.applicationBindings.getWindowHost()?.present(c, on: .root, blockInteraction: false)
|
account.telegramApplicationContext.applicationBindings.getWindowHost()?.present(c, on: .root, blockInteraction: false, completion: {})
|
||||||
}, dismissInput: {
|
}, dismissInput: {
|
||||||
dismissInput()
|
dismissInput()
|
||||||
})
|
})
|
||||||
@@ -436,7 +436,7 @@ public func openExternalUrl(account: Account, context: OpenURLContext = .generic
|
|||||||
account.telegramApplicationContext.applicationBindings.dismissNativeController()
|
account.telegramApplicationContext.applicationBindings.dismissNativeController()
|
||||||
|
|
||||||
navigationController.view.window?.endEditing(true)
|
navigationController.view.window?.endEditing(true)
|
||||||
account.telegramApplicationContext.applicationBindings.getWindowHost()?.present(controller, on: .root, blockInteraction: false)
|
account.telegramApplicationContext.applicationBindings.getWindowHost()?.present(controller, on: .root, blockInteraction: false, completion: {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -62,6 +62,10 @@ public final class PresentationCallManager {
|
|||||||
private var callSettings: (VoiceCallSettings, VoipConfiguration)?
|
private var callSettings: (VoiceCallSettings, VoipConfiguration)?
|
||||||
private var callSettingsDisposable: Disposable?
|
private var callSettingsDisposable: Disposable?
|
||||||
|
|
||||||
|
public static var voipMaxLayer: Int32 {
|
||||||
|
return OngoingCallContext.
|
||||||
|
}
|
||||||
|
|
||||||
public init(account: Account, getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void), networkType: Signal<NetworkType, NoError>, audioSession: ManagedAudioSession, callSessionManager: CallSessionManager) {
|
public init(account: Account, getDeviceAccessData: @escaping () -> (presentationData: PresentationData, present: (ViewController, Any?) -> Void, openSettings: () -> Void), networkType: Signal<NetworkType, NoError>, audioSession: ManagedAudioSession, callSessionManager: CallSessionManager) {
|
||||||
self.account = account
|
self.account = account
|
||||||
self.getDeviceAccessData = getDeviceAccessData
|
self.getDeviceAccessData = getDeviceAccessData
|
||||||
|
|||||||
@@ -72,15 +72,30 @@ final class ThemeGridController: ViewController {
|
|||||||
self?.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
self?.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||||
}, selectCustomWallpaper: { [weak self] in
|
}, selectCustomWallpaper: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.present(legacyImagePicker(theme: strongSelf.presentationData.theme, completion: { image in
|
var completionImpl: ((UIImage?) -> Void)?
|
||||||
if let strongSelf = self, let image = image {
|
let legacyPicker = legacyImagePicker(theme: strongSelf.presentationData.theme, completion: { image in
|
||||||
strongSelf.present(legacyWallpaperEditor(theme: strongSelf.presentationData.theme, image: image, completion: { image in
|
completionImpl?(image)
|
||||||
if let image = image {
|
})
|
||||||
self?.applyCustomWallpaperImage(image)
|
var lastPresentationTimestamp = 0.0
|
||||||
}
|
completionImpl = { [weak legacyPicker] image in
|
||||||
}), in: .window(.root))
|
guard let strongSelf = self, let image = image else {
|
||||||
|
legacyPicker?.dismiss()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}), in: .window(.root))
|
let timestamp = CACurrentMediaTime()
|
||||||
|
if timestamp < lastPresentationTimestamp + 1.0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastPresentationTimestamp = timestamp
|
||||||
|
strongSelf.present(legacyWallpaperEditor(theme: strongSelf.presentationData.theme, image: image, completion: { image in
|
||||||
|
if let image = image {
|
||||||
|
self?.applyCustomWallpaperImage(image)
|
||||||
|
legacyPicker?.dismiss()
|
||||||
|
}
|
||||||
|
}), in: .window(.root))
|
||||||
|
}
|
||||||
|
|
||||||
|
strongSelf.present(legacyPicker, in: .window(.root), blockInteraction: true)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
self._ready.set(self.controllerNode.ready.get())
|
self._ready.set(self.controllerNode.ready.get())
|
||||||
|
|||||||
Reference in New Issue
Block a user