From 2e6bc7f69db981a38098a2890417c2aa972519d4 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 14 Jul 2023 22:17:06 +0200 Subject: [PATCH 1/4] Various fixes --- .../Sources/AccountContext.swift | 4 - .../Sources/DrawingEntitiesView.swift | 1 + .../Sources/MediaPickerScreen.swift | 24 +++- .../Sources/VoiceChatController.swift | 106 +++++++++++------- .../CameraScreen/Sources/CameraScreen.swift | 24 +++- .../Sources/MediaAssetsContext.swift | 7 +- .../Sources/EmojiPagerContentComponent.swift | 2 +- .../Sources/MediaEditorScreen.swift | 12 +- .../Sources/ShareWithPeersScreen.swift | 13 ++- 9 files changed, 132 insertions(+), 61 deletions(-) diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 317dd4615d..5e07f87427 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -1100,9 +1100,6 @@ public struct StoriesConfiguration { } public static func with(appConfiguration: AppConfiguration) -> StoriesConfiguration { -//#if DEBUG -// return StoriesConfiguration(posting: .premium) -//#else if let data = appConfiguration.data, let postingString = data["stories_posting"] as? String { var posting: PostingAvailability switch postingString { @@ -1117,7 +1114,6 @@ public struct StoriesConfiguration { } else { return .defaultValue } -//#endif } } diff --git a/submodules/DrawingUI/Sources/DrawingEntitiesView.swift b/submodules/DrawingUI/Sources/DrawingEntitiesView.swift index 5eeb45a852..8f7e29d6db 100644 --- a/submodules/DrawingUI/Sources/DrawingEntitiesView.swift +++ b/submodules/DrawingUI/Sources/DrawingEntitiesView.swift @@ -464,6 +464,7 @@ public final class DrawingEntitiesView: UIView, TGPhotoDrawingEntitiesView { self.selectedEntityView = nil self.selectionChanged(nil) self.hasSelectionChanged(false) + view.selectionView?.removeFromSuperview() } if animated { view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak view] _ in diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 0bf1a5b204..867f43a50e 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -110,6 +110,8 @@ struct Month: Equatable { } } +private var savedStoriesContentOffset: CGFloat? + public final class MediaPickerScreen: ViewController, AttachmentContainable { public enum Subject { public enum Media: Equatable { @@ -207,7 +209,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { private let containerNode: ASDisplayNode private let backgroundNode: NavigationBackgroundNode - private let gridNode: GridNode + fileprivate let gridNode: GridNode fileprivate var cameraView: TGAttachmentCameraView? private var cameraActivateAreaNode: AccessibilityAreaNode private var placeholderNode: MediaPickerPlaceholderNode? @@ -1076,12 +1078,21 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { } } + private var didRestoreContentOffset = false private func dequeueTransaction() { if self.enqueuedTransactions.isEmpty { return } let transaction = self.enqueuedTransactions.removeFirst() self.gridNode.transaction(GridNodeTransaction(deleteItems: transaction.deletions, insertItems: transaction.insertions, updateItems: transaction.updates, scrollToItem: transaction.scrollToItem, updateLayout: nil, itemTransition: .immediate, stationaryItems: .none, updateFirstIndexInSectionOffset: nil), completion: { _ in }) + + if let subject = self.controller?.subject, case .assets(_, .story) = subject, let contentOffset = savedStoriesContentOffset, !self.didRestoreContentOffset { + if contentOffset > 64.0 { + self.gridNode.scrollView.setContentOffset(CGPoint(x: 0.0, y: contentOffset), animated: false) + self.controller?.requestAttachmentMenuExpansion() + } + self.didRestoreContentOffset = true + } } func scrollToTop(animated: Bool = false) { @@ -1861,10 +1872,17 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable { self.dismiss() } - public override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) { + public override func dismiss(completion: (() -> Void)? = nil) { self.controllerNode.cancelAssetDownloads() - super.dismiss(animated: flag, completion: completion) + if case .assets(_, .story) = self.subject { + let contentOffset = self.controllerNode.gridNode.scrollView.contentOffset.y + if contentOffset > 100.0 || savedStoriesContentOffset != nil { + savedStoriesContentOffset = contentOffset + } + } + + super.dismiss(completion: completion) } @objc private func rightButtonPressed() { diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 1aa0445953..e8ad0b7393 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -5744,6 +5744,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController return false } + private var isPanningList = false @objc func panGesture(_ recognizer: UIPanGestureRecognizer) { guard let (layout, _) = self.validLayout else { return @@ -5765,6 +5766,19 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController self.controller?.dismissAllTooltips() + let location = recognizer.location(in: self.listContainer.view) + let isPanningList: Bool + if self.listNode.frame.contains(location) { + if case let .known(value) = contentOffset, value <= 0.5 { + isPanningList = false + } else { + isPanningList = true + } + } else { + isPanningList = false + } + self.isPanningList = isPanningList + if case .fullscreen = self.displayMode, case .compact = layout.metrics.widthClass { self.isPanning = true @@ -5789,9 +5803,11 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController return } - let translateBounds: Bool + var translateBounds = false if case .regular = layout.metrics.widthClass { - translateBounds = true + if !self.isPanningList { + translateBounds = true + } } else { switch self.displayMode { case let .modal(isExpanded, previousIsFilled): @@ -5960,52 +5976,56 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController } else { self.panGestureArguments = nil var dismissing = false - if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) { - if self.isScheduling { - self.dismissScheduled() - dismissing = true - } else if case .regular = layout.metrics.widthClass { - self.controller?.dismiss(closing: false, manual: true) - dismissing = true - } else { - if case .fullscreen = self.displayMode { - } else { + if case .regular = layout.metrics.widthClass, self.isPanningList { + + } else { + if bounds.minY < -60 || (bounds.minY < 0.0 && velocity.y > 300.0) { + if self.isScheduling { + self.dismissScheduled() + dismissing = true + } else if case .regular = layout.metrics.widthClass { self.controller?.dismiss(closing: false, manual: true) dismissing = true + } else { + if case .fullscreen = self.displayMode { + } else { + self.controller?.dismiss(closing: false, manual: true) + dismissing = true + } } - } - } else if !self.isScheduling && (velocity.y < -300.0 || offset < topInset / 2.0) { - if velocity.y > -2200.0 && !self.isFullscreen { - DispatchQueue.main.async { - self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + } else if !self.isScheduling && (velocity.y < -300.0 || offset < topInset / 2.0) { + if velocity.y > -2200.0 && !self.isFullscreen { + DispatchQueue.main.async { + self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + } } + + let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset) + let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity)) + if case .modal = self.displayMode { + self.displayMode = .modal(isExpanded: true, isFilled: true) + } + self.updateDecorationsColors() + self.animatingExpansion = true + + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: transition) + } + self.updateDecorationsLayout(transition: transition, completion: { + self.animatingExpansion = false + }) + } else if !self.isScheduling { + self.updateDecorationsColors() + self.animatingExpansion = true + self.listNode.scroller.setContentOffset(CGPoint(), animated: false) + + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .easeInOut)) + } + self.updateDecorationsLayout(transition: .animated(duration: 0.3, curve: .easeInOut), completion: { + self.animatingExpansion = false + }) } - - let initialVelocity: CGFloat = offset.isZero ? 0.0 : abs(velocity.y / offset) - let transition = ContainedViewLayoutTransition.animated(duration: 0.45, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity)) - if case .modal = self.displayMode { - self.displayMode = .modal(isExpanded: true, isFilled: true) - } - self.updateDecorationsColors() - self.animatingExpansion = true - - if let (layout, navigationHeight) = self.validLayout { - self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: transition) - } - self.updateDecorationsLayout(transition: transition, completion: { - self.animatingExpansion = false - }) - } else if !self.isScheduling { - self.updateDecorationsColors() - self.animatingExpansion = true - self.listNode.scroller.setContentOffset(CGPoint(), animated: false) - - if let (layout, navigationHeight) = self.validLayout { - self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.3, curve: .easeInOut)) - } - self.updateDecorationsLayout(transition: .animated(duration: 0.3, curve: .easeInOut), completion: { - self.animatingExpansion = false - }) } if !dismissing { var bounds = self.contentContainer.bounds diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index 5d62b7da7f..fa8d3ac974 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -245,7 +245,16 @@ private final class CameraScreenComponent: CombinedComponent { func setupRecentAssetSubscription() { let mediaAssetsContext = MediaAssetsContext() self.mediaAssetsContext = mediaAssetsContext - self.lastGalleryAssetsDisposable = (mediaAssetsContext.recentAssets() + + self.lastGalleryAssetsDisposable = ( + mediaAssetsContext.mediaAccess() + |> mapToSignal { [weak mediaAssetsContext] status in + if case .authorized = status, let mediaAssetsContext { + return mediaAssetsContext.recentAssets() + } else { + return .complete() + } + } |> map { fetchResult in return fetchResult?.lastObject } @@ -258,6 +267,13 @@ private final class CameraScreenComponent: CombinedComponent { }) } + func requestMediaAccess(completion: @escaping () -> Void) { + guard let mediaAssetsContext = self.mediaAssetsContext else { + return + } + mediaAssetsContext.requestMediaAccess(completion: completion) + } + func setupVolumeButtonsHandler() { guard self.volumeButtonsListener == nil else { return @@ -687,11 +703,13 @@ private final class CameraScreenComponent: CombinedComponent { } state.togglePosition(animateFlipAction) }, - galleryTapped: { + galleryTapped: { [weak state] in guard let controller = environment.controller() as? CameraScreen else { return } - controller.presentGallery() + state?.requestMediaAccess { + controller.presentGallery() + } }, swipeHintUpdated: { [weak state] hint in if let state { diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/MediaAssetsContext.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/MediaAssetsContext.swift index ec26d5df5d..a07cb0f039 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/MediaAssetsContext.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/MediaAssetsContext.swift @@ -95,8 +95,13 @@ public final class MediaAssetsContext: NSObject, PHPhotoLibraryChangeObserver { ) } - public func requestMediaAccess() -> Void { + public func requestMediaAccess(completion: @escaping () -> Void = {}) -> Void { PHPhotoLibrary.requestAuthorization { [weak self] status in + Queue.mainQueue().async { + if case .authorized = status { + completion() + } + } self?.mediaAccessSink.putNext(status) } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 8b37ea1697..de4eb22d86 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -3799,7 +3799,7 @@ public final class EmojiPagerContentComponent: Component { } } contextGesture.activatedAfterCompletion = { [weak self] point, wasTap in - guard let `self` = self, let component = self.component else { + guard let self, let component = self.component, !self.isSearchActivated else { return } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 2e99ced89c..3793480b07 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -1038,13 +1038,15 @@ final class MediaEditorScreenComponent: Component { isGeneralThreadClosed: nil ) - let heightAndOverflow = inputMediaNode.updateLayout(width: availableSize.width, leftInset: 0.0, rightInset: 0.0, bottomInset: component.bottomSafeInset, standardInputHeight: environment.deviceMetrics.standardInputHeight(inLandscape: false), inputHeight: environment.inputHeight, maximumHeight: availableSize.height, inputPanelHeight: 0.0, transition: .immediate, interfaceState: presentationInterfaceState, layoutMetrics: environment.metrics, deviceMetrics: environment.deviceMetrics, isVisible: true, isExpanded: false) + let availableInputMediaWidth = previewSize.width + let heightAndOverflow = inputMediaNode.updateLayout(width: availableInputMediaWidth, leftInset: 0.0, rightInset: 0.0, bottomInset: component.bottomSafeInset, standardInputHeight: environment.deviceMetrics.standardInputHeight(inLandscape: false), inputHeight: environment.inputHeight, maximumHeight: availableSize.height, inputPanelHeight: 0.0, transition: .immediate, interfaceState: presentationInterfaceState, layoutMetrics: environment.metrics, deviceMetrics: environment.deviceMetrics, isVisible: true, isExpanded: false) let inputNodeHeight = heightAndOverflow.0 - let inputNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - inputNodeHeight), size: CGSize(width: availableSize.width, height: inputNodeHeight)) + let inputNodeFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - availableInputMediaWidth) / 2.0), y: availableSize.height - inputNodeHeight), size: CGSize(width: availableInputMediaWidth, height: inputNodeHeight)) transition.setFrame(layer: inputMediaNode.layer, frame: inputNodeFrame) - inputHeight = heightAndOverflow.0 - keyboardHeight = max(keyboardHeight, heightAndOverflow.0) + if inputNodeHeight > 0.0 { + inputHeight = inputNodeHeight + } } else if let inputMediaNode = self.inputMediaNode { self.inputMediaNode = nil @@ -1074,6 +1076,8 @@ final class MediaEditorScreenComponent: Component { }) } + keyboardHeight = inputHeight + let nextInputMode: MessageInputPanelComponent.InputMode switch self.currentInputMode { case .text: diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index e7200776fe..63ed52484e 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -305,6 +305,7 @@ final class ShareWithPeersScreenComponent: Component { private var ignoreScrolling: Bool = false private var isDismissed: Bool = false + private var savedSelectedPeers: [EnginePeer.Id] = [] private var selectedPeers: [EnginePeer.Id] = [] private var selectedCategories = Set() private var selectedOptions = Set() @@ -586,6 +587,7 @@ final class ShareWithPeersScreenComponent: Component { visibleBounds.size.height += itemLayout.topInset var visibleFrame = self.scrollView.frame + visibleFrame.origin.x = 0.0 visibleFrame.origin.y -= itemLayout.topInset visibleFrame.size.height += itemLayout.topInset @@ -675,7 +677,7 @@ final class ShareWithPeersScreenComponent: Component { if minSectionHeader == nil { minSectionHeader = sectionHeaderView } - sectionHeaderTransition.setFrame(view: sectionHeaderView, frame: sectionHeaderFrame) + sectionHeaderTransition.setFrame(view: sectionHeaderView, frame: sectionHeaderFrame.offsetBy(dx: self.scrollView.frame.minX, dy: 0.0)) } } } @@ -721,7 +723,14 @@ final class ShareWithPeersScreenComponent: Component { } if self.selectedCategories.contains(categoryId) { } else { - self.selectedPeers = [] + if self.selectedCategories.contains(.selectedContacts) { + self.savedSelectedPeers = self.selectedPeers + } + if categoryId == .selectedContacts { + self.selectedPeers = self.savedSelectedPeers + } else { + self.selectedPeers = [] + } self.selectedCategories.removeAll() self.selectedCategories.insert(categoryId) From ae60c2be8b2281674640c5cf8d40e5f63a634617 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 15 Jul 2023 02:38:57 +0200 Subject: [PATCH 2/4] Various improvements --- .../DrawingUI/Sources/DrawingTextEntity.swift | 1 + .../State/UserLimitsConfiguration.swift | 9 +++- .../Data/ConfigurationData.swift | 8 ++- .../TelegramEngine/Data/ContactsData.swift | 18 +++++++ .../Sources/Utils/PeerUtils.swift | 9 ++++ .../Sources/MediaEditorScreen.swift | 13 ++++- .../Sources/ShareWithPeersScreen.swift | 54 ++++++++++++++----- .../Sources/StoryContainerScreen.swift | 6 +++ .../StoryItemSetContainerComponent.swift | 14 ++++- .../TooltipUI/Sources/TooltipScreen.swift | 2 +- 10 files changed, 113 insertions(+), 21 deletions(-) diff --git a/submodules/DrawingUI/Sources/DrawingTextEntity.swift b/submodules/DrawingUI/Sources/DrawingTextEntity.swift index ffcc9844c9..1ea5cc98c7 100644 --- a/submodules/DrawingUI/Sources/DrawingTextEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingTextEntity.swift @@ -589,6 +589,7 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate self.textView.layer.shadowOpacity = 0.0 self.textView.layer.shadowRadius = 0.0 } + self.textView.textAlignment = self.textEntity.alignment.alignment self.updateText(keepSelectedRange: afterAppendingEmoji) diff --git a/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift b/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift index 6ec79782e3..e40e3c4dda 100644 --- a/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift +++ b/submodules/TelegramCore/Sources/State/UserLimitsConfiguration.swift @@ -18,6 +18,7 @@ public struct UserLimitsConfiguration: Equatable { public let maxSharedFolderInviteLinks: Int32 public let maxSharedFolderJoin: Int32 public let maxStoryCaptionLength: Int32 + public let maxExpiringStoriesCount: Int32 public static var defaultValue: UserLimitsConfiguration { return UserLimitsConfiguration( @@ -36,7 +37,8 @@ public struct UserLimitsConfiguration: Equatable { maxReactionsPerMessage: 1, maxSharedFolderInviteLinks: 3, maxSharedFolderJoin: 2, - maxStoryCaptionLength: 1024 + maxStoryCaptionLength: 1024, + maxExpiringStoriesCount: 100 ) } @@ -56,7 +58,8 @@ public struct UserLimitsConfiguration: Equatable { maxReactionsPerMessage: Int32, maxSharedFolderInviteLinks: Int32, maxSharedFolderJoin: Int32, - maxStoryCaptionLength: Int32 + maxStoryCaptionLength: Int32, + maxExpiringStoriesCount: Int32 ) { self.maxPinnedChatCount = maxPinnedChatCount self.maxArchivedPinnedChatCount = maxArchivedPinnedChatCount @@ -74,6 +77,7 @@ public struct UserLimitsConfiguration: Equatable { self.maxSharedFolderInviteLinks = maxSharedFolderInviteLinks self.maxSharedFolderJoin = maxSharedFolderJoin self.maxStoryCaptionLength = maxStoryCaptionLength + self.maxExpiringStoriesCount = maxExpiringStoriesCount } } @@ -114,5 +118,6 @@ extension UserLimitsConfiguration { self.maxSharedFolderInviteLinks = getValue("chatlist_invites_limit", orElse: isPremium ? 100 : 3) self.maxSharedFolderJoin = getValue("chatlists_joined_limit", orElse: isPremium ? 100 : 2) self.maxStoryCaptionLength = getGeneralValue("story_caption_length_limit", orElse: defaultValue.maxStoryCaptionLength) + self.maxExpiringStoriesCount = getGeneralValue("story_expiring_limit", orElse: defaultValue.maxExpiringStoriesCount) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift index a1aefc0da9..3e9abb4820 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift @@ -52,6 +52,7 @@ public enum EngineConfiguration { public let maxSharedFolderInviteLinks: Int32 public let maxSharedFolderJoin: Int32 public let maxStoryCaptionLength: Int32 + public let maxExpiringStoriesCount: Int32 public static var defaultValue: UserLimits { return UserLimits(UserLimitsConfiguration.defaultValue) @@ -73,7 +74,8 @@ public enum EngineConfiguration { maxReactionsPerMessage: Int32, maxSharedFolderInviteLinks: Int32, maxSharedFolderJoin: Int32, - maxStoryCaptionLength: Int32 + maxStoryCaptionLength: Int32, + maxExpiringStoriesCount: Int32 ) { self.maxPinnedChatCount = maxPinnedChatCount self.maxArchivedPinnedChatCount = maxArchivedPinnedChatCount @@ -91,6 +93,7 @@ public enum EngineConfiguration { self.maxSharedFolderInviteLinks = maxSharedFolderInviteLinks self.maxSharedFolderJoin = maxSharedFolderJoin self.maxStoryCaptionLength = maxStoryCaptionLength + self.maxExpiringStoriesCount = maxExpiringStoriesCount } } } @@ -143,7 +146,8 @@ public extension EngineConfiguration.UserLimits { maxReactionsPerMessage: userLimitsConfiguration.maxReactionsPerMessage, maxSharedFolderInviteLinks: userLimitsConfiguration.maxSharedFolderInviteLinks, maxSharedFolderJoin: userLimitsConfiguration.maxSharedFolderJoin, - maxStoryCaptionLength: userLimitsConfiguration.maxStoryCaptionLength + maxStoryCaptionLength: userLimitsConfiguration.maxStoryCaptionLength, + maxExpiringStoriesCount: userLimitsConfiguration.maxExpiringStoriesCount ) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Data/ContactsData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Data/ContactsData.swift index 1062d29651..379889c1c7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Data/ContactsData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Data/ContactsData.swift @@ -56,5 +56,23 @@ public extension TelegramEngine.EngineData.Item { } } } + + public struct CloseFriends: TelegramEngineDataItem, PostboxViewDataItem { + public typealias Result = Array + + public init() { + } + + var key: PostboxViewKey { + return .contacts(accountPeerId: nil, includePresences: false) + } + + func extract(view: PostboxView) -> Result { + guard let view = view as? ContactPeersView else { + preconditionFailure() + } + return view.peers.filter { $0.isCloseFriend }.map(EnginePeer.init) + } + } } } diff --git a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift index 8f15e1daa5..725f889a33 100644 --- a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift @@ -189,6 +189,15 @@ public extension Peer { } } + var isCloseFriend: Bool { + switch self { + case let user as TelegramUser: + return user.flags.contains(.isCloseFriend) + default: + return false + } + } + var isCopyProtectionEnabled: Bool { switch self { case let group as TelegramGroup: diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 3793480b07..d2db133b81 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -3238,6 +3238,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate public var dismissed: () -> Void = { } public var willDismiss: () -> Void = { } + private var closeFriends = Promise<[EnginePeer]>() + private let hapticFeedback = HapticFeedback() public init( @@ -3313,6 +3315,10 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate let dropInteraction = UIDropInteraction(delegate: self) self.displayNode.view.addInteraction(dropInteraction) + + Queue.mainQueue().after(1.0) { + self.closeFriends.set(self.context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.CloseFriends())) + } } func openPrivacySettings(_ privacy: MediaEditorResultPrivacy? = nil, completion: @escaping () -> Void = {}) { @@ -3325,7 +3331,12 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate let text = self.getCaption().string let mentions = generateTextEntities(text, enabledTypes: [.mention], currentEntities: []).map { (text as NSString).substring(with: NSRange(location: $0.range.lowerBound + 1, length: $0.range.upperBound - $0.range.lowerBound - 1)) } - let stateContext = ShareWithPeersScreen.StateContext(context: self.context, subject: .stories(editing: false), initialPeerIds: Set(privacy.privacy.additionallyIncludePeers)) + let stateContext = ShareWithPeersScreen.StateContext( + context: self.context, + subject: .stories(editing: false), + initialPeerIds: Set(privacy.privacy.additionallyIncludePeers), + closeFriends: self.closeFriends.get() + ) let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).start(next: { [weak self] _ in guard let self else { return diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index 63ed52484e..fd4c7c9e97 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -1751,13 +1751,16 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { public final class State { let peers: [EnginePeer] let presences: [EnginePeer.Id: EnginePeer.Presence] + let closeFriendsPeers: [EnginePeer] fileprivate init( peers: [EnginePeer], - presences: [EnginePeer.Id: EnginePeer.Presence] + presences: [EnginePeer.Id: EnginePeer.Presence], + closeFriendsPeers: [EnginePeer] ) { self.peers = peers self.presences = presences + self.closeFriendsPeers = closeFriendsPeers } } @@ -1787,28 +1790,33 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { public init( context: AccountContext, subject: Subject = .chats, - initialPeerIds: Set = Set() + initialPeerIds: Set = Set(), + closeFriends: Signal<[EnginePeer], NoError> = .single([]) ) { self.subject = subject self.initialPeerIds = initialPeerIds switch subject { case .stories: - var signals: [Signal] = [] + var peerSignals: [Signal] = [] if initialPeerIds.count < 3 { for peerId in initialPeerIds { - signals.append(context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))) + peerSignals.append(context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))) } } - self.stateDisposable = (combineLatest(signals) - |> deliverOnMainQueue).start(next: { [weak self] peers in + + let peers = combineLatest(peerSignals) + + self.stateDisposable = combineLatest(queue: Queue.mainQueue(), peers, closeFriends) + .start(next: { [weak self] peers, closeFriends in guard let self else { return } let state = State( peers: peers.compactMap { $0 }, - presences: [:] + presences: [:], + closeFriendsPeers: closeFriends ) self.stateValue = state self.stateSubject.set(.single(state)) @@ -1840,7 +1848,8 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { let state = State( peers: peers, - presences: presences + presences: presences, + closeFriendsPeers: [] ) self.stateValue = state self.stateSubject.set(.single(state)) @@ -1894,7 +1903,8 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { let state = State( peers: peers, - presences: contactList.presences + presences: contactList.presences, + closeFriendsPeers: [] ) self.stateValue = state @@ -1902,8 +1912,17 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { self.readySubject.set(true) }) - case let .search(query, _): - self.stateDisposable = (context.engine.contacts.searchLocalPeers(query: query) + case let .search(query, onlyContacts): + let signal: Signal<[EngineRenderedPeer], NoError> + if onlyContacts { + signal = context.engine.contacts.searchContacts(query: query) + |> map { result in + return result.0.map { EngineRenderedPeer(peer: $0) } + } + } else { + signal = context.engine.contacts.searchLocalPeers(query: query) + } + self.stateDisposable = (signal |> deliverOnMainQueue).start(next: { [weak self] peers in guard let self else { return @@ -1923,7 +1942,8 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { return false } }, - presences: [:] + presences: [:], + closeFriendsPeers: [] ) self.stateValue = state self.stateSubject.set(.single(state)) @@ -1999,12 +2019,20 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { actionTitle: contactsSubtitle )) + var closeFriendsSubtitle = "edit list" + if let peers = stateContext.stateValue?.closeFriendsPeers, !peers.isEmpty { + if peers.count > 2 { + closeFriendsSubtitle = "\(peers.count) people" + } else { + closeFriendsSubtitle = String(peers.map { $0.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) }.joined(separator: ", ")) + } + } categoryItems.append(ShareWithPeersScreenComponent.CategoryItem( id: .closeFriends, title: "Close Friends", icon: "Call/StarHighlighted", iconColor: .green, - actionTitle: "edit list" + actionTitle: closeFriendsSubtitle )) var selectedContactsSubtitle = "choose" diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift index 2d181f959a..dc14099585 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift @@ -363,6 +363,7 @@ private final class StoryContainerScreenComponent: Component { private let audioModePromise = ValuePromise(.ambient, ignoreRepeated: true) private let inputMediaNodeDataPromise = Promise() + private let closeFriendsPromise = Promise<[EnginePeer]>() private var availableReactions: StoryAvailableReactions? @@ -1078,6 +1079,10 @@ private final class StoryContainerScreenComponent: Component { sendGif: nil ) ) + + self.closeFriendsPromise.set( + component.context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.CloseFriends()) + ) } var update = false @@ -1398,6 +1403,7 @@ private final class StoryContainerScreenComponent: Component { self.state?.updated(transition: .immediate) }, keyboardInputData: self.inputMediaNodeDataPromise.get(), + closeFriends: self.closeFriendsPromise.get(), sharedViewListsContext: self.sharedViewListsContext )), environment: {}, diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index d9950249fa..36f0c2e1ca 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -103,6 +103,7 @@ public final class StoryItemSetContainerComponent: Component { public let controller: () -> ViewController? public let toggleAmbientMode: () -> Void public let keyboardInputData: Signal + public let closeFriends: Signal<[EnginePeer], NoError> let sharedViewListsContext: StoryItemSetViewListComponent.SharedListsContext init( @@ -135,6 +136,7 @@ public final class StoryItemSetContainerComponent: Component { controller: @escaping () -> ViewController?, toggleAmbientMode: @escaping () -> Void, keyboardInputData: Signal, + closeFriends: Signal<[EnginePeer], NoError>, sharedViewListsContext: StoryItemSetViewListComponent.SharedListsContext ) { self.context = context @@ -166,6 +168,7 @@ public final class StoryItemSetContainerComponent: Component { self.controller = controller self.toggleAmbientMode = toggleAmbientMode self.keyboardInputData = keyboardInputData + self.closeFriends = closeFriends self.sharedViewListsContext = sharedViewListsContext } @@ -3173,16 +3176,23 @@ public final class StoryItemSetContainerComponent: Component { } private func openItemPrivacySettings(initialPrivacy: EngineStoryPrivacy? = nil) { - guard let context = self.component?.context else { + guard let component = self.component else { return } + let context = component.context + let privacy = initialPrivacy ?? self.component?.slice.item.storyItem.privacy guard let privacy else { return } - let stateContext = ShareWithPeersScreen.StateContext(context: context, subject: .stories(editing: true), initialPeerIds: Set(privacy.additionallyIncludePeers)) + let stateContext = ShareWithPeersScreen.StateContext( + context: context, + subject: .stories(editing: true), + initialPeerIds: Set(privacy.additionallyIncludePeers), + closeFriends: component.closeFriends + ) let _ = (stateContext.ready |> filter { $0 } |> take(1) |> deliverOnMainQueue).start(next: { [weak self] _ in guard let self else { return diff --git a/submodules/TooltipUI/Sources/TooltipScreen.swift b/submodules/TooltipUI/Sources/TooltipScreen.swift index 7776d648e1..4f2b673a16 100644 --- a/submodules/TooltipUI/Sources/TooltipScreen.swift +++ b/submodules/TooltipUI/Sources/TooltipScreen.swift @@ -542,7 +542,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode { animationSpacing = 8.0 } - let containerWidth = max(100.0, min(layout.size.width, 614.0) - sideInset * 2.0) + let containerWidth = max(100.0, min(layout.size.width - sideInset * 2.0, 614.0)) var actionSize: CGSize = .zero From d88cd4f7c4379422648e6bc6a013dfaecc4e0cf1 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 15 Jul 2023 03:08:32 +0200 Subject: [PATCH 3/4] Various improvements --- submodules/DrawingUI/BUILD | 1 + .../DrawingUI/Sources/DrawingScreen.swift | 6 ++ .../DrawingUI/Sources/DrawingTextEntity.swift | 82 +++++++++++++++++-- .../Sources/Drawing/DrawingTextEntity.swift | 18 ---- .../Sources/MediaToolsScreen.swift | 16 ++-- .../Sources/TextFieldComponent.swift | 3 +- 6 files changed, 93 insertions(+), 33 deletions(-) diff --git a/submodules/DrawingUI/BUILD b/submodules/DrawingUI/BUILD index 35c361084d..74789fe4ec 100644 --- a/submodules/DrawingUI/BUILD +++ b/submodules/DrawingUI/BUILD @@ -97,6 +97,7 @@ swift_library( "//submodules/ChatPresentationInterfaceState:ChatPresentationInterfaceState", "//submodules/StickerPackPreviewUI:StickerPackPreviewUI", "//submodules/TelegramUI/Components/LottieComponent", + "//submodules/ImageTransparency", ], visibility = [ "//visibility:public", diff --git a/submodules/DrawingUI/Sources/DrawingScreen.swift b/submodules/DrawingUI/Sources/DrawingScreen.swift index bebb78e69b..9e8944c062 100644 --- a/submodules/DrawingUI/Sources/DrawingScreen.swift +++ b/submodules/DrawingUI/Sources/DrawingScreen.swift @@ -3127,6 +3127,12 @@ public final class DrawingToolsInteraction { if let entityView = self.entitiesView.getView(for: entity.uuid) { if let textEntityView = entityView as? DrawingTextEntityView { textEntityView.beginEditing(accessoryView: self.textEditAccessoryView) + + textEntityView.replaceWithImage = { [weak self] image, isSticker in + if let self { + self.insertEntity(DrawingStickerEntity(content: .image(image, isSticker ? .sticker : .rectangle)), scale: 2.5) + } + } } else { if self.isVideo { entityView.seek(to: 0.0) diff --git a/submodules/DrawingUI/Sources/DrawingTextEntity.swift b/submodules/DrawingUI/Sources/DrawingTextEntity.swift index 1ea5cc98c7..6597b1616e 100644 --- a/submodules/DrawingUI/Sources/DrawingTextEntity.swift +++ b/submodules/DrawingUI/Sources/DrawingTextEntity.swift @@ -6,6 +6,8 @@ import AccountContext import TextFormat import EmojiTextAttachmentView import MediaEditor +import MobileCoreServices +import ImageTransparency extension DrawingTextEntity.Alignment { var alignment: NSTextAlignment { @@ -30,6 +32,7 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? var textChanged: () -> Void = {} + var replaceWithImage: (UIImage, Bool) -> Void = { _, _ in } init(context: AccountContext, entity: DrawingTextEntity) { self.textView = DrawingTextView(frame: .zero) @@ -64,6 +67,10 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate return EmojiTextAttachmentView(context: context, userLocation: .other, emoji: emoji, file: emoji.file, cache: strongSelf.context.animationCache, renderer: strongSelf.context.animationRenderer, placeholderColor: UIColor.white.withAlphaComponent(0.12), pointSize: CGSize(width: pointSize, height: pointSize)) } + self.textView.onPaste = { [weak self] in + return self?.onPaste() ?? false + } + self.update(animated: false) } @@ -88,6 +95,52 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate self.endEditing() } + private func onPaste() -> Bool { + let pasteboard = UIPasteboard.general + + var images: [UIImage] = [] + var isPNG = false + var isMemoji = false + for item in pasteboard.items { + if let image = item["com.apple.png-sticker"] as? UIImage { + images.append(image) + isPNG = true + isMemoji = true + } else if let image = item[kUTTypePNG as String] as? UIImage { + images.append(image) + isPNG = true + } else if let image = item["com.apple.uikit.image"] as? UIImage { + images.append(image) + isPNG = true + } else if let image = item[kUTTypeJPEG as String] as? UIImage { + images.append(image) + } else if let image = item[kUTTypeGIF as String] as? UIImage { + images.append(image) + } + } + + if isPNG && images.count == 1, let image = images.first, let cgImage = image.cgImage { + let maxSide = max(image.size.width, image.size.height) + if maxSide.isZero { + return false + } + let aspectRatio = min(image.size.width, image.size.height) / maxSide + if isMemoji || (imageHasTransparency(cgImage) && aspectRatio > 0.2) { + self.endEditing(reset: true) + self.replaceWithImage(image, true) + return false + } + } + + if !images.isEmpty, let image = images.first { + self.endEditing(reset: true) + self.replaceWithImage(image, false) + return false + } + + return true + } + private var emojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] func updateEntities() { self.textView.drawingLayoutManager.ensureLayout(for: self.textView.textContainer) @@ -1270,12 +1323,6 @@ final class DrawingTextView: UITextView, NSLayoutManagerDelegate { self.fixTypingAttributes() } - override func paste(_ sender: Any?) { - self.fixTypingAttributes() - super.paste(sender) - self.fixTypingAttributes() - } - fileprivate func fixTypingAttributes() { var attributes: [NSAttributedString.Key: Any] = [:] if let font = self.font { @@ -1347,6 +1394,29 @@ final class DrawingTextView: UITextView, NSLayoutManagerDelegate { self.onLayersUpdate?() } + + var onPaste: () -> Bool = { return true } + override func paste(_ sender: Any?) { + if !self.text.isEmpty || self.onPaste() { + self.fixTypingAttributes() + super.paste(sender) + self.fixTypingAttributes() + } + } + + override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { + if action == #selector(self.paste(_:)) { + if UIPasteboard.general.hasImages && self.text.isEmpty { + return true + } + } + if #available(iOS 15.0, *) { + if action == #selector(captureTextFromCamera(_:)) { + return false + } + } + return super.canPerformAction(action, withSender: sender) + } } private var availableFonts: [String: (String, String)] = { diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingTextEntity.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingTextEntity.swift index e77f711caf..af589e6759 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingTextEntity.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/DrawingTextEntity.swift @@ -302,22 +302,4 @@ public final class DrawingTextEntity: DrawingEntity, Codable { } return true } - -// public weak var currentEntityView: DrawingEntityView? -// public func makeView(context: AccountContext) -> DrawingEntityView { -// let entityView = DrawingTextEntityView(context: context, entity: self) -// self.currentEntityView = entityView -// return entityView -// } -// -// public func prepareForRender() { -// self.renderImage = (self.currentEntityView as? DrawingTextEntityView)?.getRenderImage() -// self.renderSubEntities = (self.currentEntityView as? DrawingTextEntityView)?.getRenderSubEntities() -// -// if case .none = self.animation { -// self.renderAnimationFrames = nil -// } else { -// self.renderAnimationFrames = (self.currentEntityView as? DrawingTextEntityView)?.getRenderAnimationFrames() -// } -// } } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift index 28b084dbaa..551b50ca83 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaToolsScreen.swift @@ -646,15 +646,15 @@ private final class MediaToolsScreenComponent: Component { minValue: 0.0, maxValue: 1.0, startValue: 0.0 - ), - AdjustmentTool( - key: .sharpen, - title: "Sharpen", - value: mediaEditor?.getToolValue(.sharpen) as? Float ?? 0.0, - minValue: 0.0, - maxValue: 1.0, - startValue: 0.0 ) +// AdjustmentTool( +// key: .sharpen, +// title: "Sharpen", +// value: mediaEditor?.getToolValue(.sharpen) as? Float ?? 0.0, +// minValue: 0.0, +// maxValue: 1.0, +// startValue: 0.0 +// ) ] if !component.mediaEditor.sourceIsVideo { diff --git a/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift b/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift index 2c69d927b7..c953ce79b3 100644 --- a/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift +++ b/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift @@ -287,7 +287,6 @@ public final class TextFieldComponent: Component { return false } - var images: [UIImage] = [] if let data = pasteboard.data(forPasteboardType: "com.compuserve.gif") { component.paste(.gif(data)) return false @@ -295,6 +294,7 @@ public final class TextFieldComponent: Component { component.paste(.video(data)) return false } else { + var images: [UIImage] = [] var isPNG = false var isMemoji = false for item in pasteboard.items { @@ -332,6 +332,7 @@ public final class TextFieldComponent: Component { return false } } + return true } From 547564eac36f3ef601902f5fc93dc76aac4ef33b Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 15 Jul 2023 14:34:49 +0200 Subject: [PATCH 4/4] Various fixes --- .../Components/CameraScreen/Sources/CameraScreen.swift | 9 ++++++--- .../MediaEditorScreen/Sources/MediaEditorScreen.swift | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift index fa8d3ac974..adf12ee39c 100644 --- a/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift +++ b/submodules/TelegramUI/Components/CameraScreen/Sources/CameraScreen.swift @@ -1368,15 +1368,15 @@ public class CameraScreen: ViewController { ) |> filter { $0 && $1 } |> take(1)).start(next: { [weak self] _, _ in - self?.mainPreviewView.removePlaceholder(delay: 0.15) - self?.additionalPreviewView.removePlaceholder(delay: 0.15) + self?.mainPreviewView.removePlaceholder(delay: 0.35) + self?.additionalPreviewView.removePlaceholder(delay: 0.35) }) } else { let _ = (self.mainPreviewView.isPreviewing |> filter { $0 } |> take(1) |> deliverOnMainQueue).start(next: { [weak self] _ in - self?.mainPreviewView.removePlaceholder(delay: 0.15) + self?.mainPreviewView.removePlaceholder(delay: 0.35) }) } } else { @@ -1581,6 +1581,9 @@ public class CameraScreen: ViewController { if gestureRecognizer is UIPanGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer { return false } + if gestureRecognizer is UIPinchGestureRecognizer && otherGestureRecognizer is UIPanGestureRecognizer { + return false + } return true } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index d2db133b81..dc1027ffcb 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -2091,6 +2091,12 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate } else { self.mediaEditor?.play() } + } else if self.mediaEditor?.sourceIsVideo == true { + if isInteracting { + self.mediaEditor?.stop() + } else { + self.mediaEditor?.play() + } } self.isInteractingWithEntities = isInteracting if !isInteracting {