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
|
||||
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .empty))
|
||||
}).start()
|
||||
})]), on: .root, blockInteraction: false)
|
||||
})]), on: .root, blockInteraction: false, completion: {})
|
||||
})
|
||||
], actionLayout: .vertical)
|
||||
contentNode.textAttributeAction = (NSAttributedStringKey(rawValue: TelegramTextAttributes.URL), { value in
|
||||
@@ -251,7 +251,7 @@ public final class AuthorizationSequenceController: NavigationController {
|
||||
controller?.dismissAnimated()
|
||||
}
|
||||
strongSelf.view.endEditing(true)
|
||||
strongSelf.currentWindow?.present(controller, on: .root, blockInteraction: false)
|
||||
strongSelf.currentWindow?.present(controller, on: .root, blockInteraction: false, completion: {})
|
||||
}
|
||||
presentAlertAgainImpl = {
|
||||
presentAlertImpl()
|
||||
|
||||
@@ -88,7 +88,20 @@ private func preparedChatMediaInputGridEntryTransition(account: Account, view: I
|
||||
} else if !toEntries.isEmpty {
|
||||
if let collectionId = collectionId {
|
||||
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
|
||||
if !fromEntries.isEmpty && fromEntries[0].index < toEntries[i].index {
|
||||
directionHint = .down
|
||||
@@ -537,49 +550,49 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
self.addSubnode(self.collectionListContainer)
|
||||
|
||||
let itemCollectionsView = self.itemCollectionsViewPosition.get()
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { position -> Signal<(ItemCollectionsView, StickerPacksCollectionUpdate), NoError> in
|
||||
switch position {
|
||||
case .initial:
|
||||
var firstTime = true
|
||||
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: nil, count: 50)
|
||||
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
||||
let update: StickerPacksCollectionUpdate
|
||||
if firstTime {
|
||||
firstTime = false
|
||||
update = .initial
|
||||
} else {
|
||||
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)
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { position -> Signal<(ItemCollectionsView, StickerPacksCollectionUpdate), NoError> in
|
||||
switch position {
|
||||
case .initial:
|
||||
var firstTime = true
|
||||
return account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers], namespaces: [Namespaces.ItemCollection.CloudStickerPacks], aroundIndex: nil, count: 50)
|
||||
|> map { view -> (ItemCollectionsView, StickerPacksCollectionUpdate) in
|
||||
let update: StickerPacksCollectionUpdate
|
||||
if firstTime {
|
||||
firstTime = false
|
||||
update = .initial
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let previousEntries = Atomic<([ChatMediaInputPanelEntry], [ChatMediaInputGridEntry])>(value: ([], []))
|
||||
@@ -666,8 +679,12 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
|
||||
if let topVisibleSection = visibleItems.topSectionVisible as? ChatMediaInputStickerGridSection {
|
||||
topVisibleCollectionId = topVisibleSection.collectionId
|
||||
} else if let topVisible = visibleItems.topVisible, let item = topVisible.1 as? ChatMediaInputStickerGridItem {
|
||||
topVisibleCollectionId = item.index.collectionId
|
||||
} else if let topVisible = visibleItems.topVisible {
|
||||
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 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 transformedCopyViewFinalFrame = self.imageNode.view.convert(self.imageNode.view.bounds, to: self.view)
|
||||
|
||||
let surfaceCopyView = 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)
|
||||
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.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)
|
||||
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)
|
||||
|
||||
transformedFrame.origin = CGPoint()
|
||||
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) {
|
||||
self.fetchDisposable.set(nil)
|
||||
|
||||
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 transformedSelfFrame = node.0.view.convert(node.0.view.bounds, to: self.view)
|
||||
@@ -192,18 +224,30 @@ final class InstantImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var copyCompleted = false
|
||||
|
||||
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)
|
||||
copyView.frame = transformedSelfFrame
|
||||
|
||||
let intermediateCompletion = { [weak copyView] in
|
||||
let intermediateCompletion = { [weak copyView, weak surfaceCopyView] in
|
||||
if positionCompleted && boundsCompleted && copyCompleted {
|
||||
copyView?.removeFromSuperview()
|
||||
surfaceCopyView?.removeFromSuperview()
|
||||
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)
|
||||
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()
|
||||
})
|
||||
|
||||
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
|
||||
positionCompleted = true
|
||||
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()
|
||||
self.imageNode.layer.animateBounds(from: self.imageNode.layer.bounds, to: transformedFrame, duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||
boundsCompleted = true
|
||||
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) {
|
||||
|
||||
@@ -1195,7 +1195,10 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if let strongSelf = self {
|
||||
for (_, itemNode) in strongSelf.visibleItemsWithNodes {
|
||||
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 {
|
||||
var dismissImpl: (() -> Void)?
|
||||
let legacyController = LegacyImagePickerController(presentation: .modal(animateIn: true), theme: theme, completion: { image in
|
||||
dismissImpl?()
|
||||
completion(image)
|
||||
})
|
||||
|
||||
@@ -41,9 +39,5 @@ func legacyImagePicker(theme: PresentationTheme, completion: @escaping (UIImage?
|
||||
|
||||
legacyController.bind(controller: imagePickerController)
|
||||
|
||||
dismissImpl = { [weak legacyController] in
|
||||
legacyController?.dismiss()
|
||||
}
|
||||
|
||||
return legacyController
|
||||
}
|
||||
|
||||
@@ -121,12 +121,14 @@ public struct AudioSessionActivationState {
|
||||
public class ManagedAudioSessionControl {
|
||||
private let setupImpl: (Bool) -> Void
|
||||
private let activateImpl: (ManagedAudioSessionControlActivate) -> Void
|
||||
private let setupAndActivateImpl: (Bool, ManagedAudioSessionControlActivate) -> 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.activateImpl = activateImpl
|
||||
self.setOutputModeImpl = setOutputModeImpl
|
||||
self.setupAndActivateImpl = setupAndActivateImpl
|
||||
}
|
||||
|
||||
public func setup(synchronous: Bool = false) {
|
||||
@@ -137,6 +139,10 @@ public class ManagedAudioSessionControl {
|
||||
self.activateImpl(ManagedAudioSessionControlActivate(completion))
|
||||
}
|
||||
|
||||
public func setupAndActivate(synchronous: Bool = false, _ completion: @escaping (AudioSessionActivationState) -> Void) {
|
||||
self.setupAndActivateImpl(synchronous, ManagedAudioSessionControlActivate(completion))
|
||||
}
|
||||
|
||||
public func setOutputMode(_ mode: AudioSessionOutputMode) {
|
||||
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 {
|
||||
return self.push(audioSessionType: audioSessionType, once: once, manualActivate: { control in
|
||||
control.setup()
|
||||
control.activate({ state in
|
||||
control.setupAndActivate(synchronous: false, { state in
|
||||
activate(state)
|
||||
})
|
||||
}, deactivate: deactivate)
|
||||
@@ -361,21 +366,21 @@ public final class ManagedAudioSession {
|
||||
let queue = self.queue
|
||||
queue.async {
|
||||
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 {
|
||||
if holder.id == id && holder.active {
|
||||
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode)
|
||||
strongSelf.setup(type: audioSessionType, outputMode: holder.outputMode, activateNow: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if synchronous {
|
||||
strongSelf.queue.sync(f)
|
||||
} else {
|
||||
strongSelf.queue.async(f)
|
||||
}
|
||||
}
|
||||
|
||||
if synchronous {
|
||||
queue.sync(f)
|
||||
} else {
|
||||
queue.async(f)
|
||||
}
|
||||
}, activateImpl: { [weak self] completion in
|
||||
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
|
||||
manualActivate(state)
|
||||
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 = nil
|
||||
|
||||
@@ -600,9 +625,13 @@ public final class ManagedAudioSession {
|
||||
case .record, .voiceCall:
|
||||
options.insert(.allowBluetooth)
|
||||
}
|
||||
try AVAudioSession.sharedInstance().setCategory(nativeCategoryForType(type, headphones: self.isHeadsetPluggedInValue), with: options)
|
||||
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 {
|
||||
print("ManagedAudioSession setup error \(error)")
|
||||
}
|
||||
@@ -618,6 +647,10 @@ public final class ManagedAudioSession {
|
||||
subscriber(true)
|
||||
}
|
||||
}
|
||||
|
||||
if activateNow {
|
||||
self.activate()
|
||||
}
|
||||
}
|
||||
|
||||
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)applyServerConfig:(NSString * _Nullable)data;
|
||||
+ (int32_t)maxLayer;
|
||||
|
||||
@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);
|
||||
|
||||
@@ -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 {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
|
||||
@@ -205,7 +205,7 @@ public func openExternalUrl(account: Account, context: OpenURLContext = .generic
|
||||
|
||||
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()
|
||||
})
|
||||
@@ -436,7 +436,7 @@ public func openExternalUrl(account: Account, context: OpenURLContext = .generic
|
||||
account.telegramApplicationContext.applicationBindings.dismissNativeController()
|
||||
|
||||
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
|
||||
|
||||
@@ -62,6 +62,10 @@ public final class PresentationCallManager {
|
||||
private var callSettings: (VoiceCallSettings, VoipConfiguration)?
|
||||
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) {
|
||||
self.account = account
|
||||
self.getDeviceAccessData = getDeviceAccessData
|
||||
|
||||
@@ -72,15 +72,30 @@ final class ThemeGridController: ViewController {
|
||||
self?.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}, selectCustomWallpaper: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(legacyImagePicker(theme: strongSelf.presentationData.theme, completion: { image in
|
||||
if let strongSelf = self, let image = image {
|
||||
strongSelf.present(legacyWallpaperEditor(theme: strongSelf.presentationData.theme, image: image, completion: { image in
|
||||
if let image = image {
|
||||
self?.applyCustomWallpaperImage(image)
|
||||
}
|
||||
}), in: .window(.root))
|
||||
var completionImpl: ((UIImage?) -> Void)?
|
||||
let legacyPicker = legacyImagePicker(theme: strongSelf.presentationData.theme, completion: { image in
|
||||
completionImpl?(image)
|
||||
})
|
||||
var lastPresentationTimestamp = 0.0
|
||||
completionImpl = { [weak legacyPicker] image in
|
||||
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())
|
||||
|
||||
Reference in New Issue
Block a user