From 1cda5ccf908471b37624fe3ab32ab4a5d46e9be6 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 2 Apr 2022 13:45:41 +0400 Subject: [PATCH] Web app improvements --- .../Sources/AttachmentPanel.swift | 46 ++++++++-------- .../Sources/MediaPickerSelectedListNode.swift | 6 +++ .../Sources/ChannelAdminController.swift | 2 +- .../PendingMessages/EnqueueMessage.swift | 2 + .../TelegramUI/Sources/ChatController.swift | 52 ++++++++++--------- .../WebUI/Sources/WebAppController.swift | 11 ++-- 6 files changed, 70 insertions(+), 49 deletions(-) diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index e7e26f7870..d5129fd715 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -15,8 +15,9 @@ import ChatTextLinkEditUI import PhotoResources private let buttonSize = CGSize(width: 88.0, height: 49.0) +private let smallButtonWidth: CGFloat = 69.0 private let iconSize = CGSize(width: 30.0, height: 30.0) -private let sideInset: CGFloat = 0.0 +private let sideInset: CGFloat = 3.0 private final class IconComponent: Component { public let account: Account @@ -546,19 +547,20 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { let visibleRect = self.scrollNode.bounds.insetBy(dx: -180.0, dy: 0.0) var validButtons = Set() - let distanceBetweenNodes = layout.size.width / CGFloat(self.buttons.count) + var distanceBetweenNodes = layout.size.width / CGFloat(self.buttons.count) let internalWidth = distanceBetweenNodes * CGFloat(self.buttons.count - 1) - let leftNodeOriginX = (layout.size.width - internalWidth) / 2.0 - -// var sideInset = sideInset -// let buttonsWidth = sideInset * 2.0 + buttonSize.width * CGFloat(self.buttons.count) -// if buttonsWidth < layout.size.width { -// sideInset = floorToScreenPixels((layout.size.width - buttonsWidth) / 2.0) -// } -// + var leftNodeOriginX = (layout.size.width - internalWidth) / 2.0 + + var buttonWidth = buttonSize.width + if self.buttons.count > 6 { + buttonWidth = smallButtonWidth + distanceBetweenNodes = buttonWidth + leftNodeOriginX = sideInset + buttonWidth / 2.0 + } + for i in 0 ..< self.buttons.count { - let originX = floor(leftNodeOriginX + CGFloat(i) * distanceBetweenNodes - buttonSize.width / 2.0) - let buttonFrame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: buttonSize) + let originX = floor(leftNodeOriginX + CGFloat(i) * distanceBetweenNodes - buttonWidth / 2.0) + let buttonFrame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: CGSize(width: buttonWidth, height: buttonSize.height)) if !visibleRect.intersects(buttonFrame) { continue } @@ -589,12 +591,16 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { if strongSelf.selectionChanged(type) { strongSelf.selectedIndex = i strongSelf.updateViews(transition: .init(animation: .curve(duration: 0.2, curve: .spring))) + + if strongSelf.buttons.count > 6, let button = strongSelf.buttonViews[i] { + strongSelf.scrollNode.view.scrollRectToVisible(button.frame.insetBy(dx: -35.0, dy: 0.0), animated: true) + } } } }) ), environment: {}, - containerSize: buttonSize + containerSize: CGSize(width: buttonWidth, height: buttonSize.height) ) buttonTransition.setFrame(view: buttonView, frame: buttonFrame) } @@ -608,14 +614,12 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { return false } -// var sideInset = sideInset -// let buttonsWidth = sideInset * 2.0 + buttonSize.width * CGFloat(self.buttons.count) -// if buttonsWidth < layout.size.width { -// sideInset = floorToScreenPixels((layout.size.width - buttonsWidth) / 2.0) -// } - - let contentSize = CGSize(width: layout.size.width, height: buttonSize.height) -// CGSize(width: sideInset * 2.0 + CGFloat(self.buttons.count) * buttonSize.width, height: buttonSize.height) + var contentSize = CGSize(width: layout.size.width, height: buttonSize.height) + var buttonWidth = buttonSize.width + if self.buttons.count > 6 { + buttonWidth = smallButtonWidth + contentSize = CGSize(width: sideInset * 2.0 + CGFloat(self.buttons.count) * buttonWidth, height: buttonSize.height) + } self.scrollLayout = (layout.size.width, contentSize) transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.isSelecting ? -buttonSize.height : 0.0), size: CGSize(width: layout.size.width, height: buttonSize.height))) diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index 8bcf19e5f0..5d1de9b2ca 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -506,6 +506,10 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI backgroundNode.layer.removeAllAnimations() } + for (_, itemNode) in strongSelf.itemNodes { + itemNode.layer.removeAllAnimations() + } + strongSelf.messageNodes?.first?.layer.removeAllAnimations() strongSelf.messageNodes?.last?.layer.removeAllAnimations() @@ -523,6 +527,8 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI for (identifier, itemNode) in self.itemNodes { if let (transitionView, completion) = self.getTransitionView(identifier) { itemNode.animateTo(transitionView, completion: completion) + } else { + itemNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false) } } diff --git a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift index 66ab46af3d..cbcb77fbb1 100644 --- a/submodules/PeerInfoUI/Sources/ChannelAdminController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelAdminController.swift @@ -618,7 +618,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s } } } else { - if let adminPeer = adminView.peers[adminView.peerId] as? TelegramUser, adminPeer.botInfo != nil, case .group = channel.info, invite { + if let adminPeer = adminView.peers[adminView.peerId] as? TelegramUser, adminPeer.botInfo != nil, case .group = channel.info, invite, let channelPeer = channelView.peers[channelView.peerId], canEditAdminRights(accountPeerId: accountPeerId, channelPeer: channelPeer, initialParticipant: initialParticipant) { entries.append(.adminRights(presentationData.theme, presentationData.strings.Bot_AddToChat_Add_AdminRights, state.adminRights)) } diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index 690481f8b7..cddf7c165b 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -146,6 +146,8 @@ private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAt return true case _ as SendAsMessageAttribute: return true + case _ as ReplyMessageAttribute: + return true default: return false } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 8dc6162a2e..dae1c75c39 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1658,9 +1658,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - if let botPeer = botPeer, botPeer.flags.contains(.isVerified) { - openBot() - } else if let botPeer = botPeer { + if let botPeer = botPeer { let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: botPeer.id) |> deliverOnMainQueue).start(next: { value in guard let strongSelf = self else { @@ -3383,7 +3381,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self else { return } - let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal) + let controller = standaloneWebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, completion: { [weak self] in + self?.chatDisplayNode.historyNode.scrollToEndOfHistory() + }) strongSelf.present(controller, in: .window(.root)) // let controller = WebAppController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: peerId, botId: peerId, botName: botName, url: result.url, queryId: result.queryId, buttonText: buttonText, keepAliveSignal: result.keepAliveSignal, replyToMessageId: nil, iconFile: nil) // controller.getNavigationController = { [weak self] in @@ -3400,27 +3400,23 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - if peer.flags.contains(.isVerified) { - openWebView() - } else { - let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id) - |> deliverOnMainQueue).start(next: { value in - guard let strongSelf = self else { - return - } + let _ = (ApplicationSpecificNotice.getBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id) + |> deliverOnMainQueue).start(next: { value in + guard let strongSelf = self else { + return + } - if value { - openWebView() - } else { - strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertTitle, text: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertText(botName).string, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { - if let strongSelf = self { - let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id).start() - openWebView() - } - })], parseMarkdown: true), in: .window(.root), with: nil) - } - }) - } + if value { + openWebView() + } else { + strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertTitle, text: strongSelf.presentationData.strings.WebApp_OpenWebViewAlertText(botName).string, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { }), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { + if let strongSelf = self { + let _ = ApplicationSpecificNotice.setBotGameNotice(accountManager: strongSelf.context.sharedContext.accountManager, peerId: peer.id).start() + openWebView() + } + })], parseMarkdown: true), in: .window(.root), with: nil) + } + }) }, requestMessageUpdate: { [weak self] id in if let strongSelf = self { strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id) @@ -10895,6 +10891,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G controller.getNavigationController = { [weak self] in return self?.effectiveNavigationController } + controller.completion = { [weak self] in + if let strongSelf = self { + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { + $0.updatedInterfaceState { $0.withUpdatedReplyMessageId(nil) } + }) + strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory() + } + } completion(controller, nil) strongSelf.controllerNavigationDisposable.set(nil) default: diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 4e6a4b14be..7c6050ec48 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -266,6 +266,7 @@ public final class WebAppController: ViewController, AttachmentContainable { } }, completed: { [weak self] in if let strongSelf = self { + strongSelf.controller?.completion() strongSelf.controller?.dismiss() } }) @@ -483,6 +484,8 @@ public final class WebAppController: ViewController, AttachmentContainable { private var presentationDataDisposable: Disposable? public var getNavigationController: () -> NavigationController? = { return nil } + + public var completion: () -> Void = {} public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, botId: PeerId, botName: String, url: String?, queryId: Int64?, buttonText: String?, keepAliveSignal: Signal?, replyToMessageId: MessageId?, iconFile: TelegramMediaFile?) { self.context = context @@ -653,10 +656,12 @@ private final class WebAppContextReferenceContentSource: ContextReferenceContent } } -public func standaloneWebAppController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, botId: PeerId, botName: String, url: String, queryId: Int64?, buttonText: String?, keepAliveSignal: Signal?) -> ViewController { +public func standaloneWebAppController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: PeerId, botId: PeerId, botName: String, url: String, queryId: Int64?, buttonText: String?, keepAliveSignal: Signal?, completion: @escaping () -> Void = {}) -> ViewController { let controller = AttachmentController(context: context, updatedPresentationData: updatedPresentationData, chatLocation: .peer(id: peerId), buttons: [.standalone], initialButton: .standalone) - controller.requestController = { _, completion in - completion(WebAppController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, botId: botId, botName: botName, url: url, queryId: queryId, buttonText: buttonText, keepAliveSignal: keepAliveSignal, replyToMessageId: nil, iconFile: nil), nil) + controller.requestController = { _, present in + let webAppController = WebAppController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, botId: botId, botName: botName, url: url, queryId: queryId, buttonText: buttonText, keepAliveSignal: keepAliveSignal, replyToMessageId: nil, iconFile: nil) + webAppController.completion = completion + present(webAppController, nil) } return controller }