diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index e07d7be3a3..9bc79ab039 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -899,7 +899,9 @@ public protocol SharedAccountContext: AnyObject { func makeStickerPackScreen(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, mainStickerPack: StickerPackReference, stickerPacks: [StickerPackReference], loadedStickerPacks: [LoadedStickerPack], parentNavigationController: NavigationController?, sendSticker: ((FileMediaReference, UIView, CGRect) -> Bool)?) -> ViewController - func makeMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController + func makeMediaPickerScreen(context: AccountContext, completion: @escaping (Any) -> Void) -> ViewController + + func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController func makeProxySettingsController(sharedContext: SharedAccountContext, account: UnauthorizedAccount) -> ViewController diff --git a/submodules/Camera/Sources/Camera.swift b/submodules/Camera/Sources/Camera.swift index 7064d73ebc..8ddb7bcf58 100644 --- a/submodules/Camera/Sources/Camera.swift +++ b/submodules/Camera/Sources/Camera.swift @@ -3,6 +3,7 @@ import UIKit import SwiftSignalKit import AVFoundation import CoreImage +import TelegramCore final class CameraSession { private let singleSession: AVCaptureSession? @@ -82,6 +83,8 @@ final class CameraDeviceContext { private var preferredMaxDimensions: CMVideoDimensions { if self.additional { + //if case .iPhoneXS = DeviceModel.current { +// return CMVideoDimensions(width: 1440, height: 1080) return CMVideoDimensions(width: 1920, height: 1440) } else { return CMVideoDimensions(width: 1920, height: 1080) @@ -194,13 +197,22 @@ private final class CameraContext { self.mainDeviceContext.output.processCodes = { [weak self] codes in self?.detectedCodesPipe.putNext(codes) } + + NotificationCenter.default.addObserver( + self, + selector: #selector(self.sessionRuntimeError), + name: .AVCaptureSessionRuntimeError, + object: self.session.session + ) } + private var isSessionRunning = false func startCapture() { guard !self.session.session.isRunning else { return } self.session.session.startRunning() + self.isSessionRunning = self.session.session.isRunning } func stopCapture(invalidate: Bool = false) { @@ -512,6 +524,27 @@ private final class CameraContext { var detectedCodes: Signal<[CameraCode], NoError> { return self.detectedCodesPipe.signal() } + + @objc private func sessionInterruptionEnded(notification: NSNotification) { + } + + @objc private func sessionRuntimeError(notification: NSNotification) { + guard let errorValue = notification.userInfo?[AVCaptureSessionErrorKey] as? NSError else { + return + } + + let error = AVError(_nsError: errorValue) + Logger.shared.log("Camera", "Runtime error: \(error)") + + if error.code == .mediaServicesWereReset { + self.queue.async { + if self.isSessionRunning { + self.session.session.startRunning() + self.isSessionRunning = self.session.session.isRunning + } + } + } + } } public final class Camera { diff --git a/submodules/Camera/Sources/CameraDevice.swift b/submodules/Camera/Sources/CameraDevice.swift index 5aeccc34b1..e96335f584 100644 --- a/submodules/Camera/Sources/CameraDevice.swift +++ b/submodules/Camera/Sources/CameraDevice.swift @@ -86,7 +86,7 @@ final class CameraDevice { let subtype = CMFormatDescriptionGetMediaSubType(format.formatDescription) if subtype == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange { for range in format.videoSupportedFrameRateRanges { - if range.maxFrameRate > maxFramerate { + if range.maxFrameRate > 60 { continue outer } } @@ -104,11 +104,23 @@ final class CameraDevice { } } - if let bestFormat = candidates.last { - device.activeFormat = bestFormat + if !candidates.isEmpty { + var bestFormat: AVCaptureDevice.Format? + outer: for format in candidates { + for range in format.videoSupportedFrameRateRanges { + if range.maxFrameRate > maxFramerate { + continue outer + } + bestFormat = format + } + } + if bestFormat == nil { + bestFormat = candidates.last + } + device.activeFormat = bestFormat! Logger.shared.log("Camera", "Selected format:") - Logger.shared.log("Camera", bestFormat.description) + Logger.shared.log("Camera", bestFormat!.description) } else { Logger.shared.log("Camera", "No format selected") } diff --git a/submodules/Camera/Sources/CameraInput.swift b/submodules/Camera/Sources/CameraInput.swift index 67a24c27e6..c058c2127b 100644 --- a/submodules/Camera/Sources/CameraInput.swift +++ b/submodules/Camera/Sources/CameraInput.swift @@ -1,4 +1,5 @@ import AVFoundation +import TelegramCore class CameraInput { var videoInput: AVCaptureDeviceInput? @@ -32,6 +33,8 @@ class CameraInput { } else { session.session.addInput(videoInput) } + } else { + Logger.shared.log("Camera", "Can't add video input") } } } @@ -45,6 +48,8 @@ class CameraInput { self.audioInput = audioInput if session.session.canAddInput(audioInput) { session.session.addInput(audioInput) + } else { + Logger.shared.log("Camera", "Can't add audio input") } } } diff --git a/submodules/Camera/Sources/CameraMetrics.swift b/submodules/Camera/Sources/CameraMetrics.swift index 9c296c8528..20938f5c4a 100644 --- a/submodules/Camera/Sources/CameraMetrics.swift +++ b/submodules/Camera/Sources/CameraMetrics.swift @@ -47,7 +47,7 @@ public extension Camera { } } -enum DeviceModel: CaseIterable { +enum DeviceModel: CaseIterable, Equatable { static var allCases: [DeviceModel] { return [ .iPodTouch1, @@ -72,6 +72,9 @@ enum DeviceModel: CaseIterable { case iPodTouch6 case iPodTouch7 + case iPhoneX + case iPhoneXS + case iPhone12 case iPhone12Mini case iPhone12Pro @@ -89,48 +92,52 @@ enum DeviceModel: CaseIterable { case unknown(String) - var modelId: String? { + var modelId: [String] { switch self { case .iPodTouch1: - return "iPod1,1" + return ["iPod1,1"] case .iPodTouch2: - return "iPod2,1" + return ["iPod2,1"] case .iPodTouch3: - return "iPod3,1" + return ["iPod3,1"] case .iPodTouch4: - return "iPod4,1" + return ["iPod4,1"] case .iPodTouch5: - return "iPod5,1" + return ["iPod5,1"] case .iPodTouch6: - return "iPod7,1" + return ["iPod7,1"] case .iPodTouch7: - return "iPod9,1" + return ["iPod9,1"] + case .iPhoneX: + return ["iPhone11,2"] + case .iPhoneXS: + return ["iPhone11,4", "iPhone11,6"] case .iPhone12: - return "iPhone13,2" + return ["iPhone13,2"] case .iPhone12Mini: - return "iPhone13,1" + return ["iPhone13,1"] case .iPhone12Pro: - return "iPhone13,3" + return ["iPhone13,3"] case .iPhone12ProMax: - return "iPhone13,4" + return ["iPhone13,4"] case .iPhone13: - return "iPhone14,5" + return ["iPhone14,5"] case .iPhone13Mini: - return "iPhone14,4" + return ["iPhone14,4"] case .iPhone13Pro: - return "iPhone14,2" + return ["iPhone14,2"] case .iPhone13ProMax: - return "iPhone14,3" + return ["iPhone14,3"] case .iPhone14: - return "iPhone14,7" + return ["iPhone14,7"] case .iPhone14Plus: - return "iPhone14,8" + return ["iPhone14,8"] case .iPhone14Pro: - return "iPhone15,2" + return ["iPhone15,2"] case .iPhone14ProMax: - return "iPhone15,3" + return ["iPhone15,3"] case let .unknown(modelId): - return modelId + return [modelId] } } @@ -150,6 +157,10 @@ enum DeviceModel: CaseIterable { return "iPod touch 6G" case .iPodTouch7: return "iPod touch 7G" + case .iPhoneX: + return "iPhone X" + case .iPhoneXS: + return "iPhone XS" case .iPhone12: return "iPhone 12" case .iPhone12Mini: @@ -200,7 +211,7 @@ enum DeviceModel: CaseIterable { var result: DeviceModel? if let modelCode { for model in DeviceModel.allCases { - if model.modelId == modelCode { + if model.modelId.contains(modelCode) { result = model break } diff --git a/submodules/Camera/Sources/CameraOutput.swift b/submodules/Camera/Sources/CameraOutput.swift index 8778b6c852..74f8af6fc7 100644 --- a/submodules/Camera/Sources/CameraOutput.swift +++ b/submodules/Camera/Sources/CameraOutput.swift @@ -5,6 +5,7 @@ import SwiftSignalKit import CoreImage import Vision import VideoToolbox +import TelegramCore public enum VideoCaptureResult: Equatable { case finished((String, UIImage, Bool), (String, UIImage, Bool)?, Double, [(Bool, Double)], Double) @@ -124,6 +125,8 @@ final class CameraOutput: NSObject { session.session.addOutput(self.videoOutput) } self.videoOutput.setSampleBufferDelegate(self, queue: self.queue) + } else { + Logger.shared.log("Camera", "Can't add video output") } if audio, session.session.canAddOutput(self.audioOutput) { session.session.addOutput(self.audioOutput) @@ -135,6 +138,8 @@ final class CameraOutput: NSObject { } else { session.session.addOutput(self.photoOutput) } + } else { + Logger.shared.log("Camera", "Can't add photo output") } if metadata, session.session.canAddOutput(self.metadataOutput) { session.session.addOutput(self.metadataOutput) @@ -152,6 +157,8 @@ final class CameraOutput: NSObject { if session.session.canAddConnection(previewConnection) { session.session.addConnection(previewConnection) self.previewConnection = previewConnection + } else { + Logger.shared.log("Camera", "Can't add preview connection") } } @@ -159,6 +166,8 @@ final class CameraOutput: NSObject { if session.session.canAddConnection(videoConnection) { session.session.addConnection(videoConnection) self.videoConnection = videoConnection + } else { + Logger.shared.log("Camera", "Can't add video connection") } if photo { @@ -168,6 +177,8 @@ final class CameraOutput: NSObject { self.photoConnection = photoConnection } } + } else { + Logger.shared.log("Camera", "Can't get video port") } } } diff --git a/submodules/DrawingUI/Sources/DrawingEntitySnapTool.swift b/submodules/DrawingUI/Sources/DrawingEntitySnapTool.swift new file mode 100644 index 0000000000..583b5ba6fc --- /dev/null +++ b/submodules/DrawingUI/Sources/DrawingEntitySnapTool.swift @@ -0,0 +1,375 @@ +import Foundation +import UIKit + +private let snapTimeout = 1.0 + +class DrawingEntitySnapTool { + enum SnapType { + case centerX + case centerY + case top + case left + case right + case bottom + case rotation(CGFloat?) + + static var allPositionTypes: [SnapType] { + return [ + .centerX, + .centerY, + .top, + .left, + .right, + .bottom + ] + } + } + + struct SnapState { + let skipped: CGFloat + let waitForLeave: Bool + } + + private var topEdgeState: SnapState? + private var leftEdgeState: SnapState? + private var rightEdgeState: SnapState? + private var bottomEdgeState: SnapState? + + private var xState: SnapState? + private var yState: SnapState? + + private var rotationState: (angle: CGFloat, skipped: CGFloat, waitForLeave: Bool)? + + var onSnapUpdated: (SnapType, Bool) -> Void = { _, _ in } + + var previousTopEdgeSnapTimestamp: Double? + var previousLeftEdgeSnapTimestamp: Double? + var previousRightEdgeSnapTimestamp: Double? + var previousBottomEdgeSnapTimestamp: Double? + + var previousXSnapTimestamp: Double? + var previousYSnapTimestamp: Double? + var previousRotationSnapTimestamp: Double? + + func reset() { + self.topEdgeState = nil + self.leftEdgeState = nil + self.rightEdgeState = nil + self.bottomEdgeState = nil + self.xState = nil + self.yState = nil + + for type in SnapType.allPositionTypes { + self.onSnapUpdated(type, false) + } + } + + func rotationReset() { + self.rotationState = nil + self.onSnapUpdated(.rotation(nil), false) + } + + func maybeSkipFromStart(entityView: DrawingEntityView, position: CGPoint) { + self.topEdgeState = nil + self.leftEdgeState = nil + self.rightEdgeState = nil + self.bottomEdgeState = nil + + self.xState = nil + self.yState = nil + + let snapXDelta: CGFloat = (entityView.superview?.frame.width ?? 0.0) * 0.02 + let snapYDelta: CGFloat = (entityView.superview?.frame.width ?? 0.0) * 0.02 + + if let snapLocation = (entityView.superview as? DrawingEntitiesView)?.getEntityCenterPosition() { + if position.x > snapLocation.x - snapXDelta && position.x < snapLocation.x + snapXDelta { + self.xState = SnapState(skipped: 0.0, waitForLeave: true) + } + + if position.y > snapLocation.y - snapYDelta && position.y < snapLocation.y + snapYDelta { + self.yState = SnapState(skipped: 0.0, waitForLeave: true) + } + } + } + + func update(entityView: DrawingEntityView, velocity: CGPoint, delta: CGPoint, updatedPosition: CGPoint, size: CGSize) -> CGPoint { + var updatedPosition = updatedPosition + + guard let snapCenterLocation = (entityView.superview as? DrawingEntitiesView)?.getEntityCenterPosition() else { + return updatedPosition + } + let snapEdgeLocations = (entityView.superview as? DrawingEntitiesView)?.getEntityEdgePositions() + + let currentTimestamp = CACurrentMediaTime() + + let snapDelta: CGFloat = (entityView.superview?.frame.width ?? 0.0) * 0.02 + let snapVelocity: CGFloat = snapDelta * 12.0 + let snapSkipTranslation: CGFloat = snapDelta * 2.0 + + let topPoint = updatedPosition.y - size.height / 2.0 + let leftPoint = updatedPosition.x - size.width / 2.0 + let rightPoint = updatedPosition.x + size.width / 2.0 + let bottomPoint = updatedPosition.y + size.height / 2.0 + + func process( + state: SnapState?, + velocity: CGFloat, + delta: CGFloat, + value: CGFloat, + snapVelocity: CGFloat, + snapToValue: CGFloat?, + snapDelta: CGFloat, + snapSkipTranslation: CGFloat, + previousSnapTimestamp: Double?, + onSnapUpdated: (Bool) -> Void + ) -> ( + value: CGFloat, + state: SnapState?, + snapTimestamp: Double? + ) { + var updatedValue = value + var updatedState = state + var updatedPreviousSnapTimestamp = previousSnapTimestamp + if abs(velocity) < snapVelocity || state?.waitForLeave == true { + if let snapToValue { + if let state { + let skipped = state.skipped + let waitForLeave = state.waitForLeave + if waitForLeave { + if value > snapToValue - snapDelta * 2.0 && value < snapToValue + snapDelta * 2.0 { + + } else { + updatedState = nil + } + } else if abs(skipped) < snapSkipTranslation { + updatedState = SnapState(skipped: skipped + delta, waitForLeave: false) + updatedValue = snapToValue + } else { + updatedState = SnapState(skipped: snapSkipTranslation, waitForLeave: true) + onSnapUpdated(false) + } + } else { + if value > snapToValue - snapDelta && value < snapToValue + snapDelta { + if let previousSnapTimestamp, currentTimestamp - previousSnapTimestamp < snapTimeout { + + } else { + updatedPreviousSnapTimestamp = currentTimestamp + updatedState = SnapState(skipped: 0.0, waitForLeave: false) + updatedValue = snapToValue + onSnapUpdated(true) + } + } + } + } + } else { + updatedState = nil + onSnapUpdated(false) + } + return (updatedValue, updatedState, updatedPreviousSnapTimestamp) + } + + let (updatedXValue, updatedXState, updatedXPreviousTimestamp) = process( + state: self.xState, + velocity: velocity.x, + delta: delta.x, + value: updatedPosition.x, + snapVelocity: snapVelocity, + snapToValue: snapCenterLocation.x, + snapDelta: snapDelta, + snapSkipTranslation: snapSkipTranslation, + previousSnapTimestamp: self.previousXSnapTimestamp, + onSnapUpdated: { [weak self] snapped in + self?.onSnapUpdated(.centerX, snapped) + } + ) + self.xState = updatedXState + self.previousXSnapTimestamp = updatedXPreviousTimestamp + + let (updatedYValue, updatedYState, updatedYPreviousTimestamp) = process( + state: self.yState, + velocity: velocity.y, + delta: delta.y, + value: updatedPosition.y, + snapVelocity: snapVelocity, + snapToValue: snapCenterLocation.y, + snapDelta: snapDelta, + snapSkipTranslation: snapSkipTranslation, + previousSnapTimestamp: self.previousYSnapTimestamp, + onSnapUpdated: { [weak self] snapped in + self?.onSnapUpdated(.centerY, snapped) + } + ) + self.yState = updatedYState + self.previousYSnapTimestamp = updatedYPreviousTimestamp + + if let snapEdgeLocations { + if updatedXState == nil { + let (updatedXLeftEdgeValue, updatedLeftEdgeState, updatedLeftEdgePreviousTimestamp) = process( + state: self.leftEdgeState, + velocity: velocity.x, + delta: delta.x, + value: leftPoint, + snapVelocity: snapVelocity, + snapToValue: snapEdgeLocations.left, + snapDelta: snapDelta, + snapSkipTranslation: snapSkipTranslation, + previousSnapTimestamp: self.previousLeftEdgeSnapTimestamp, + onSnapUpdated: { [weak self] snapped in + self?.onSnapUpdated(.left, snapped) + } + ) + self.leftEdgeState = updatedLeftEdgeState + self.previousLeftEdgeSnapTimestamp = updatedLeftEdgePreviousTimestamp + + if updatedLeftEdgeState != nil { + updatedPosition.x = updatedXLeftEdgeValue + size.width / 2.0 + + self.rightEdgeState = nil + self.previousRightEdgeSnapTimestamp = nil + } else { + let (updatedXRightEdgeValue, updatedRightEdgeState, updatedRightEdgePreviousTimestamp) = process( + state: self.rightEdgeState, + velocity: velocity.x, + delta: delta.x, + value: rightPoint, + snapVelocity: snapVelocity, + snapToValue: snapEdgeLocations.right, + snapDelta: snapDelta, + snapSkipTranslation: snapSkipTranslation, + previousSnapTimestamp: self.previousRightEdgeSnapTimestamp, + onSnapUpdated: { [weak self] snapped in + self?.onSnapUpdated(.right, snapped) + } + ) + self.rightEdgeState = updatedRightEdgeState + self.previousRightEdgeSnapTimestamp = updatedRightEdgePreviousTimestamp + + updatedPosition.x = updatedXRightEdgeValue - size.width / 2.0 + } + } else { + updatedPosition.x = updatedXValue + } + + if updatedYState == nil { + let (updatedYTopEdgeValue, updatedTopEdgeState, updatedTopEdgePreviousTimestamp) = process( + state: self.topEdgeState, + velocity: velocity.y, + delta: delta.y, + value: topPoint, + snapVelocity: snapVelocity, + snapToValue: snapEdgeLocations.top, + snapDelta: snapDelta, + snapSkipTranslation: snapSkipTranslation, + previousSnapTimestamp: self.previousTopEdgeSnapTimestamp, + onSnapUpdated: { [weak self] snapped in + self?.onSnapUpdated(.top, snapped) + } + ) + self.topEdgeState = updatedTopEdgeState + self.previousTopEdgeSnapTimestamp = updatedTopEdgePreviousTimestamp + + if updatedTopEdgeState != nil { + updatedPosition.y = updatedYTopEdgeValue + size.height / 2.0 + + self.bottomEdgeState = nil + self.previousBottomEdgeSnapTimestamp = nil + } else { + let (updatedYBottomEdgeValue, updatedBottomEdgeState, updatedBottomEdgePreviousTimestamp) = process( + state: self.bottomEdgeState, + velocity: velocity.y, + delta: delta.y, + value: bottomPoint, + snapVelocity: snapVelocity, + snapToValue: snapEdgeLocations.bottom, + snapDelta: snapDelta, + snapSkipTranslation: snapSkipTranslation, + previousSnapTimestamp: self.previousBottomEdgeSnapTimestamp, + onSnapUpdated: { [weak self] snapped in + self?.onSnapUpdated(.bottom, snapped) + } + ) + self.bottomEdgeState = updatedBottomEdgeState + self.previousBottomEdgeSnapTimestamp = updatedBottomEdgePreviousTimestamp + + updatedPosition.y = updatedYBottomEdgeValue - size.height / 2.0 + } + } else { + updatedPosition.y = updatedYValue + } + } else { + updatedPosition.x = updatedXValue + updatedPosition.y = updatedYValue + } + + return updatedPosition + } + + private let snapRotations: [CGFloat] = [0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0] + func maybeSkipFromStart(entityView: DrawingEntityView, rotation: CGFloat) { + self.rotationState = nil + + let snapDelta: CGFloat = 0.25 + for snapRotation in self.snapRotations { + let snapRotation = snapRotation * .pi + if rotation > snapRotation - snapDelta && rotation < snapRotation + snapDelta { + self.rotationState = (snapRotation, 0.0, true) + break + } + } + } + + func update(entityView: DrawingEntityView, velocity: CGFloat, delta: CGFloat, updatedRotation: CGFloat) -> CGFloat { + var updatedRotation = updatedRotation + if updatedRotation < 0.0 { + updatedRotation = 2.0 * .pi + updatedRotation + } else if updatedRotation > 2.0 * .pi { + while updatedRotation > 2.0 * .pi { + updatedRotation -= 2.0 * .pi + } + } + + let currentTimestamp = CACurrentMediaTime() + + let snapDelta: CGFloat = 0.01 + let snapVelocity: CGFloat = snapDelta * 35.0 + let snapSkipRotation: CGFloat = snapDelta * 40.0 + + if abs(velocity) < snapVelocity || self.rotationState?.waitForLeave == true { + if let (snapRotation, skipped, waitForLeave) = self.rotationState { + if waitForLeave { + if updatedRotation > snapRotation - snapDelta * 2.0 && updatedRotation < snapRotation + snapDelta { + + } else { + self.rotationState = nil + } + } else if abs(skipped) < snapSkipRotation { + self.rotationState = (snapRotation, skipped + delta, false) + updatedRotation = snapRotation + } else { + self.rotationState = (snapRotation, snapSkipRotation, true) + self.onSnapUpdated(.rotation(nil), false) + } + } else { + for snapRotation in self.snapRotations { + let snapRotation = snapRotation * .pi + if updatedRotation > snapRotation - snapDelta && updatedRotation < snapRotation + snapDelta { + if let previousRotationSnapTimestamp, currentTimestamp - previousRotationSnapTimestamp < snapTimeout { + + } else { + self.previousRotationSnapTimestamp = currentTimestamp + self.rotationState = (snapRotation, 0.0, false) + updatedRotation = snapRotation + self.onSnapUpdated(.rotation(snapRotation), true) + } + break + } + } + } + } else { + self.rotationState = nil + self.onSnapUpdated(.rotation(nil), false) + } + + return updatedRotation + } +} diff --git a/submodules/DrawingUI/Sources/DrawingScreen.swift b/submodules/DrawingUI/Sources/DrawingScreen.swift index 08d842c082..064a544fd8 100644 --- a/submodules/DrawingUI/Sources/DrawingScreen.swift +++ b/submodules/DrawingUI/Sources/DrawingScreen.swift @@ -3172,39 +3172,41 @@ public final class DrawingToolsInteraction { } func presentEyedropper(retryLaterForVideo: Bool = true, dismissed: @escaping () -> Void) { -// self.entitiesView.pause() -// -// if self.isVideo && retryLaterForVideo { -// self.updateVideoPlayback(false) -// Queue.mainQueue().after(0.1) { -// self.presentEyedropper(retryLaterForVideo: false, dismissed: dismissed) -// } -// return -// } -// -// guard let currentImage = self.getCurrentImage() else { -// self.entitiesView.play() -// self.updateVideoPlayback(true) -// return -// } -// -// let sourceImage = generateImage(self.drawingView.imageSize, contextGenerator: { size, context in -// let bounds = CGRect(origin: .zero, size: size) -// if let cgImage = currentImage.cgImage { -// context.draw(cgImage, in: bounds) -// } -// if let cgImage = self.drawingView.drawingImage?.cgImage { -// context.draw(cgImage, in: bounds) -// } -// context.translateBy(x: size.width / 2.0, y: size.height / 2.0) -// context.scaleBy(x: 1.0, y: -1.0) -// context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) -// self.entitiesView.layer.render(in: context) -// }, opaque: true, scale: 1.0) -// guard let sourceImage = sourceImage else { -// return -// } -// + self.entitiesView.pause() + + if self.isVideo && retryLaterForVideo { + self.updateVideoPlayback(false) + Queue.mainQueue().after(0.1) { + self.presentEyedropper(retryLaterForVideo: false, dismissed: dismissed) + } + return + } + + guard let currentImage = self.getCurrentImage() else { + self.entitiesView.play() + self.updateVideoPlayback(true) + return + } + + let sourceImage = generateImage(self.drawingView.imageSize, contextGenerator: { size, context in + let bounds = CGRect(origin: .zero, size: size) + if let cgImage = currentImage.cgImage { + context.draw(cgImage, in: bounds) + } + if let cgImage = self.drawingView.drawingImage?.cgImage { + context.draw(cgImage, in: bounds) + } + context.translateBy(x: size.width / 2.0, y: size.height / 2.0) + context.scaleBy(x: 1.0, y: -1.0) + context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0) + self.entitiesView.layer.render(in: context) + }, opaque: true, scale: 1.0) + guard let sourceImage = sourceImage else { + return + } + + let _ = sourceImage + // let eyedropperView = EyedropperView(containerSize: controller.contentWrapperView.frame.size, drawingView: self.drawingView, sourceImage: sourceImage) // eyedropperView.completed = { [weak self] color in // if let self { diff --git a/submodules/DrawingUI/Sources/DrawingStickerEntity.swift b/submodules/DrawingUI/Sources/DrawingStickerEntity.swift index befadba83d..98cba24d6d 100644 --- a/submodules/DrawingUI/Sources/DrawingStickerEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingStickerEntity.swift @@ -179,12 +179,46 @@ public final class DrawingStickerEntityView: DrawingEntityView { self.setNeedsLayout() } } else if let image = self.image { + func drawImageWithOrientation(_ image: UIImage, size: CGSize, in context: CGContext) { + let imageSize: CGSize + + switch image.imageOrientation { + case .left, .leftMirrored, .right, .rightMirrored: + imageSize = CGSize(width: size.height, height: size.width) + default: + imageSize = size + } + + let imageRect = CGRect(origin: .zero, size: imageSize) + + switch image.imageOrientation { + case .down, .downMirrored: + context.translateBy(x: imageSize.width, y: imageSize.height) + context.rotate(by: CGFloat.pi) + case .left, .leftMirrored: + context.translateBy(x: imageSize.width, y: 0) + context.rotate(by: CGFloat.pi / 2) + case .right, .rightMirrored: + context.translateBy(x: 0, y: imageSize.height) + context.rotate(by: -CGFloat.pi / 2) + default: + break + } + +// switch image.imageOrientation { +// case .leftMirrored, .rightMirrored: +// context.scaleBy(x: -1, y: 1) +// default: +// context.scaleBy(x: 1, y: -1) +// } + + context.draw(image.cgImage!, in: imageRect) + } + self.imageNode.setSignal(.single({ arguments -> DrawingContext? in let context = DrawingContext(size: arguments.drawingSize, opaque: false, clear: true) context?.withFlippedContext({ ctx in - if let cgImage = image.cgImage { - ctx.draw(cgImage, in: CGRect(origin: .zero, size: arguments.drawingSize)) - } + drawImageWithOrientation(image, size: arguments.drawingSize, in: ctx) }) return context })) @@ -644,385 +678,15 @@ final class DrawingStickerEntititySelectionView: DrawingEntitySelectionView { self.border.lineWidth = 2.0 / self.scale if entity.isRectangle { + let aspectRatio = entity.baseSize.width / entity.baseSize.height + let width: CGFloat = self.bounds.width - inset * 2.0 - let height: CGFloat = self.bounds.height - inset * 2.0 + let height: CGFloat = self.bounds.height / aspectRatio - inset * 2.0 + let cornerRadius: CGFloat = 12.0 - self.scale - self.border.path = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: inset, y: inset), size: CGSize(width: width, height: height)), cornerRadius: cornerRadius).cgPath + self.border.path = UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: floorToScreenPixels((self.bounds.width - width) / 2.0), y: floorToScreenPixels((self.bounds.height - height) / 2.0)), size: CGSize(width: width, height: height)), cornerRadius: cornerRadius).cgPath } else { self.border.path = UIBezierPath(ovalIn: CGRect(origin: CGPoint(x: inset, y: inset), size: CGSize(width: self.bounds.width - inset * 2.0, height: self.bounds.height - inset * 2.0))).cgPath } } } - -private let snapTimeout = 1.0 - -class DrawingEntitySnapTool { - enum SnapType { - case centerX - case centerY - case top - case left - case right - case bottom - case rotation(CGFloat?) - - static var allPositionTypes: [SnapType] { - return [ - .centerX, - .centerY, - .top, - .left, - .right, - .bottom - ] - } - } - - struct SnapState { - let skipped: CGFloat - let waitForLeave: Bool - } - - private var topEdgeState: SnapState? - private var leftEdgeState: SnapState? - private var rightEdgeState: SnapState? - private var bottomEdgeState: SnapState? - - private var xState: SnapState? - private var yState: SnapState? - - private var rotationState: (angle: CGFloat, skipped: CGFloat, waitForLeave: Bool)? - - var onSnapUpdated: (SnapType, Bool) -> Void = { _, _ in } - - var previousTopEdgeSnapTimestamp: Double? - var previousLeftEdgeSnapTimestamp: Double? - var previousRightEdgeSnapTimestamp: Double? - var previousBottomEdgeSnapTimestamp: Double? - - var previousXSnapTimestamp: Double? - var previousYSnapTimestamp: Double? - var previousRotationSnapTimestamp: Double? - - func reset() { - self.topEdgeState = nil - self.leftEdgeState = nil - self.rightEdgeState = nil - self.bottomEdgeState = nil - self.xState = nil - self.yState = nil - - for type in SnapType.allPositionTypes { - self.onSnapUpdated(type, false) - } - } - - func rotationReset() { - self.rotationState = nil - self.onSnapUpdated(.rotation(nil), false) - } - - func maybeSkipFromStart(entityView: DrawingEntityView, position: CGPoint) { - self.topEdgeState = nil - self.leftEdgeState = nil - self.rightEdgeState = nil - self.bottomEdgeState = nil - - self.xState = nil - self.yState = nil - - let snapXDelta: CGFloat = (entityView.superview?.frame.width ?? 0.0) * 0.02 - let snapYDelta: CGFloat = (entityView.superview?.frame.width ?? 0.0) * 0.02 - - if let snapLocation = (entityView.superview as? DrawingEntitiesView)?.getEntityCenterPosition() { - if position.x > snapLocation.x - snapXDelta && position.x < snapLocation.x + snapXDelta { - self.xState = SnapState(skipped: 0.0, waitForLeave: true) - } - - if position.y > snapLocation.y - snapYDelta && position.y < snapLocation.y + snapYDelta { - self.yState = SnapState(skipped: 0.0, waitForLeave: true) - } - } - } - - func update(entityView: DrawingEntityView, velocity: CGPoint, delta: CGPoint, updatedPosition: CGPoint, size: CGSize) -> CGPoint { - var updatedPosition = updatedPosition - - guard let snapCenterLocation = (entityView.superview as? DrawingEntitiesView)?.getEntityCenterPosition() else { - return updatedPosition - } - let snapEdgeLocations = (entityView.superview as? DrawingEntitiesView)?.getEntityEdgePositions() - - let currentTimestamp = CACurrentMediaTime() - - let snapDelta: CGFloat = (entityView.superview?.frame.width ?? 0.0) * 0.02 - let snapVelocity: CGFloat = snapDelta * 12.0 - let snapSkipTranslation: CGFloat = snapDelta * 2.0 - - let topPoint = updatedPosition.y - size.height / 2.0 - let leftPoint = updatedPosition.x - size.width / 2.0 - let rightPoint = updatedPosition.x + size.width / 2.0 - let bottomPoint = updatedPosition.y + size.height / 2.0 - - func process( - state: SnapState?, - velocity: CGFloat, - delta: CGFloat, - value: CGFloat, - snapVelocity: CGFloat, - snapToValue: CGFloat?, - snapDelta: CGFloat, - snapSkipTranslation: CGFloat, - previousSnapTimestamp: Double?, - onSnapUpdated: (Bool) -> Void - ) -> ( - value: CGFloat, - state: SnapState?, - snapTimestamp: Double? - ) { - var updatedValue = value - var updatedState = state - var updatedPreviousSnapTimestamp = previousSnapTimestamp - if abs(velocity) < snapVelocity || state?.waitForLeave == true { - if let snapToValue { - if let state { - let skipped = state.skipped - let waitForLeave = state.waitForLeave - if waitForLeave { - if value > snapToValue - snapDelta * 2.0 && value < snapToValue + snapDelta * 2.0 { - - } else { - updatedState = nil - } - } else if abs(skipped) < snapSkipTranslation { - updatedState = SnapState(skipped: skipped + delta, waitForLeave: false) - updatedValue = snapToValue - } else { - updatedState = SnapState(skipped: snapSkipTranslation, waitForLeave: true) - onSnapUpdated(false) - } - } else { - if value > snapToValue - snapDelta && value < snapToValue + snapDelta { - if let previousSnapTimestamp, currentTimestamp - previousSnapTimestamp < snapTimeout { - - } else { - updatedPreviousSnapTimestamp = currentTimestamp - updatedState = SnapState(skipped: 0.0, waitForLeave: false) - updatedValue = snapToValue - onSnapUpdated(true) - } - } - } - } - } else { - updatedState = nil - onSnapUpdated(false) - } - return (updatedValue, updatedState, updatedPreviousSnapTimestamp) - } - - let (updatedXValue, updatedXState, updatedXPreviousTimestamp) = process( - state: self.xState, - velocity: velocity.x, - delta: delta.x, - value: updatedPosition.x, - snapVelocity: snapVelocity, - snapToValue: snapCenterLocation.x, - snapDelta: snapDelta, - snapSkipTranslation: snapSkipTranslation, - previousSnapTimestamp: self.previousXSnapTimestamp, - onSnapUpdated: { [weak self] snapped in - self?.onSnapUpdated(.centerX, snapped) - } - ) - self.xState = updatedXState - self.previousXSnapTimestamp = updatedXPreviousTimestamp - - let (updatedYValue, updatedYState, updatedYPreviousTimestamp) = process( - state: self.yState, - velocity: velocity.y, - delta: delta.y, - value: updatedPosition.y, - snapVelocity: snapVelocity, - snapToValue: snapCenterLocation.y, - snapDelta: snapDelta, - snapSkipTranslation: snapSkipTranslation, - previousSnapTimestamp: self.previousYSnapTimestamp, - onSnapUpdated: { [weak self] snapped in - self?.onSnapUpdated(.centerY, snapped) - } - ) - self.yState = updatedYState - self.previousYSnapTimestamp = updatedYPreviousTimestamp - - if let snapEdgeLocations { - if updatedXState == nil { - let (updatedXLeftEdgeValue, updatedLeftEdgeState, updatedLeftEdgePreviousTimestamp) = process( - state: self.leftEdgeState, - velocity: velocity.x, - delta: delta.x, - value: leftPoint, - snapVelocity: snapVelocity, - snapToValue: snapEdgeLocations.left, - snapDelta: snapDelta, - snapSkipTranslation: snapSkipTranslation, - previousSnapTimestamp: self.previousLeftEdgeSnapTimestamp, - onSnapUpdated: { [weak self] snapped in - self?.onSnapUpdated(.left, snapped) - } - ) - self.leftEdgeState = updatedLeftEdgeState - self.previousLeftEdgeSnapTimestamp = updatedLeftEdgePreviousTimestamp - - if updatedLeftEdgeState != nil { - updatedPosition.x = updatedXLeftEdgeValue + size.width / 2.0 - - self.rightEdgeState = nil - self.previousRightEdgeSnapTimestamp = nil - } else { - let (updatedXRightEdgeValue, updatedRightEdgeState, updatedRightEdgePreviousTimestamp) = process( - state: self.rightEdgeState, - velocity: velocity.x, - delta: delta.x, - value: rightPoint, - snapVelocity: snapVelocity, - snapToValue: snapEdgeLocations.right, - snapDelta: snapDelta, - snapSkipTranslation: snapSkipTranslation, - previousSnapTimestamp: self.previousRightEdgeSnapTimestamp, - onSnapUpdated: { [weak self] snapped in - self?.onSnapUpdated(.right, snapped) - } - ) - self.rightEdgeState = updatedRightEdgeState - self.previousRightEdgeSnapTimestamp = updatedRightEdgePreviousTimestamp - - updatedPosition.x = updatedXRightEdgeValue - size.width / 2.0 - } - } else { - updatedPosition.x = updatedXValue - } - - if updatedYState == nil { - let (updatedYTopEdgeValue, updatedTopEdgeState, updatedTopEdgePreviousTimestamp) = process( - state: self.topEdgeState, - velocity: velocity.y, - delta: delta.y, - value: topPoint, - snapVelocity: snapVelocity, - snapToValue: snapEdgeLocations.top, - snapDelta: snapDelta, - snapSkipTranslation: snapSkipTranslation, - previousSnapTimestamp: self.previousTopEdgeSnapTimestamp, - onSnapUpdated: { [weak self] snapped in - self?.onSnapUpdated(.top, snapped) - } - ) - self.topEdgeState = updatedTopEdgeState - self.previousTopEdgeSnapTimestamp = updatedTopEdgePreviousTimestamp - - if updatedTopEdgeState != nil { - updatedPosition.y = updatedYTopEdgeValue + size.height / 2.0 - - self.bottomEdgeState = nil - self.previousBottomEdgeSnapTimestamp = nil - } else { - let (updatedYBottomEdgeValue, updatedBottomEdgeState, updatedBottomEdgePreviousTimestamp) = process( - state: self.bottomEdgeState, - velocity: velocity.y, - delta: delta.y, - value: bottomPoint, - snapVelocity: snapVelocity, - snapToValue: snapEdgeLocations.bottom, - snapDelta: snapDelta, - snapSkipTranslation: snapSkipTranslation, - previousSnapTimestamp: self.previousBottomEdgeSnapTimestamp, - onSnapUpdated: { [weak self] snapped in - self?.onSnapUpdated(.bottom, snapped) - } - ) - self.bottomEdgeState = updatedBottomEdgeState - self.previousBottomEdgeSnapTimestamp = updatedBottomEdgePreviousTimestamp - - updatedPosition.y = updatedYBottomEdgeValue - size.height / 2.0 - } - } else { - updatedPosition.y = updatedYValue - } - } else { - updatedPosition.x = updatedXValue - updatedPosition.y = updatedYValue - } - - return updatedPosition - } - - private let snapRotations: [CGFloat] = [0.0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0] - func maybeSkipFromStart(entityView: DrawingEntityView, rotation: CGFloat) { - self.rotationState = nil - - let snapDelta: CGFloat = 0.25 - for snapRotation in self.snapRotations { - let snapRotation = snapRotation * .pi - if rotation > snapRotation - snapDelta && rotation < snapRotation + snapDelta { - self.rotationState = (snapRotation, 0.0, true) - break - } - } - } - - func update(entityView: DrawingEntityView, velocity: CGFloat, delta: CGFloat, updatedRotation: CGFloat) -> CGFloat { - var updatedRotation = updatedRotation - if updatedRotation < 0.0 { - updatedRotation = 2.0 * .pi + updatedRotation - } else if updatedRotation > 2.0 * .pi { - while updatedRotation > 2.0 * .pi { - updatedRotation -= 2.0 * .pi - } - } - - let currentTimestamp = CACurrentMediaTime() - - let snapDelta: CGFloat = 0.01 - let snapVelocity: CGFloat = snapDelta * 35.0 - let snapSkipRotation: CGFloat = snapDelta * 40.0 - - if abs(velocity) < snapVelocity || self.rotationState?.waitForLeave == true { - if let (snapRotation, skipped, waitForLeave) = self.rotationState { - if waitForLeave { - if updatedRotation > snapRotation - snapDelta * 2.0 && updatedRotation < snapRotation + snapDelta { - - } else { - self.rotationState = nil - } - } else if abs(skipped) < snapSkipRotation { - self.rotationState = (snapRotation, skipped + delta, false) - updatedRotation = snapRotation - } else { - self.rotationState = (snapRotation, snapSkipRotation, true) - self.onSnapUpdated(.rotation(nil), false) - } - } else { - for snapRotation in self.snapRotations { - let snapRotation = snapRotation * .pi - if updatedRotation > snapRotation - snapDelta && updatedRotation < snapRotation + snapDelta { - if let previousRotationSnapTimestamp, currentTimestamp - previousRotationSnapTimestamp < snapTimeout { - - } else { - self.previousRotationSnapTimestamp = currentTimestamp - self.rotationState = (snapRotation, 0.0, false) - updatedRotation = snapRotation - self.onSnapUpdated(.rotation(snapRotation), true) - } - break - } - } - } - } else { - self.rotationState = nil - self.onSnapUpdated(.rotation(nil), false) - } - - return updatedRotation - } -} diff --git a/submodules/DrawingUI/Sources/StickerPickerScreen.swift b/submodules/DrawingUI/Sources/StickerPickerScreen.swift index c155dec41e..99edb0f2e1 100644 --- a/submodules/DrawingUI/Sources/StickerPickerScreen.swift +++ b/submodules/DrawingUI/Sources/StickerPickerScreen.swift @@ -912,7 +912,13 @@ public class StickerPickerScreen: ViewController { useOpaqueTheme: false, hideBackground: true, stateContext: nil, - addImage: nil + addImage: { [weak self] in + if let self { + self.controller?.completion(nil) + self.controller?.dismiss(animated: true) + self.controller?.presentGallery() + } + } ) var stickerPeekBehavior: EmojiContentPeekBehaviorImpl? @@ -1170,8 +1176,12 @@ public class StickerPickerScreen: ViewController { useOpaqueTheme: false, hideBackground: true, stateContext: nil, - addImage: { - + addImage: { [weak self] in + if let self { + self.controller?.completion(nil) + self.controller?.dismiss(animated: true) + self.controller?.presentGallery() + } } ) @@ -1627,6 +1637,8 @@ public class StickerPickerScreen: ViewController { public var completion: (DrawingStickerEntity.Content?) -> Void = { _ in } + public var presentGallery: () -> Void = { } + public init(context: AccountContext, inputData: Signal) { self.context = context self.theme = defaultDarkColorPresentationTheme diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 35a952c1d6..9c8b0b8784 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -137,6 +137,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { case `default` case wallpaper case story + case addImage } case assets(PHAssetCollection?, AssetsMode) @@ -250,7 +251,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { self.presentationData = controller.presentationData var assetType: PHAssetMediaType? - if case let .assets(_, mode) = controller.subject, case .wallpaper = mode { + if case let .assets(_, mode) = controller.subject, [.wallpaper, .addImage].contains(mode) { assetType = .image } let mediaAssetsContext = MediaAssetsContext(assetType: assetType) @@ -404,7 +405,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { self.gridNode.scrollView.alwaysBounceVertical = true self.gridNode.scrollView.showsVerticalScrollIndicator = false - if case let .assets(_, mode) = controller.subject, [.wallpaper, .story].contains(mode) { + if case let .assets(_, mode) = controller.subject, [.wallpaper, .story, .addImage].contains(mode) { } else { let selectionGesture = MediaPickerGridSelectionGesture() @@ -1379,6 +1380,9 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { self.titleView.title = presentationData.strings.Attachment_Gallery case .wallpaper: self.titleView.title = presentationData.strings.Conversation_Theme_ChooseWallpaperTitle + case .addImage: + //TODO:localize + self.titleView.title = "Add Image" } } } else { @@ -2184,6 +2188,28 @@ public func wallpaperMediaPickerController( return controller } +public func mediaPickerController( + context: AccountContext, + completion: @escaping (Any) -> Void +) -> ViewController { + let presentationData = context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: defaultDarkColorPresentationTheme) + let updatedPresentationData: (PresentationData, Signal) = (presentationData, .single(presentationData)) + let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: nil, buttons: [.standalone], initialButton: .standalone, fromMenu: false, hasTextInput: false, makeEntityInputView: { + return nil + }) + controller.requestController = { _, present in + let mediaPickerController = MediaPickerScreen(context: context, updatedPresentationData: updatedPresentationData, peer: nil, threadTitle: nil, chatLocation: nil, bannedSendPhotos: nil, bannedSendVideos: nil, subject: .assets(nil, .addImage), mainButtonState: nil, mainButtonAction: nil) + mediaPickerController.customSelection = { controller, result in + completion(result) + controller.dismiss(animated: true) + } + present(mediaPickerController, mediaPickerController.mediaPickerContext) + } + controller.navigationPresentation = .flatModal + controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) + return controller +} + public func storyMediaPickerController( context: AccountContext, getSourceRect: @escaping () -> CGRect, diff --git a/submodules/SettingsUI/BUILD b/submodules/SettingsUI/BUILD index d7c52ee05c..6781ddea57 100644 --- a/submodules/SettingsUI/BUILD +++ b/submodules/SettingsUI/BUILD @@ -113,6 +113,7 @@ swift_library( "//submodules/MediaPickerUI:MediaPickerUI", "//submodules/ImageBlur:ImageBlur", "//submodules/AttachmentUI:AttachmentUI", + "//submodules/TelegramUI/Components/PeerInfo/PeerInfoStoryGridScreen", ], visibility = [ "//visibility:public", diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift index ff3cb6d2e6..956d5a70a5 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift @@ -53,6 +53,8 @@ extension SettingsSearchableItemIcon { return PresentationResourcesSettings.devices case .premium: return PresentationResourcesSettings.premium + case .stories: + return PresentationResourcesSettings.stories } } } diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift index fbed9c2c50..e2dd3d9eb4 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift @@ -21,6 +21,7 @@ import NotificationPeerExceptionController import QrCodeUI import PremiumUI import StorageUsageScreen +import PeerInfoStoryGridScreen enum SettingsSearchableItemIcon { case profile @@ -41,6 +42,7 @@ enum SettingsSearchableItemIcon { case deleteAccount case devices case premium + case stories } public enum SettingsSearchableItemId: Hashable { @@ -62,6 +64,7 @@ public enum SettingsSearchableItemId: Hashable { case deleteAccount(Int32) case devices(Int32) case premium(Int32) + case stories(Int32) private var namespace: Int32 { switch self { @@ -101,6 +104,8 @@ public enum SettingsSearchableItemId: Hashable { return 18 case .premium: return 19 + case .stories: + return 20 } } @@ -123,7 +128,8 @@ public enum SettingsSearchableItemId: Hashable { let .chatFolders(id), let .deleteAccount(id), let .devices(id), - let .premium(id): + let .premium(id), + let .stories(id): return id } } @@ -172,6 +178,8 @@ public enum SettingsSearchableItemId: Hashable { self = .devices(id) case 19: self = .premium(id) + case 20: + self = .stories(id) default: return nil } @@ -340,6 +348,25 @@ private func premiumSearchableItems(context: AccountContext) -> [SettingsSearcha return result } +private func storiesSearchableItems(context: AccountContext) -> [SettingsSearchableItem] { + let icon: SettingsSearchableItemIcon = .stories + let strings = context.sharedContext.currentPresentationData.with { $0 }.strings + + var result: [SettingsSearchableItem] = [] + + //TODO:localize + result.append(SettingsSearchableItem(id: .stories(0), title: "My Stories", alternate: synonyms(strings.SettingsSearch_Synonyms_Premium), icon: icon, breadcrumbs: [], present: { context, _, present in + present(.push, PeerInfoStoryGridScreen(context: context, peerId: context.account.peerId, scope: .saved)) + })) + + result.append(SettingsSearchableItem(id: .stories(1), title: "Stories Archive", alternate: synonyms(strings.SettingsSearch_Synonyms_Premium), icon: icon, breadcrumbs: [], present: { context, _, present in + present(.push, PeerInfoStoryGridScreen(context: context, peerId: context.account.peerId, scope: .archive)) + })) + + return result +} + + private func callSearchableItems(context: AccountContext) -> [SettingsSearchableItem] { let icon: SettingsSearchableItemIcon = .calls let strings = context.sharedContext.currentPresentationData.with { $0 }.strings @@ -1008,6 +1035,9 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList let premiumItems = premiumSearchableItems(context: context) allItems.append(contentsOf: premiumItems) + + let storiesItems = storiesSearchableItems(context: context) + allItems.append(contentsOf: storiesItems) if watchAppInstalled { let watch = SettingsSearchableItem(id: .watch(0), title: strings.Settings_AppleWatch, alternate: synonyms(strings.SettingsSearch_Synonyms_Watch), icon: .watch, breadcrumbs: [], present: { context, _, present in diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index fc40a1733b..479e7bdb7b 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -1370,7 +1370,7 @@ public class CameraScreen: ViewController { private var isDismissing = false @objc private func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) { - guard let controller = self.controller else { + guard let controller = self.controller, let layout = self.validLayout else { return } let translation = gestureRecognizer.translation(in: gestureRecognizer.view) @@ -1380,7 +1380,7 @@ public class CameraScreen: ViewController { case .changed: if self.componentExternalState.isRecording { - } else { + } else if case .compact = layout.metrics.widthClass { if translation.x < -10.0 || self.isDismissing { self.isDismissing = true let transitionFraction = 1.0 - max(0.0, translation.x * -1.0) / self.frame.width @@ -2179,7 +2179,7 @@ public class CameraScreen: ViewController { if let current = self.galleryController { controller = current } else { - controller = self.context.sharedContext.makeMediaPickerScreen(context: self.context, getSourceRect: { [weak self] in + controller = self.context.sharedContext.makeStoryMediaPickerScreen(context: self.context, getSourceRect: { [weak self] in if let self { if let galleryButton = self.node.componentHost.findTaggedView(tag: galleryButtonTag) { return galleryButton.convert(galleryButton.bounds, to: self.view).offsetBy(dx: 0.0, dy: -15.0) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index bf81ed1bfb..d2cb63c5fd 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -588,6 +588,18 @@ public final class EntityKeyboardComponent: Component { } ).minSize(CGSize(width: 38.0, height: 38.0))))) } + if let addImage = component.stickerContent?.inputInteractionHolder.inputInteraction?.addImage { + contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Media Editor/AddImage", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { + addImage() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + } } let deleteBackwards = component.emojiContent?.inputInteractionHolder.inputInteraction?.deleteBackwards @@ -689,9 +701,8 @@ public final class EntityKeyboardComponent: Component { component.switchToTextInput() } ).minSize(CGSize(width: 38.0, height: 38.0))))) - } - if let addImage = component.stickerContent?.inputInteractionHolder.inputInteraction?.addImage { - contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "image", component: AnyComponent(Button( + } else if let addImage = component.emojiContent?.inputInteractionHolder.inputInteraction?.addImage { + contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(Button( content: AnyComponent(BundleIconComponent( name: "Media Editor/AddImage", tintColor: component.theme.chat.inputMediaPanel.panelIconColor, diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 5d29f1624e..81a218d6ca 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -1843,6 +1843,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate switch subject { case .image, .video: isSavingAvailable = !controller.isEditingStory + case .draft: + isSavingAvailable = true default: isSavingAvailable = false } @@ -1973,7 +1975,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate } else { self.previewContainerView.alpha = 1.0 - if CACurrentMediaTime() - self.initializationTimestamp > 0.2 { + if CACurrentMediaTime() - self.initializationTimestamp > 0.2, case .image = subject { self.previewContainerView.layer.allowsGroupOpacity = true self.previewContainerView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { _ in self.previewContainerView.layer.allowsGroupOpacity = false @@ -2330,6 +2332,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate if let view = self.componentHost.view as? MediaEditorScreenComponent.View { view.animateIn(from: .camera, completion: completion) } + if let subject = self.subject, case let .video(_, mainTransitionImage, _, _, additionalTransitionImage, _, _, positionChangeTimestamps, pipPosition) = subject, let mainTransitionImage { var transitionImage = mainTransitionImage if let additionalTransitionImage { @@ -2703,34 +2706,27 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate self.saveTooltip = tooltipController } } - - private weak var storyArchiveTooltip: ViewController? - func presentStoryArchiveTooltip(sourceView: UIView) { + + func presentGallery() { guard let controller = self.controller else { return } - - if let storyArchiveTooltip = self.storyArchiveTooltip { - storyArchiveTooltip.dismiss(animated: true) - self.storyArchiveTooltip = nil - } - - let parentFrame = self.view.convert(self.bounds, to: nil) - let absoluteFrame = sourceView.convert(sourceView.bounds, to: nil).offsetBy(dx: -parentFrame.minX, dy: 0.0) - let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.minY - 5.0), size: CGSize()) - - let text: String - if controller.state.privacy.pin { - text = "Story will be kept on your page." - } else { - text = "Story will disappear in 24 hours." - } - - let tooltipController = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: .plain(text: text), location: .point(location, .bottom), displayDuration: .default, inset: 7.0, cornerRadius: 9.0, shouldDismissOnTouch: { _, _ in - return .ignore + let galleryController = self.context.sharedContext.makeMediaPickerScreen(context: self.context, completion: { [weak self] result in + guard let self, let asset = result as? PHAsset else { + return + } + + let options = PHImageRequestOptions() + options.deliveryMode = .highQualityFormat + PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .default, options: options) { [weak self] image, _ in + if let self, let image { + Queue.mainQueue().async { + self.interaction?.insertEntity(DrawingStickerEntity(content: .image(image, true)), scale: 2.5) + } + } + } }) - self.storyArchiveTooltip = tooltipController - self.controller?.present(tooltipController, in: .current) + controller.push(galleryController) } func updateModalTransitionFactor(_ value: CGFloat, transition: ContainedViewLayoutTransition) { @@ -2885,6 +2881,11 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate self.updateModalTransitionFactor(transitionFactor, transition: transition) } } + controller.presentGallery = { [weak self] in + if let self { + self.presentGallery() + } + } self.stickerScreen = controller self.controller?.present(controller, in: .window(.root)) return diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index 60cb01ddf7..799e845ffe 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -1476,7 +1476,7 @@ final class ShareWithPeersScreenComponent: Component { let inset: CGFloat if case let .stories(editing) = component.stateContext.subject { if editing { - inset = 430.0 + inset = 446.0 } else { inset = 605.0 } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 4370a19614..fe79b9deb2 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -2220,6 +2220,7 @@ public final class StoryItemSetContainerComponent: Component { self.controlsContainerView.addSubview(moreButtonView) } transition.setFrame(view: moreButtonView, frame: CGRect(origin: CGPoint(x: headerRightOffset - moreButtonSize.width, y: 2.0), size: moreButtonSize)) + transition.setAlpha(view: moreButtonView, alpha: component.slice.item.storyItem.isPending ? 0.0 : 1.0) headerRightOffset -= moreButtonSize.width + 15.0 } diff --git a/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/Contents.json index 728f719c77..e11ef0c09b 100644 --- a/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "photo_24.pdf", + "filename" : "image_30.pdf", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/image_30.pdf b/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/image_30.pdf new file mode 100644 index 0000000000..02dfd54352 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/image_30.pdf @@ -0,0 +1,160 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 5.335022 5.334991 cm +1.000000 1.000000 1.000000 scn +7.065000 19.330017 m +7.035460 19.330017 l +5.940372 19.330021 5.077796 19.330025 4.383656 19.273312 c +3.675523 19.215456 3.084329 19.095276 2.547134 18.821562 c +1.669358 18.374313 0.955704 17.660660 0.508455 16.782883 c +0.234740 16.245687 0.114562 15.654494 0.056705 14.946362 c +-0.000008 14.252222 -0.000005 13.389645 0.000000 12.294557 c +0.000000 12.265017 l +0.000000 7.065017 l +0.000000 7.035477 l +-0.000005 5.940390 -0.000008 5.077813 0.056705 4.383673 c +0.114562 3.675540 0.234740 3.084345 0.508455 2.547152 c +0.955704 1.669374 1.669358 0.955721 2.547134 0.508471 c +3.084329 0.234756 3.675523 0.114578 4.383656 0.056721 c +5.077746 0.000010 5.940250 0.000013 7.035228 0.000017 c +7.035275 0.000017 l +7.035323 0.000017 l +7.035370 0.000017 l +7.065000 0.000017 l +12.265000 0.000017 l +12.294630 0.000017 l +12.294676 0.000017 l +12.294722 0.000017 l +12.294767 0.000017 l +13.389750 0.000013 14.252252 0.000010 14.946344 0.056721 c +15.654477 0.114578 16.245672 0.234756 16.782866 0.508471 c +17.660643 0.955721 18.374296 1.669374 18.821547 2.547152 c +19.095261 3.084345 19.215439 3.675540 19.273296 4.383673 c +19.330008 5.077765 19.330004 5.940269 19.330000 7.035251 c +19.330000 7.035296 l +19.330000 7.035342 l +19.330000 7.035388 l +19.330000 7.065018 l +19.330000 12.265018 l +19.330000 12.294647 l +19.330000 12.294695 l +19.330000 12.294742 l +19.330000 12.294788 l +19.330004 13.389767 19.330008 14.252271 19.273296 14.946362 c +19.215439 15.654494 19.095261 16.245687 18.821547 16.782883 c +18.374296 17.660660 17.660643 18.374313 16.782866 18.821562 c +16.245672 19.095276 15.654477 19.215456 14.946344 19.273312 c +14.252204 19.330025 13.389627 19.330021 12.294539 19.330017 c +12.264999 19.330017 l +7.065000 19.330017 l +h +3.150942 17.636524 m +3.469394 17.798782 3.866076 17.896591 4.491960 17.947729 c +5.125607 17.999500 5.933921 18.000017 7.065000 18.000017 c +12.264999 18.000017 l +13.396078 18.000017 14.204392 17.999500 14.838039 17.947729 c +15.463923 17.896591 15.860606 17.798782 16.179058 17.636524 c +16.806580 17.316786 17.316771 16.806597 17.636507 16.179075 c +17.798767 15.860623 17.896576 15.463942 17.947712 14.838057 c +17.999483 14.204411 18.000000 13.396095 18.000000 12.265018 c +18.000000 7.065018 l +18.000000 6.309615 17.999769 5.698176 17.984194 5.186587 c +15.466902 7.867111 l +14.693245 8.690934 13.378143 8.669102 12.632261 7.820047 c +11.520865 6.554921 l +6.709533 11.633550 l +5.937637 12.448328 4.633699 12.427637 3.888045 11.588776 c +1.330000 8.710975 l +1.330000 12.265017 l +1.330000 13.396095 1.330517 14.204410 1.382288 14.838057 c +1.433425 15.463942 1.531234 15.860623 1.693493 16.179075 c +2.013231 16.806597 2.523421 17.316786 3.150942 17.636524 c +h +14.497394 6.956641 m +17.768957 3.472939 l +17.730608 3.355179 17.686632 3.249336 17.636507 3.150959 c +17.316771 2.523438 16.806580 2.013247 16.179058 1.693510 c +16.167240 1.687489 16.155315 1.681555 16.143274 1.675711 c +12.439418 5.585338 l +13.631460 6.942265 l +13.859314 7.201635 14.261054 7.208306 14.497394 6.956641 c +h +1.330082 6.709152 m +1.330711 5.761131 1.336117 5.057091 1.382288 4.491978 c +1.433425 3.866094 1.531234 3.469411 1.693493 3.150959 c +2.013231 2.523438 2.523421 2.013247 3.150942 1.693510 c +3.469394 1.531250 3.866076 1.433441 4.491960 1.382305 c +5.125607 1.330534 5.933922 1.330017 7.065000 1.330017 c +12.265000 1.330017 l +13.261761 1.330017 14.007863 1.330418 14.604662 1.365944 c +5.744016 10.718849 l +5.508215 10.967751 5.109884 10.961430 4.882100 10.705172 c +1.330082 6.709152 l +h +14.040000 12.165017 m +15.075534 12.165017 15.915000 13.004483 15.915000 14.040017 c +15.915000 15.075551 15.075534 15.915017 14.040000 15.915017 c +13.004466 15.915017 12.165000 15.075551 12.165000 14.040017 c +12.165000 13.004483 13.004466 12.165017 14.040000 12.165017 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 3865 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 30.000000 30.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000003955 00000 n +0000003978 00000 n +0000004151 00000 n +0000004225 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4284 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/photo_24.pdf b/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/photo_24.pdf deleted file mode 100644 index abbb6f872f..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Media Editor/AddImage.imageset/photo_24.pdf +++ /dev/null @@ -1,154 +0,0 @@ -%PDF-1.7 - -1 0 obj - << >> -endobj - -2 0 obj - << /Length 3 0 R >> -stream -/DeviceRGB CS -/DeviceRGB cs -q -1.000000 0.000000 -0.000000 1.000000 3.835083 3.834961 cm -1.000000 1.000000 1.000000 scn -5.465000 16.330017 m -5.436178 16.330017 l -5.436174 16.330017 l -4.620535 16.330023 3.967872 16.330027 3.440454 16.286936 c -2.899074 16.242702 2.431364 16.149773 2.001125 15.930555 c -1.311511 15.579180 0.750837 15.018506 0.399461 14.328892 c -0.180244 13.898653 0.087314 13.430943 0.043081 12.889563 c --0.000010 12.362144 -0.000006 11.709482 0.000000 10.893843 c -0.000000 10.893839 l -0.000000 10.865017 l -0.000000 5.465017 l -0.000000 5.436195 l --0.000006 4.620555 -0.000010 3.967890 0.043081 3.440471 c -0.087314 2.899090 0.180244 2.431380 0.399461 2.001142 c -0.750837 1.311528 1.311511 0.750854 2.001125 0.399478 c -2.431364 0.180260 2.899074 0.087330 3.440454 0.043098 c -3.967863 0.000008 4.620512 0.000011 5.436130 0.000017 c -5.436194 0.000017 l -5.465001 0.000017 l -10.865000 0.000017 l -10.893806 0.000017 l -10.893871 0.000017 l -11.709489 0.000011 12.362138 0.000008 12.889546 0.043098 c -13.430927 0.087330 13.898637 0.180260 14.328876 0.399478 c -15.018489 0.750854 15.579163 1.311528 15.930539 2.001142 c -16.149757 2.431380 16.242687 2.899091 16.286919 3.440471 c -16.330009 3.967880 16.330006 4.620529 16.330000 5.436146 c -16.330000 5.436212 l -16.330000 5.465017 l -16.330000 10.865017 l -16.330000 10.893824 l -16.330000 10.893888 l -16.330006 11.709505 16.330009 12.362154 16.286919 12.889563 c -16.242687 13.430943 16.149757 13.898653 15.930539 14.328892 c -15.579163 15.018506 15.018489 15.579180 14.328876 15.930555 c -13.898637 16.149773 13.430926 16.242702 12.889546 16.286936 c -12.362126 16.330029 11.709461 16.330023 10.893822 16.330017 c -10.865000 16.330017 l -5.465000 16.330017 l -h -2.604932 14.745517 m -2.816429 14.853280 3.089626 14.923841 3.548759 14.961352 c -4.015654 14.999499 4.613948 15.000017 5.465000 15.000017 c -10.865000 15.000017 l -11.716052 15.000017 12.314346 14.999499 12.781241 14.961352 c -13.240374 14.923841 13.513572 14.853280 13.725068 14.745517 c -14.164426 14.521652 14.521636 14.164443 14.745501 13.725084 c -14.853263 13.513588 14.923823 13.240391 14.961336 12.781259 c -14.999483 12.314363 15.000000 11.716068 15.000000 10.865017 c -15.000000 5.465017 l -15.000000 5.137442 14.999924 4.847313 14.997654 4.587710 c -12.903418 6.817746 l -12.230759 7.534022 11.087341 7.515037 10.438833 6.776826 c -9.645941 5.874260 l -5.897148 9.831320 l -5.226022 10.539732 4.092310 10.521740 3.444000 9.792391 c -1.330000 7.414142 l -1.330000 10.865017 l -1.330000 11.716068 1.330518 12.314363 1.368664 12.781259 c -1.406177 13.240391 1.476737 13.513588 1.584500 13.725084 c -1.808364 14.164443 2.165574 14.521652 2.604932 14.745517 c -h -11.933909 5.907277 m -14.833861 2.819281 l -14.807792 2.739742 14.778378 2.669474 14.745501 2.604949 c -14.521636 2.165591 14.164426 1.808381 13.725068 1.584517 c -13.714809 1.579343 l -10.564494 4.904676 l -11.438032 5.899043 l -11.568513 6.047573 11.798571 6.051393 11.933909 5.907277 c -h -1.330001 5.412228 m -1.330038 4.589128 1.331311 4.005958 1.368664 3.548775 c -1.406177 3.089643 1.476737 2.816445 1.584500 2.604949 c -1.808364 2.165591 2.165574 1.808381 2.604932 1.584517 c -2.816429 1.476754 3.089626 1.406194 3.548759 1.368681 c -4.015654 1.330534 4.613949 1.330017 5.465001 1.330017 c -10.865000 1.330017 l -11.357291 1.330017 11.765009 1.330190 12.111642 1.337719 c -4.931631 8.916620 l -4.796600 9.059153 4.568496 9.055533 4.438055 8.908787 c -1.330001 5.412228 l -h -11.664969 10.165024 m -12.493397 10.165024 13.164969 10.836597 13.164969 11.665024 c -13.164969 12.493451 12.493397 13.165024 11.664969 13.165024 c -10.836542 13.165024 10.164969 12.493451 10.164969 11.665024 c -10.164969 10.836597 10.836542 10.165024 11.664969 10.165024 c -h -f* -n -Q - -endstream -endobj - -3 0 obj - 3694 -endobj - -4 0 obj - << /Annots [] - /Type /Page - /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] - /Resources 1 0 R - /Contents 2 0 R - /Parent 5 0 R - >> -endobj - -5 0 obj - << /Kids [ 4 0 R ] - /Count 1 - /Type /Pages - >> -endobj - -6 0 obj - << /Pages 5 0 R - /Type /Catalog - >> -endobj - -xref -0 7 -0000000000 65535 f -0000000010 00000 n -0000000034 00000 n -0000003784 00000 n -0000003807 00000 n -0000003980 00000 n -0000004054 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -4113 -%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 4ac887145d..60593dc748 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1843,7 +1843,11 @@ public final class SharedAccountContextImpl: SharedAccountContext { return StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: mainStickerPack, stickerPacks: stickerPacks, loadedStickerPacks: loadedStickerPacks, parentNavigationController: parentNavigationController, sendSticker: sendSticker) } - public func makeMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController { + public func makeMediaPickerScreen(context: AccountContext, completion: @escaping (Any) -> Void) -> ViewController { + return mediaPickerController(context: context, completion: completion) + } + + public func makeStoryMediaPickerScreen(context: AccountContext, getSourceRect: @escaping () -> CGRect, completion: @escaping (Any, UIView, CGRect, UIImage?, @escaping (Bool?) -> (UIView, CGRect)?, @escaping () -> Void) -> Void, dismissed: @escaping () -> Void) -> ViewController { return storyMediaPickerController(context: context, getSourceRect: getSourceRect, completion: completion, dismissed: dismissed) }