From 546c6322d6c24628bb3c5225399593162ddf91ca Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 11 Sep 2018 17:13:45 +0100 Subject: [PATCH] no message --- TelegramUI.xcodeproj/project.pbxproj | 14 +- TelegramUI/BotCheckoutActionButton.swift | 2 +- .../BotCheckoutInfoControllerNode.swift | 75 ++++++--- TelegramUI/BotPaymentFieldItemNode.swift | 7 +- TelegramUI/ChatImageGalleryItem.swift | 10 +- TelegramUI/DeviceContactData.swift | 6 +- TelegramUI/DeviceContactInfoController.swift | 5 +- TelegramUI/GalleryControllerNode.swift | 5 + TelegramUI/GalleryPagerNode.swift | 9 ++ .../GalleryThumbnailContainerNode.swift | 143 ++++++++++++++---- TelegramUI/InstantImageGalleryItem.swift | 13 +- TelegramUI/ItemListTextWithLabelItem.swift | 2 +- TelegramUI/PeerAvatarImageGalleryItem.swift | 14 +- TelegramUI/SecureIdAuthFormFieldNode.swift | 32 +++- TelegramUI/ShareController.swift | 3 +- TelegramUI/UniversalVideoCalleryItem.swift | 16 +- TelegramUI/YoutubeEmbedImplementation.swift | 6 +- 17 files changed, 274 insertions(+), 88 deletions(-) diff --git a/TelegramUI.xcodeproj/project.pbxproj b/TelegramUI.xcodeproj/project.pbxproj index c1c9b89fcf..eb87106474 100644 --- a/TelegramUI.xcodeproj/project.pbxproj +++ b/TelegramUI.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 091EB4EB213F48B4005284DE /* Vision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 094981C52138D73B00A10660 /* Vision.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 091BEAB3214552D9003AEA30 /* Vision.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D02DADBE2138D76F00116225 /* Vision.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 09310D2C213ED5FB0020033A /* anim_read.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D14213BC5DE0020033A /* anim_read.json */; }; 09310D2D213ED5FB0020033A /* anim_pin.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D15213BC5DE0020033A /* anim_pin.json */; }; 09310D2E213ED5FB0020033A /* anim_unmute.json in Resources */ = {isa = PBXBuildFile; fileRef = 09310D16213BC5DE0020033A /* anim_unmute.json */; }; @@ -1029,7 +1029,6 @@ 0941A99F210B057200EBE194 /* OpenInActionSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInActionSheetController.swift; sourceTree = ""; }; 0941A9A3210B0E2E00EBE194 /* OpenInAppIconResources.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInAppIconResources.swift; sourceTree = ""; }; 0941A9A5210B822D00EBE194 /* OpenInOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInOptions.swift; sourceTree = ""; }; - 094981C52138D73B00A10660 /* Vision.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Vision.framework; path = System/Library/Frameworks/Vision.framework; sourceTree = SDKROOT; }; 09797872210633CD0077D77F /* InstantPageSettingsButtonItemNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantPageSettingsButtonItemNode.swift; sourceTree = ""; }; 0979787B210642CB0077D77F /* WebEmbedPlayerNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebEmbedPlayerNode.swift; sourceTree = ""; }; 0979787D210646C00077D77F /* YoutubeEmbedImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = YoutubeEmbedImplementation.swift; sourceTree = ""; }; @@ -2117,8 +2116,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 091BEAB3214552D9003AEA30 /* Vision.framework in Frameworks */, D0C45E9F213FFAFD00988156 /* Lottie.framework in Frameworks */, - 091EB4EB213F48B4005284DE /* Vision.framework in Frameworks */, D00ACA4B20222C280045D427 /* libtgvoip.framework in Frameworks */, D07BCBFE1F2B792300ED97AA /* LegacyComponents.framework in Frameworks */, D053B4371F1A9CA000E2D58A /* WebKit.framework in Frameworks */, @@ -2155,14 +2154,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 091EB4E8213F3D86005284DE /* Recovered References */ = { - isa = PBXGroup; - children = ( - 094981C52138D73B00A10660 /* Vision.framework */, - ); - name = "Recovered References"; - sourceTree = ""; - }; 09310D13213BC5DE0020033A /* Animations */ = { isa = PBXGroup; children = ( @@ -4372,7 +4363,6 @@ D0FC408C1D5B8E7500261D9D /* TelegramUITests */, D0FC40801D5B8E7400261D9D /* Products */, D08D45281D5E340200A7428A /* Frameworks */, - 091EB4E8213F3D86005284DE /* Recovered References */, ); sourceTree = ""; }; diff --git a/TelegramUI/BotCheckoutActionButton.swift b/TelegramUI/BotCheckoutActionButton.swift index ede3d2ccf1..7a593ebafd 100644 --- a/TelegramUI/BotCheckoutActionButton.swift +++ b/TelegramUI/BotCheckoutActionButton.swift @@ -41,7 +41,7 @@ enum BotCheckoutActionButtonState: Equatable { private let titleFont = Font.semibold(17.0) -final class BotCheckoutActionButton: HighlightTrackingButtonNode { +final class BotCheckoutActionButton: HighlightableButtonNode { static var diameter: CGFloat = 48.0 private var inactiveFillColor: UIColor diff --git a/TelegramUI/BotCheckoutInfoControllerNode.swift b/TelegramUI/BotCheckoutInfoControllerNode.swift index 1e9e365e33..19bc6d1e12 100644 --- a/TelegramUI/BotCheckoutInfoControllerNode.swift +++ b/TelegramUI/BotCheckoutInfoControllerNode.swift @@ -225,9 +225,44 @@ final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollVi } } + let fieldsAndTypes = { [weak self] () -> [(BotPaymentFieldItemNode, BotCheckoutInfoControllerFocus)] in + guard let strongSelf = self else { + return [] + } + var fieldsAndTypes: [(BotPaymentFieldItemNode, BotCheckoutInfoControllerFocus)] = [] + if let addressItems = strongSelf.addressItems { + fieldsAndTypes.append((addressItems.address1, .address(.street1))) + fieldsAndTypes.append((addressItems.address2, .address(.street2))) + fieldsAndTypes.append((addressItems.city, .address(.city))) + fieldsAndTypes.append((addressItems.state, .address(.state))) + fieldsAndTypes.append((addressItems.postcode, .address(.postcode))) + } + if let nameItem = strongSelf.nameItem { + fieldsAndTypes.append((nameItem, .name)) + } + if let phoneItem = strongSelf.phoneItem { + fieldsAndTypes.append((phoneItem, .phone)) + } + if let emailItem = strongSelf.emailItem { + fieldsAndTypes.append((emailItem, .email)) + } + return fieldsAndTypes + } + for items in itemNodes { for item in items { if let item = item as? BotPaymentFieldItemNode { + item.focused = { [weak self, weak item] in + guard let strongSelf = self, let item = item else { + return + } + for (node, focus) in fieldsAndTypes() { + if node === item { + strongSelf.focus = focus + break + } + } + } item.textUpdated = { [weak self] in self?.updateDone() } @@ -236,32 +271,13 @@ final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollVi return } - var fieldsAndTypes: [(BotPaymentFieldItemNode, BotCheckoutInfoControllerFocus)] = [] - if let addressItems = strongSelf.addressItems { - fieldsAndTypes.append((addressItems.address1, .address(.street1))) - fieldsAndTypes.append((addressItems.address2, .address(.street2))) - fieldsAndTypes.append((addressItems.city, .address(.city))) - fieldsAndTypes.append((addressItems.state, .address(.state))) - fieldsAndTypes.append((addressItems.postcode, .address(.postcode))) - } - if let nameItem = strongSelf.nameItem { - fieldsAndTypes.append((nameItem, .name)) - } - if let phoneItem = strongSelf.phoneItem { - fieldsAndTypes.append((phoneItem, .phone)) - } - if let emailItem = strongSelf.emailItem { - fieldsAndTypes.append((emailItem, .email)) - } - - var activateNext = true + var activateNext = false outer: for section in strongSelf.itemNodes { for i in 0 ..< section.count { if section[i] === item { activateNext = true } else if activateNext, let field = section[i] as? BotPaymentFieldItemNode { - - for (node, focus) in fieldsAndTypes { + for (node, focus) in fieldsAndTypes() { if node === field { strongSelf.focus = focus if let containerLayout = strongSelf.containerLayout { @@ -431,8 +447,19 @@ final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollVi if let focus = self.focus { var focusItem: ASDisplayNode? switch focus { - case .address: - focusItem = self.addressItems?.address1 + case let .address(field): + switch field { + case .street1: + focusItem = self.addressItems?.address1 + case .street2: + focusItem = self.addressItems?.address2 + case .city: + focusItem = self.addressItems?.city + case .state: + focusItem = self.addressItems?.state + case .postcode: + focusItem = self.addressItems?.postcode + } case .name: focusItem = self.nameItem case .email: @@ -447,7 +474,7 @@ final class BotCheckoutInfoControllerNode: ViewControllerTracingNode, UIScrollVi contentOffset.y = max(contentOffset.y, -insets.top) transition.updateBounds(node: self.scrollNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: contentOffset.y), size: layout.size)) - if previousLayout == nil, let focusItem = focusItem as? BotPaymentFieldItemNode { + if let focusItem = focusItem as? BotPaymentFieldItemNode { focusItem.activateInput() } } diff --git a/TelegramUI/BotPaymentFieldItemNode.swift b/TelegramUI/BotPaymentFieldItemNode.swift index c365ffe9c4..03bf732aff 100644 --- a/TelegramUI/BotPaymentFieldItemNode.swift +++ b/TelegramUI/BotPaymentFieldItemNode.swift @@ -29,6 +29,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate { private var theme: PresentationTheme? + var focused: (() -> Void)? var textUpdated: (() -> Void)? var returnPressed: (() -> Void)? @@ -50,7 +51,7 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate { case .name, .address: self.textField.textField.autocorrectionType = .no case .phoneNumber: - self.textField.textField.keyboardType = .numberPad + self.textField.textField.keyboardType = .phonePad if #available(iOSApplicationExtension 10.0, *) { self.textField.textField.textContentType = .telephoneNumber } @@ -122,6 +123,10 @@ final class BotPaymentFieldItemNode: BotPaymentItemNode, UITextFieldDelegate { self.textUpdated?() } + func textFieldDidBeginEditing(_ textField: UITextField) { + self.focused?() + } + func textFieldShouldReturn(_ textField: UITextField) -> Bool { self.returnPressed?() return false diff --git a/TelegramUI/ChatImageGalleryItem.swift b/TelegramUI/ChatImageGalleryItem.swift index 2f7f34a06f..a2b3caf2d6 100644 --- a/TelegramUI/ChatImageGalleryItem.swift +++ b/TelegramUI/ChatImageGalleryItem.swift @@ -30,9 +30,11 @@ enum ChatMediaGalleryThumbnail: Equatable { final class ChatMediaGalleryThumbnailItem: GalleryThumbnailItem { private let account: Account private let thumbnail: ChatMediaGalleryThumbnail + private let requestForIndex: () -> Int? - init?(account: Account, mediaReference: AnyMediaReference) { + init?(account: Account, mediaReference: AnyMediaReference, requestForIndex: @escaping () -> Int?) { self.account = account + self.requestForIndex = requestForIndex if let imageReference = mediaReference.concrete(TelegramMediaImage.self) { self.thumbnail = .image(imageReference) } else if let fileReference = mediaReference.concrete(TelegramMediaFile.self), fileReference.media.isVideo { @@ -66,6 +68,10 @@ final class ChatMediaGalleryThumbnailItem: GalleryThumbnailItem { } } } + + var index: Int? { + return self.requestForIndex() + } } class ChatImageGalleryItem: GalleryItem { @@ -132,7 +138,7 @@ class ChatImageGalleryItem: GalleryItem { } } if let mediaReference = mediaReference { - if let item = ChatMediaGalleryThumbnailItem(account: self.account, mediaReference: mediaReference) { + if let item = ChatMediaGalleryThumbnailItem(account: self.account, mediaReference: mediaReference, requestForIndex: { return 0 }) { return (Int64(id), item) } } diff --git a/TelegramUI/DeviceContactData.swift b/TelegramUI/DeviceContactData.swift index 325f9ba215..c0e64b780c 100644 --- a/TelegramUI/DeviceContactData.swift +++ b/TelegramUI/DeviceContactData.swift @@ -293,8 +293,8 @@ public final class DeviceContactExtendedData: Equatable { } } -extension DeviceContactExtendedData { - convenience init?(vcard: Data) { +public extension DeviceContactExtendedData { + public convenience init?(vcard: Data) { if #available(iOSApplicationExtension 9.0, *) { guard let contact = (try? CNContactVCardSerialization.contacts(with: vcard))?.first else { return nil @@ -340,7 +340,7 @@ extension DeviceContactExtendedData { return contact } - func serializedVCard() -> String? { + public func serializedVCard() -> String? { if #available(iOSApplicationExtension 9.0, *) { guard let data = try? CNContactVCardSerialization.data(with: [self.asMutableCNContact()]) else { return nil diff --git a/TelegramUI/DeviceContactInfoController.swift b/TelegramUI/DeviceContactInfoController.swift index 560926b9b1..867486ca31 100644 --- a/TelegramUI/DeviceContactInfoController.swift +++ b/TelegramUI/DeviceContactInfoController.swift @@ -649,7 +649,7 @@ private func deviceContactInfoEntries(account: Account, presentationData: Presen return entries } -enum DeviceContactInfoSubject { +public enum DeviceContactInfoSubject { case vcard(Peer?, DeviceContactStableId?, DeviceContactExtendedData) case filter(peer: Peer?, contactId: DeviceContactStableId?, contactData: DeviceContactExtendedData, completion: (Peer?, DeviceContactExtendedData) -> Void) case create(peer: Peer?, contactData: DeviceContactExtendedData, completion: (Peer?, DeviceContactStableId, DeviceContactExtendedData) -> Void) @@ -705,7 +705,7 @@ private final class DeviceContactInfoController: ItemListController ViewController { +public func deviceContactInfoController(account: Account, subject: DeviceContactInfoSubject, cancelled: (() -> Void)? = nil) -> ViewController { var initialState = DeviceContactInfoState() if case let .create(peer, contactData, _) = subject { var peerPhoneNumber: String? @@ -911,6 +911,7 @@ func deviceContactInfoController(account: Account, subject: DeviceContactInfoSub case .filter, .create: leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { dismissImpl?(true) + cancelled?() }) } diff --git a/TelegramUI/GalleryControllerNode.swift b/TelegramUI/GalleryControllerNode.swift index e44797390e..d8a08653c4 100644 --- a/TelegramUI/GalleryControllerNode.swift +++ b/TelegramUI/GalleryControllerNode.swift @@ -123,6 +123,11 @@ class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGestureRecog let convertedIndex = (index, progress) if strongSelf.currentThumbnailContainerNode?.groupId != centralId { node = GalleryThumbnailContainerNode(groupId: centralId) + node?.itemChanged = { [weak self] index in + if let strongSelf = self { + //strongSelf.pager.transaction(GalleryPagerTransaction(deleteItems: [], insertItems: [], updateItems: [], focusOnItem: index)) + } + } node?.updateItems(items, centralIndex: convertedIndex.0, progress: convertedIndex.1) } else { node = strongSelf.currentThumbnailContainerNode diff --git a/TelegramUI/GalleryPagerNode.swift b/TelegramUI/GalleryPagerNode.swift index 2a90ea85a8..234230800f 100644 --- a/TelegramUI/GalleryPagerNode.swift +++ b/TelegramUI/GalleryPagerNode.swift @@ -214,6 +214,10 @@ final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate { self.updateItemNodes(transition: .immediate) } + else if let focusOnItem = transaction.focusOnItem { + self.centralItemIndex = focusOnItem + self.updateItemNodes(transition: .immediate) + } } private func makeNodeForItem(at index: Int) -> GalleryItemNode { @@ -261,6 +265,11 @@ final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate { } var resetOffsetToCentralItem = false + if let centralItemIndex = self.centralItemIndex, self.visibleItemNode(at: centralItemIndex) == nil, !self.itemNodes.isEmpty { + repeat { + self.removeVisibleItemNode(internalIndex: self.itemNodes.count - 1) + } while self.itemNodes.count > 0 + } if self.itemNodes.isEmpty { let node = self.makeNodeForItem(at: self.centralItemIndex ?? 0) node.frame = CGRect(origin: CGPoint(), size: scrollView.bounds.size) diff --git a/TelegramUI/GalleryThumbnailContainerNode.swift b/TelegramUI/GalleryThumbnailContainerNode.swift index bbd2e6e812..4b0cb8cb65 100644 --- a/TelegramUI/GalleryThumbnailContainerNode.swift +++ b/TelegramUI/GalleryThumbnailContainerNode.swift @@ -3,9 +3,13 @@ import AsyncDisplayKit import Display import SwiftSignalKit +private let itemBaseSize = CGSize(width: 23.0, height: 42.0) +private let spacing: CGFloat = 2.0 + protocol GalleryThumbnailItem { func isEqual(to: GalleryThumbnailItem) -> Bool var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) { get } + var index: Int? { get } } private final class GalleryThumbnailItemNode: ASDisplayNode { @@ -30,9 +34,8 @@ private final class GalleryThumbnailItemNode: ASDisplayNode { } func updateLayout(height: CGFloat, progress: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat { - let baseWidth: CGFloat = 23.0 let boundingSize = self.imageSize.aspectFilled(CGSize(width: 1.0, height: height)) - let width = baseWidth * (1.0 - progress) + boundingSize.width * progress + let width = itemBaseSize.width * (1.0 - progress) + boundingSize.width * progress let arguments = TransformImageArguments(corners: ImageCorners(radius: 0), imageSize: boundingSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets()) let makeLayout = self.imageNode.asyncLayout() let apply = makeLayout(arguments) @@ -50,9 +53,13 @@ final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { private(set) var items: [GalleryThumbnailItem] = [] private var itemNodes: [GalleryThumbnailItemNode] = [] - private var centralIndexAndProgress: (Int, CGFloat)? + private var centralIndexAndProgress: (Int, CGFloat?)? private var currentLayout: CGSize? + private var isPanning: Bool = false + + public var itemChanged: ((Int) -> Void)? + init(groupId: Int64) { self.groupId = groupId self.scrollNode = ASScrollNode() @@ -60,10 +67,24 @@ final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { super.init() self.scrollNode.view.delegate = self + self.scrollNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) self.addSubnode(self.scrollNode) } + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) + { + let location = recognizer.location(in: recognizer.view) + for i in 0 ..< self.itemNodes.count { + let view = self.itemNodes[i] + if view.frame.contains(location) { + self.updateCentralIndexAndProgress(centralIndex: i, progress: 0.0) + self.itemChanged?(self.items[i].index!) + break + } + } + } + func updateItems(_ items: [GalleryThumbnailItem], centralIndex: Int, progress: CGFloat) { var items: [GalleryThumbnailItem] = items.count <= 1 ? [] : items var updated = false @@ -120,18 +141,40 @@ final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { } } - func updateLayout(size: CGSize, centralIndex: Int, progress: CGFloat, transition: ContainedViewLayoutTransition) { + private func contentOffsetToCenterItem(index: Int, progress: CGFloat?, contentInset: UIEdgeInsets) -> CGPoint { + let progress = progress ?? 0.0 + return CGPoint(x: -contentInset.left + (CGFloat(index) + progress) * (itemBaseSize.width + spacing), y: 0.0) + } + + func updateLayout(size: CGSize, centralIndex: Int, progress: CGFloat?, transition: ContainedViewLayoutTransition) { self.currentLayout = size self.scrollNode.frame = CGRect(origin: CGPoint(), size: size) - let spacing: CGFloat = 2.0 let centralSpacing: CGFloat = 8.0 - let itemHeight: CGFloat = 42.0 + let contentInset = UIEdgeInsetsMake(0.0, size.width / 2.0, 0.0, 0.0) + let contentSize = CGSize(width: size.width - contentInset.left + (itemBaseSize.width + spacing) * CGFloat(self.itemNodes.count - 1), height : size.height) + + var updated = false + if contentInset != self.scrollNode.view.contentInset { + self.scrollNode.view.contentInset = contentInset + updated = true + } + if contentSize != self.scrollNode.view.contentSize { + self.scrollNode.view.contentSize = contentSize + updated = true + } + + if updated || !self.isPanning { + self.scrollNode.view.contentOffset = contentOffsetToCenterItem(index: centralIndex, progress: progress, contentInset: contentInset) + } + + let progress = progress ?? 0.0 var itemFrames: [CGRect] = [] var lastTrailingSpacing: CGFloat = 0.0 + var xOffset: CGFloat = -itemBaseSize.width / 2.0 for i in 0 ..< self.itemNodes.count { let itemProgress: CGFloat - if i == centralIndex { + if i == centralIndex && !self.isPanning { itemProgress = 1.0 - abs(progress) } else if i == centralIndex - 1 { itemProgress = max(0.0, -progress) @@ -141,43 +184,26 @@ final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { itemProgress = 0.0 } let itemSpacing = itemProgress * centralSpacing + (1.0 - itemProgress) * spacing + let itemWidth = self.itemNodes[i].updateLayout(height: itemBaseSize.height, progress: itemProgress, transition: transition) + if i == centralIndex { + xOffset = -itemWidth / 2.0 + } let itemX: CGFloat if i == 0 { - itemX = lastTrailingSpacing + itemX = 0.0 } else { - itemX = lastTrailingSpacing + itemFrames[itemFrames.count - 1].maxX + itemSpacing * 0.5 + itemX = itemFrames[itemFrames.count - 1].maxX + lastTrailingSpacing + itemSpacing * 0.5 } if i == self.itemNodes.count - 1 { lastTrailingSpacing = 0.0 } else { lastTrailingSpacing = itemSpacing * 0.5 - } - let itemWidth = self.itemNodes[i].updateLayout(height: itemHeight, progress: itemProgress, transition: transition) - itemFrames.append(CGRect(origin: CGPoint(x: itemX, y: 0.0), size: CGSize(width: itemWidth, height: itemHeight))) + } + itemFrames.append(CGRect(origin: CGPoint(x: itemX, y: 0.0), size: CGSize(width: itemWidth, height: itemBaseSize.height))) } for i in 0 ..< itemFrames.count { - if i == centralIndex { - var midX = itemFrames[i].midX - if progress < 0.0 { - if i != 0 { - midX = midX * (1.0 - abs(progress)) + itemFrames[i - 1].midX * abs(progress) - } else { - midX = midX * (1.0 - abs(progress)) + itemFrames[i].offsetBy(dx: -itemFrames[i].width, dy: 0.0).midX * abs(progress) - } - } else if progress > 0.0 { - if i != itemFrames.count - 1 { - midX = midX * (1.0 - abs(progress)) + itemFrames[i + 1].midX * abs(progress) - } else { - midX = midX * (1.0 - abs(progress)) + itemFrames[i].offsetBy(dx: itemFrames[i].width, dy: 0.0).midX * abs(progress) - } - } - let offset = size.width / 2.0 - midX - for j in 0 ..< itemFrames.count { - itemFrames[j].origin.x += offset - } - break - } + itemFrames[i].origin.x += xOffset } for i in 0 ..< self.itemNodes.count { @@ -208,14 +234,65 @@ final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDelegate { } func scrollViewDidScroll(_ scrollView: UIScrollView) { + guard let currentLayout = self.currentLayout else { + return + } + + if scrollView.isDragging && !self.isPanning { + if let (currentCentralIndex, _) = self.centralIndexAndProgress { + self.centralIndexAndProgress = (currentCentralIndex, nil) + } + self.isPanning = true + + self.updateLayout(size: currentLayout, transition: .animated(duration: 0.4, curve: .spring)) + } + if scrollView.isDragging || scrollView.isDecelerating { + let position = scrollView.contentInset.left + scrollView.contentOffset.x + let index = max(0, min(self.items.count, Int(round(position / (itemBaseSize.width + spacing))))) + + if let (currentCentralIndex, _) = self.centralIndexAndProgress, currentCentralIndex != index { + self.centralIndexAndProgress = (index, nil) + self.itemChanged?(self.items[index].index!) + } + } } func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + guard let currentLayout = self.currentLayout else { + return + } + if let (centralIndex, progress) = self.centralIndexAndProgress { + let contentOffset = contentOffsetToCenterItem(index: centralIndex, progress: progress, contentInset: self.scrollNode.view.contentInset) + + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) + if !decelerate { + self.isPanning = false + self.updateLayout(size: currentLayout, transition: transition) + } + transition.animateView { + self.scrollNode.view.contentOffset = contentOffset + } + } } func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + guard let currentLayout = self.currentLayout, !scrollView.isTracking else { + return + } + if let (centralIndex, progress) = self.centralIndexAndProgress { + let contentOffset = contentOffsetToCenterItem(index: centralIndex, progress: progress, contentInset: self.scrollNode.view.contentInset) + + let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring) + if self.isPanning { + self.isPanning = false + self.updateLayout(size: currentLayout, transition: transition) + } + transition.animateView { + self.scrollNode.view.contentOffset = contentOffset + } + } } } diff --git a/TelegramUI/InstantImageGalleryItem.swift b/TelegramUI/InstantImageGalleryItem.swift index 24b1470dc0..c2ab6b8abe 100644 --- a/TelegramUI/InstantImageGalleryItem.swift +++ b/TelegramUI/InstantImageGalleryItem.swift @@ -8,6 +8,7 @@ import TelegramCore private struct InstantImageGalleryThumbnailItem: GalleryThumbnailItem { let account: Account let mediaReference: AnyMediaReference + let requestForIndex: () -> Int? var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) { if let imageReferene = mediaReference.concrete(TelegramMediaImage.self), let representation = largestImageRepresentation(imageReferene.media.representations) { @@ -26,6 +27,10 @@ private struct InstantImageGalleryThumbnailItem: GalleryThumbnailItem { return false } } + + var index: Int? { + return self.requestForIndex() + } } class InstantImageGalleryItem: GalleryItem { @@ -66,7 +71,13 @@ class InstantImageGalleryItem: GalleryItem { } func thumbnailItem() -> (Int64, GalleryThumbnailItem)? { - return (0, InstantImageGalleryThumbnailItem(account: self.account, mediaReference: imageReference.abstract)) + return (0, InstantImageGalleryThumbnailItem(account: self.account, mediaReference: imageReference.abstract, requestForIndex: { [weak self] in + if let strongSelf = self { + return 0 //return strongSelf..index + } else { + return nil + } + })) } } diff --git a/TelegramUI/ItemListTextWithLabelItem.swift b/TelegramUI/ItemListTextWithLabelItem.swift index 05633b88a2..9d145c7fd2 100644 --- a/TelegramUI/ItemListTextWithLabelItem.swift +++ b/TelegramUI/ItemListTextWithLabelItem.swift @@ -176,7 +176,7 @@ class ItemListTextWithLabelItemNode: ListViewItemNode { if let selected = item.selected { let (selectionWidth, selectionApply) = selectionNodeLayout(item.theme.list.itemCheckColors.strokeColor, item.theme.list.itemCheckColors.fillColor, item.theme.list.itemCheckColors.foregroundColor, selected) selectionNodeWidthAndApply = (selectionWidth, selectionApply) - leftOffset += selectionWidth - 24.0 + leftOffset += selectionWidth - 8.0 } let labelColor: UIColor diff --git a/TelegramUI/PeerAvatarImageGalleryItem.swift b/TelegramUI/PeerAvatarImageGalleryItem.swift index 8f424dd74a..2147daba38 100644 --- a/TelegramUI/PeerAvatarImageGalleryItem.swift +++ b/TelegramUI/PeerAvatarImageGalleryItem.swift @@ -23,6 +23,14 @@ private struct PeerAvatarImageGalleryThumbnailItem: GalleryThumbnailItem { let account: Account let peer: Peer let content: PeerAvatarImageGalleryThumbnailContent + private let requestForIndex: () -> Int? + + init(account: Account, peer: Peer, content: PeerAvatarImageGalleryThumbnailContent, requestForIndex: @escaping () -> Int?) { + self.account = account + self.peer = peer + self.content = content + self.requestForIndex = requestForIndex + } var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) { if let representation = largestImageRepresentation(self.content.representations) { @@ -44,6 +52,10 @@ private struct PeerAvatarImageGalleryThumbnailItem: GalleryThumbnailItem { return false } } + + var index: Int? { + return self.requestForIndex() + } } class PeerAvatarImageGalleryItem: GalleryItem { @@ -98,7 +110,7 @@ class PeerAvatarImageGalleryItem: GalleryItem { content = .standaloneImage(image.representations) } - return (0, PeerAvatarImageGalleryThumbnailItem(account: self.account, peer: self.peer, content: content)) + return (0, PeerAvatarImageGalleryThumbnailItem(account: self.account, peer: self.peer, content: content, requestForIndex: { return 0 })) } } diff --git a/TelegramUI/SecureIdAuthFormFieldNode.swift b/TelegramUI/SecureIdAuthFormFieldNode.swift index f68da9d44c..20254ebee0 100644 --- a/TelegramUI/SecureIdAuthFormFieldNode.swift +++ b/TelegramUI/SecureIdAuthFormFieldNode.swift @@ -246,8 +246,36 @@ private func countryName(code: String, strings: PresentationStrings) -> String { return AuthorizationSequenceCountrySelectionController.lookupCountryNameById(code, strings: strings) ?? "" } +private func stringForDocumentType(_ type: SecureIdRequestedIdentityDocument, strings: PresentationStrings) -> String { + switch type { + case .passport: + return strings.Passport_Identity_TypePassport + case .internalPassport: + return strings.Passport_Identity_TypeInternalPassport + case .idCard: + return strings.Passport_Identity_TypeIdentityCard + case .driversLicense: + return strings.Passport_Identity_TypeDriversLicense + } +} + +private func stringForDocumentType(_ type: SecureIdRequestedAddressDocument, strings: PresentationStrings) -> String { + switch type { + case .rentalAgreement: + return strings.Passport_Address_TypeRentalAgreement + case .bankStatement: + return strings.Passport_Address_TypeBankStatement + case .passportRegistration: + return strings.Passport_Address_TypePassportRegistration + case .temporaryRegistration: + return strings.Passport_Address_TypeTemporaryRegistration + case .utilityBill: + return strings.Passport_Address_TypeUtilityBill + } +} + private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings: PresentationStrings, values: [SecureIdValueWithContext]) -> (String, String) { - let title: String + var title: String let placeholder: String var text: String = "" @@ -257,6 +285,7 @@ private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings: title = strings.Passport_FieldIdentity switch document { case let .just(type): + title = stringForDocumentType(type, strings: strings) break case let .oneOf(types): break @@ -280,6 +309,7 @@ private func fieldTitleAndText(field: SecureIdParsedRequestedFormField, strings: title = strings.Passport_FieldAddress switch document { case let .just(type): + title = stringForDocumentType(type, strings: strings) break case let .oneOf(types): break diff --git a/TelegramUI/ShareController.swift b/TelegramUI/ShareController.swift index 30c3338758..6c55fc271c 100644 --- a/TelegramUI/ShareController.swift +++ b/TelegramUI/ShareController.swift @@ -260,7 +260,8 @@ public final class ShareController: ViewController { switch entry { case let .MessageEntry(_, _, _, _, _, renderedPeer, _): if let peer = renderedPeer.chatMainPeer, peer.id != accountPeer.id { - if canSendMessagesToPeer(peer) { + if let user = peer as? TelegramUser, (user.firstName ?? "").isEmpty, (user.lastName ?? "").isEmpty { + } else if canSendMessagesToPeer(peer) { peers.append(peer) } } diff --git a/TelegramUI/UniversalVideoCalleryItem.swift b/TelegramUI/UniversalVideoCalleryItem.swift index abbcab8237..5a8199fff3 100644 --- a/TelegramUI/UniversalVideoCalleryItem.swift +++ b/TelegramUI/UniversalVideoCalleryItem.swift @@ -73,13 +73,25 @@ class UniversalVideoGalleryItem: GalleryItem { } } if let mediaReference = mediaReference { - if let item = ChatMediaGalleryThumbnailItem(account: self.account, mediaReference: mediaReference) { + if let item = ChatMediaGalleryThumbnailItem(account: self.account, mediaReference: mediaReference, requestForIndex: { [weak self] in + if let strongSelf = self { + return 0 //strongSelf.index + } else { + return nil + } + }) { return (Int64(id), item) } } } } else if case let .webPage(webPage, file) = contentInfo { - if let item = ChatMediaGalleryThumbnailItem(account: self.account, mediaReference: .webPage(webPage: WebpageReference(webPage), media: file)) { + if let item = ChatMediaGalleryThumbnailItem(account: self.account, mediaReference: .webPage(webPage: WebpageReference(webPage), media: file), requestForIndex: { [weak self] in + if let strongSelf = self { + return 0 //strongSelf.index + } else { + return nil + } + }) { return (0, item) } } diff --git a/TelegramUI/YoutubeEmbedImplementation.swift b/TelegramUI/YoutubeEmbedImplementation.swift index 689510fb03..43b75835c8 100644 --- a/TelegramUI/YoutubeEmbedImplementation.swift +++ b/TelegramUI/YoutubeEmbedImplementation.swift @@ -28,7 +28,7 @@ func extractYoutubeVideoIdAndTimestamp(url: String) -> (String, Int)? { if value.contains("s") { var range = value.startIndex.. (String, Int)? { } if let minutesRange = value.range(of: "m", options: .caseInsensitive, range: range, locale: nil) { - let subvalue = String(value[range.lowerBound.. (String, Int)? { } if let secondsRange = value.range(of: "s", options: .caseInsensitive, range: range, locale: nil) { - let subvalue = String(value[range.lowerBound..