diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index d649bac93f..111e8fed80 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -11599,7 +11599,7 @@ Sorry for the inconvenience."; "ChatbotSetup.Recipients.IncludedSectionFooter" = "Select chats or entire chat categories which the bot **WILL** have access to."; "ChatbotSetup.PermissionsSectionHeader" = "BOT PERMISSIONS"; -"ChatbotSetup.PermissionsSectionFooter" = "The bot will be able to view all new incoming messages, but not the messages that had been sent before you added the bot."; +"ChatbotSetup.PermissionsSectionFooter" = "The bot can only reply on your behalf in chats that were active during the last 24h."; "ChatbotSetup.Permission.ReplyToMessages" = "Reply to Messages"; "ChatbotSetup.BotAddAction" = "ADD"; diff --git a/submodules/TelegramCore/Sources/State/ChatHistoryPreloadManager.swift b/submodules/TelegramCore/Sources/State/ChatHistoryPreloadManager.swift index 37e1406e1f..c40d36570a 100644 --- a/submodules/TelegramCore/Sources/State/ChatHistoryPreloadManager.swift +++ b/submodules/TelegramCore/Sources/State/ChatHistoryPreloadManager.swift @@ -376,6 +376,11 @@ final class ChatHistoryPreloadManager { } private func update(indices: [(ChatHistoryPreloadIndex, Bool, Bool)], additionalPeerIds: Set) { + #if DEBUG + var indices = indices + indices.removeAll() + #endif + self.queue.async { var validEntityIds = Set(indices.map { $0.0.entity }) for peerId in additionalPeerIds { @@ -431,7 +436,7 @@ final class ChatHistoryPreloadManager { let key: PostboxViewKey switch index.entity { case let .peer(peerId, threadId): - key = .messageOfInterestHole(location: .peer(peerId: peerId, threadId: threadId), namespace: Namespaces.Message.Cloud, count: 70) + key = .messageOfInterestHole(location: .peer(peerId: peerId, threadId: threadId), namespace: Namespaces.Message.Cloud, count: 50) } view.disposable.set((self.postbox.combinedView(keys: [key]) |> deliverOn(self.queue)).start(next: { [weak self] next in diff --git a/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift b/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift index 1ddfd9175c..4be6ef70f6 100644 --- a/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift +++ b/submodules/TelegramUI/Components/ListMultilineTextFieldItemComponent/Sources/ListMultilineTextFieldItemComponent.swift @@ -45,10 +45,12 @@ public final class ListMultilineTextFieldItemComponent: Component { public let placeholder: String public let autocapitalizationType: UITextAutocapitalizationType public let autocorrectionType: UITextAutocorrectionType + public let returnKeyType: UIReturnKeyType public let characterLimit: Int? public let displayCharacterLimit: Bool public let emptyLineHandling: EmptyLineHandling public let updated: ((String) -> Void)? + public let returnKeyAction: (() -> Void)? public let textUpdateTransition: Transition public let tag: AnyObject? @@ -62,10 +64,12 @@ public final class ListMultilineTextFieldItemComponent: Component { placeholder: String, autocapitalizationType: UITextAutocapitalizationType = .sentences, autocorrectionType: UITextAutocorrectionType = .default, + returnKeyType: UIReturnKeyType = .default, characterLimit: Int? = nil, displayCharacterLimit: Bool = false, emptyLineHandling: EmptyLineHandling = .allowed, updated: ((String) -> Void)?, + returnKeyAction: (() -> Void)? = nil, textUpdateTransition: Transition = .immediate, tag: AnyObject? = nil ) { @@ -78,10 +82,12 @@ public final class ListMultilineTextFieldItemComponent: Component { self.placeholder = placeholder self.autocapitalizationType = autocapitalizationType self.autocorrectionType = autocorrectionType + self.returnKeyType = returnKeyType self.characterLimit = characterLimit self.displayCharacterLimit = displayCharacterLimit self.emptyLineHandling = emptyLineHandling self.updated = updated + self.returnKeyAction = returnKeyAction self.textUpdateTransition = textUpdateTransition self.tag = tag } @@ -114,6 +120,9 @@ public final class ListMultilineTextFieldItemComponent: Component { if lhs.autocorrectionType != rhs.autocorrectionType { return false } + if lhs.returnKeyType != rhs.returnKeyType { + return false + } if lhs.characterLimit != rhs.characterLimit { return false } @@ -196,6 +205,12 @@ public final class ListMultilineTextFieldItemComponent: Component { return false } + public func activateInput() { + if let textFieldView = self.textField.view as? TextFieldComponent.View { + textFieldView.activateInput() + } + } + func update(component: ListMultilineTextFieldItemComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.isUpdating = true defer { @@ -260,11 +275,18 @@ public final class ListMultilineTextFieldItemComponent: Component { characterLimit: component.characterLimit, emptyLineHandling: mappedEmptyLineHandling, formatMenuAvailability: .none, + returnKeyType: component.returnKeyType, lockedFormatAction: { }, present: { _ in }, paste: { _ in + }, + returnKeyAction: { [weak self] in + guard let self, let component = self.component else { + return + } + component.returnKeyAction?() } )), environment: {}, diff --git a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift index 578ce79289..5b0588b08f 100644 --- a/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift +++ b/submodules/TelegramUI/Components/Settings/BusinessIntroSetupScreen/Sources/BusinessIntroSetupScreen.swift @@ -77,6 +77,7 @@ final class BusinessIntroSetupScreenComponent: Component { private let introSection = ComponentView() private let deleteSection = ComponentView() + private var ignoreScrolling: Bool = false private var isUpdating: Bool = false private var component: BusinessIntroSetupScreenComponent? @@ -161,7 +162,9 @@ final class BusinessIntroSetupScreenComponent: Component { } func scrollViewDidScroll(_ scrollView: UIScrollView) { - self.updateScrolling(transition: .immediate) + if !self.ignoreScrolling { + self.updateScrolling(transition: .immediate) + } } private var scrolledUp = true @@ -765,11 +768,21 @@ final class BusinessIntroSetupScreenComponent: Component { placeholder: "Enter Title", autocapitalizationType: .none, autocorrectionType: .no, + returnKeyType: .next, characterLimit: 32, displayCharacterLimit: true, emptyLineHandling: .notAllowed, updated: { _ in }, + returnKeyAction: { [weak self] in + guard let self else { + return + } + + if let titleView = self.introSection.findTaggedView(tag: self.textInputTag) as? ListMultilineTextFieldItemComponent.View { + titleView.activateInput() + } + }, textUpdateTransition: .spring(duration: 0.4), tag: self.titleInputTag )))) @@ -786,11 +799,20 @@ final class BusinessIntroSetupScreenComponent: Component { placeholder: "Enter Message", autocapitalizationType: .none, autocorrectionType: .no, + returnKeyType: .done, characterLimit: 70, displayCharacterLimit: true, emptyLineHandling: .notAllowed, updated: { _ in }, + returnKeyAction: { [weak self] in + guard let self else { + return + } + if let titleView = self.introSection.findTaggedView(tag: self.textInputTag) as? ListMultilineTextFieldItemComponent.View { + titleView.endEditing(true) + } + }, textUpdateTransition: .spring(duration: 0.4), tag: self.textInputTag )))) @@ -1083,6 +1105,7 @@ final class BusinessIntroSetupScreenComponent: Component { let previousBounds = self.scrollView.bounds + self.ignoreScrolling = true let contentSize = CGSize(width: availableSize.width, height: contentHeight) if self.scrollView.frame != CGRect(origin: CGPoint(), size: availableSize) { self.scrollView.frame = CGRect(origin: CGPoint(), size: availableSize) @@ -1123,6 +1146,7 @@ final class BusinessIntroSetupScreenComponent: Component { } self.topOverscrollLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: -3000.0), size: CGSize(width: availableSize.width, height: 3000.0)) + self.ignoreScrolling = false self.updateScrolling(transition: transition) diff --git a/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift b/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift index 861cb25723..b63817fc1a 100644 --- a/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift +++ b/submodules/TelegramUI/Components/TextFieldComponent/Sources/TextFieldComponent.swift @@ -109,9 +109,11 @@ public final class TextFieldComponent: Component { public let characterLimit: Int? public let emptyLineHandling: EmptyLineHandling public let formatMenuAvailability: FormatMenuAvailability + public let returnKeyType: UIReturnKeyType public let lockedFormatAction: () -> Void public let present: (ViewController) -> Void public let paste: (PasteData) -> Void + public let returnKeyAction: (() -> Void)? public init( context: AccountContext, @@ -128,9 +130,11 @@ public final class TextFieldComponent: Component { characterLimit: Int? = nil, emptyLineHandling: EmptyLineHandling = .allowed, formatMenuAvailability: FormatMenuAvailability, + returnKeyType: UIReturnKeyType = .default, lockedFormatAction: @escaping () -> Void, present: @escaping (ViewController) -> Void, - paste: @escaping (PasteData) -> Void + paste: @escaping (PasteData) -> Void, + returnKeyAction: (() -> Void)? = nil ) { self.context = context self.theme = theme @@ -146,9 +150,11 @@ public final class TextFieldComponent: Component { self.characterLimit = characterLimit self.emptyLineHandling = emptyLineHandling self.formatMenuAvailability = formatMenuAvailability + self.returnKeyType = returnKeyType self.lockedFormatAction = lockedFormatAction self.present = present self.paste = paste + self.returnKeyAction = returnKeyAction } public static func ==(lhs: TextFieldComponent, rhs: TextFieldComponent) -> Bool { @@ -194,6 +200,9 @@ public final class TextFieldComponent: Component { if lhs.formatMenuAvailability != rhs.formatMenuAvailability { return false } + if lhs.returnKeyType != rhs.returnKeyType { + return false + } return true } @@ -408,6 +417,13 @@ public final class TextFieldComponent: Component { } public func chatInputTextNodeShouldReturn() -> Bool { + guard let component = self.component else { + return true + } + if let returnKeyAction = component.returnKeyAction { + returnKeyAction() + return false + } return true } @@ -565,6 +581,7 @@ public final class TextFieldComponent: Component { guard let component = self.component else { return true } + if let characterLimit = component.characterLimit { let string = self.inputState.inputText.string as NSString let updatedString = string.replacingCharacters(in: range, with: text) @@ -582,6 +599,11 @@ public final class TextFieldComponent: Component { return false } case .notAllowed: + if (range.length == 0 && text == "\n"), let returnKeyAction = component.returnKeyAction { + returnKeyAction() + return false + } + let string = self.inputState.inputText.string as NSString let updatedString = string.replacingCharacters(in: range, with: text) if updatedString.range(of: "\n") != nil { @@ -1081,6 +1103,10 @@ public final class TextFieldComponent: Component { } } + if self.textView.returnKeyType != component.returnKeyType { + self.textView.returnKeyType = component.returnKeyType + } + if let initialText = component.externalState.initialText { component.externalState.initialText = nil self.updateInputState { _ in