diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 41502d52e8..b7e3a23bc7 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -16176,6 +16176,7 @@ Error: %8$@"; "CreatePoll.OptionsNeededOne" = "Add at least one option"; "CreatePoll.QuizCorrectOptionNeeded" = "Select a correct option"; "CreatePoll.QuizCorrectOptionNeededMultiple" = "Select at least one correct option"; +"CreatePoll.QuizCountryNeeded" = "Select at least one country"; "Stars.Intro.Transaction.Commission.Title" = "%@ commission"; @@ -16192,7 +16193,7 @@ Error: %8$@"; "CreatePoll.AllowedCountries.Countries_1" = "%@ country"; "CreatePoll.AllowedCountries.Countries_any" = "%@ countries"; -"Chat.Poll.Restriction.Subscribers" = "Only subscribers of **%@** can vote"; +"Chat.Poll.Restriction.Subscribers" = "Only subscribers of **%@** can vote."; "Chat.Poll.Restriction.Subscribers.TimeLimit" = "Only subscribers who joined more than **24 hours** ago can vote."; "Chat.Poll.Restriction.Country" = "Only users from %@ can vote."; "Chat.Poll.Restriction.SubscribersCountry" = "Only subscribers of **%@** from %@ can vote."; @@ -16232,3 +16233,26 @@ Error: %8$@"; "Login.Fee.GetPremiumForDays" = "Get Telegram Premium for %@"; "Login.Fee.GetPremiumForDays.Days_1" = "%@ day"; "Login.Fee.GetPremiumForDays.Days_any" = "%@ days"; + +"PeerInfo.DeleteReaction" = "Delete Reaction"; +"Chat.DeleteReactionInfo" = "Tap and hold to delete reaction."; + +"Chat.AdminActionSheet.DeleteReactionTitle" = "Delete 1 Reaction"; +"Chat.AdminActionSheet.DeleteAllMessages" = "Delete All Messages"; +"Chat.AdminActionSheet.DeleteAllReactions" = "Delete All Reactions"; + +"Conversation.CalendarSearch.Title" = "Search"; +"Conversation.CalendarSearch.Done" = "Done"; + +"ScheduleMessage.SilentPosting.YouEnabled" = "You will receive a silent notification"; +"ScheduleMessage.SilentPosting.YouDisabled" = "You will be notified"; +"ScheduleMessage.SilentPosting.UserEnabled" = "%@ will receive a silent notification"; +"ScheduleMessage.SilentPosting.UserDisabled" = "%@ will be notified"; +"ScheduleMessage.SilentPosting.GroupEnabled" = "Members will receive a silent notification"; +"ScheduleMessage.SilentPosting.GroupDisabled" = "Members will be notified"; +"ScheduleMessage.SilentPosting.ChannelEnabled" = "Subscribers will receive a silent notification"; +"ScheduleMessage.SilentPosting.ChannelDisabled" = "Subscribers will be notified"; + +"Settings.ChatAutomation" = "Chat Automation"; +"Settings.ChatAutomationInfo" = "Add a bot to reply to messages on your behalf."; +"Settings.ChatAutomationOff" = "Off"; diff --git a/submodules/BrowserUI/Sources/BrowserMarkdown.swift b/submodules/BrowserUI/Sources/BrowserMarkdown.swift index 6ef7a0eea5..c3723b4075 100644 --- a/submodules/BrowserUI/Sources/BrowserMarkdown.swift +++ b/submodules/BrowserUI/Sources/BrowserMarkdown.swift @@ -20,6 +20,7 @@ private let markdownInlineHTMLInlineIntent = InlinePresentationIntent(rawValue: private let markdownDefaultBlockImageDimensions = PixelDimensions(width: 1200, height: 900) private let markdownDefaultInlineImageDimensions = PixelDimensions(width: 18, height: 18) +private let markdownImageParsingEnabled = false private let markdownTaskListUncheckedNumber = "\u{001f}tg-md-task:unchecked" private let markdownTaskListCheckedNumber = "\u{001f}tg-md-task:checked" private let markdownRawHTMLTagRegex = try! NSRegularExpression(pattern: #"]*?>"#) @@ -353,6 +354,9 @@ private final class MarkdownConversionContext { } func resolveImage(attributes: [NSAttributedString.Key: Any]) -> MarkdownResolvedImage? { + guard markdownImageParsingEnabled else { + return nil + } guard let imageUrl = markdownImageURL(attributes: attributes) else { return nil } @@ -1166,10 +1170,8 @@ private func markdownBlocks(from node: MarkdownIntentNode, context: MarkdownConv switch level { case Int.min ... 1: return [.title(text)] - case 2: - return [.header(text)] default: - return [.heading(text: text, level: Int32(max(3, min(level, 6))))] + return [.heading(text: text, level: Int32(max(2, min(level, 6))))] } case .paragraph: guard let inlineContent = markdownInlineContent(from: node.attributedText, context: context) else { diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 313f684120..c9c94d3288 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -7389,3 +7389,25 @@ private final class AdsInfoContextReferenceContentSource: ContextReferenceConten return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds.inset(by: self.insets), insets: self.contentInsets) } } + +public struct ChatListNavigationTarget { + public let chatListController: ChatListControllerImpl + public let popToController: ViewController? +} + +public func resolveChatListNavigationTarget(navigationController: NavigationController, excluding excludedController: ViewController? = nil) -> ChatListNavigationTarget? { + for case let controller as ViewController in navigationController.viewControllers.reversed() { + if let excludedController, controller === excludedController { + continue + } + if let chatListController = controller as? ChatListControllerImpl, !chatListController.previewing { + return ChatListNavigationTarget(chatListController: chatListController, popToController: controller) + } + } + + if let controller = navigationController.viewControllers.first as? TabBarController, let chatListController = controller.currentController as? ChatListControllerImpl { + return ChatListNavigationTarget(chatListController: chatListController, popToController: nil) + } + + return nil +} diff --git a/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift b/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift index 4229f74605..87e357334b 100644 --- a/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift +++ b/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift @@ -92,5 +92,18 @@ public func chatTextLinkEditController( dismissImpl = { [weak alertController] in alertController?.dismiss(completion: nil) } + + if link == nil { + Queue.mainQueue().after(0.1, { + let pasteboard = UIPasteboard.general + if pasteboard.hasURLs { + if inputState.value.string.isEmpty, let url = pasteboard.url?.absoluteString, !url.isEmpty { + let value = NSAttributedString(string: url) + inputState.setValue(value, selectionRange: 0 ..< value.length) + } + } + }) + } + return alertController } diff --git a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsSheet.swift b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsSheet.swift index b8bfed14be..2f7a4dc717 100644 --- a/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsSheet.swift +++ b/submodules/TelegramUI/Components/AdminUserActionsSheet/Sources/AdminUserActionsSheet.swift @@ -302,9 +302,8 @@ private func adminUserActionsTitle( } else { return strings.Chat_AdminActionSheet_DeleteTitle(Int32(messageCount)) } - case .chatReaction(_): - //TODO:localize - return "Delete 1 Reaction" + case .chatReaction: + return strings.Chat_AdminActionSheet_DeleteReactionTitle } } @@ -535,14 +534,13 @@ private final class AdminUserActionsContentComponent: Component { )))) } } else { - //TODO:localize subItems.append( AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent( theme: component.theme, style: .glass, title: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( - string: "Delete all Messages", + string: component.strings.Chat_AdminActionSheet_DeleteAllMessages, font: Font.regular(component.presentationData.listsFontSize.baseDisplaySize), textColor: component.theme.list.itemPrimaryTextColor )), @@ -568,7 +566,7 @@ private final class AdminUserActionsContentComponent: Component { style: .glass, title: AnyComponent(MultilineTextComponent( text: .plain(NSAttributedString( - string: "Delete all Reactions", + string: component.strings.Chat_AdminActionSheet_DeleteAllReactions, font: Font.regular(component.presentationData.listsFontSize.baseDisplaySize), textColor: component.theme.list.itemPrimaryTextColor )), diff --git a/submodules/TelegramUI/Components/AlertComponent/AlertMultilineInputFieldComponent/Sources/AlertMultilineInputFieldComponent.swift b/submodules/TelegramUI/Components/AlertComponent/AlertMultilineInputFieldComponent/Sources/AlertMultilineInputFieldComponent.swift index 49f9b1e7d7..1d484546b6 100644 --- a/submodules/TelegramUI/Components/AlertComponent/AlertMultilineInputFieldComponent/Sources/AlertMultilineInputFieldComponent.swift +++ b/submodules/TelegramUI/Components/AlertComponent/AlertMultilineInputFieldComponent/Sources/AlertMultilineInputFieldComponent.swift @@ -19,6 +19,7 @@ public final class AlertMultilineInputFieldComponent: Component { public fileprivate(set) var value: NSAttributedString = NSAttributedString() public fileprivate(set) var animateError: () -> Void = {} public fileprivate(set) var activateInput: () -> Void = {} + fileprivate var setValueImpl: ((NSAttributedString, Range) -> Void)? fileprivate let valuePromise = ValuePromise(NSAttributedString()) public var valueSignal: Signal { return self.valuePromise.get() @@ -32,6 +33,13 @@ public final class AlertMultilineInputFieldComponent: Component { public init() { } + + public func setValue(_ value: NSAttributedString, selectionRange: Range? = nil) { + let selectionRange = selectionRange ?? (value.length ..< value.length) + self.value = value + self.valuePromise.set(value) + self.setValueImpl?(value, selectionRange) + } } public enum FormatMenuAvailability: Equatable { @@ -226,13 +234,18 @@ public final class AlertMultilineInputFieldComponent: Component { func update(component: AlertMultilineInputFieldComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: ComponentTransition) -> CGSize { var resetText: NSAttributedString? if self.component == nil { - resetText = component.initialValue + resetText = component.initialValue ?? (component.externalState.value.length == 0 ? nil : component.externalState.value) component.externalState.animateError = { [weak self] in self?.animateError() } component.externalState.activateInput = { [weak self] in self?.activateInput() } + component.externalState.setValueImpl = { [weak self] value, selectionRange in + if let textFieldView = self?.textField.view as? TextFieldComponent.View { + textFieldView.updateText(value, selectionRange: selectionRange) + } + } } let isFirstTime = self.component == nil diff --git a/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift index d7cd526a60..6e87fb27b6 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessagePollBubbleContentNode/Sources/ChatMessagePollBubbleContentNode.swift @@ -2918,31 +2918,42 @@ public class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { if case .public = poll.publicity { item.controllerInteraction.openMessagePollResults(item.message.id, option.opaqueIdentifier) } else if isRestricted { - let locale = localeWithStrings(item.presentationData.strings) - let countryNames = poll.countries.map { id in - if let countryName = locale.localizedString(forRegionCode: id) { - return countryName - } else { - return id - } - } - var countries: String = "" - if countryNames.count == 1, let country = countryNames.first { - countries = "**\(country)**" - } else { - for i in 0 ..< countryNames.count { - countries.append("**\(countryNames[i])**") - if i == countryNames.count - 2 { - countries.append(item.presentationData.strings.Chat_Poll_Restriction_Country_CountriesLastDelimiter) - } else if i < countryNames.count - 2 { - countries.append(item.presentationData.strings.Chat_Poll_Restriction_Country_CountriesDelimiter) + let text: String + + let peerName = item.message.peers[item.message.id.peerId].flatMap(EnginePeer.init)?.compactDisplayTitle ?? "" + if !poll.countries.isEmpty { + let locale = localeWithStrings(item.presentationData.strings) + let countryNames = poll.countries.map { id in + if let countryName = locale.localizedString(forRegionCode: id) { + return countryName + } else { + return id } } + var countries: String = "" + if countryNames.count == 1, let country = countryNames.first { + countries = "**\(country)**" + } else { + for i in 0 ..< countryNames.count { + countries.append("**\(countryNames[i])**") + if i == countryNames.count - 2 { + countries.append(item.presentationData.strings.Chat_Poll_Restriction_Country_CountriesLastDelimiter) + } else if i < countryNames.count - 2 { + countries.append(item.presentationData.strings.Chat_Poll_Restriction_Country_CountriesDelimiter) + } + } + } + if poll.restrictToSubscribers { + text = item.presentationData.strings.Chat_Poll_Restriction_SubscribersCountry(peerName, countries).string + } else { + text = item.presentationData.strings.Chat_Poll_Restriction_Country(countries).string + } + } else { + text = item.presentationData.strings.Chat_Poll_Restriction_Subscribers(peerName).string } - //TODO:localize let controller = UndoOverlayController( presentationData: item.context.sharedContext.currentPresentationData.with { $0 }, - content: .banned(text: "Only users from \(countries) can vote."), + content: .banned(text: text), elevatedLayout: true, position: .bottom, action: { _ in return true } diff --git a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift index d36aec58d2..58ec1e213a 100644 --- a/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift +++ b/submodules/TelegramUI/Components/ChatScheduleTimeController/Sources/ChatScheduleTimeScreen.swift @@ -174,42 +174,39 @@ private final class ChatScheduleTimeSheetContentComponent: Component { let isSilentPosting = self.isSilentPosting let _ = (component.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) |> deliverOnMainQueue).start(next: { [weak self] peer in - guard let self, let peer, let controller = self.environment?.controller() else { + guard let self, let peer, let environment = self.environment, let controller = self.environment?.controller() else { return } - var isChannel = false if case let .channel(channel) = peer, case .broadcast = channel.info { isChannel = true } - - //TODO:localize let text: String if case let .user(user) = peer { if user.id == component.context.account.peerId { if isSilentPosting { - text = "You will receive a silent notification" + text = environment.strings.ScheduleMessage_SilentPosting_YouEnabled } else { - text = "You will be notified" + text = environment.strings.ScheduleMessage_SilentPosting_YouDisabled } } else { if isSilentPosting { - text = "\(peer.compactDisplayTitle) will receive a silent notification" + text = environment.strings.ScheduleMessage_SilentPosting_UserEnabled(peer.compactDisplayTitle).string } else { - text = "\(peer.compactDisplayTitle) will be notified" + text = environment.strings.ScheduleMessage_SilentPosting_UserDisabled(peer.compactDisplayTitle).string } } } else if isChannel { if isSilentPosting { - text = "Subscribers will receive a silent notification" + text = environment.strings.ScheduleMessage_SilentPosting_ChannelEnabled } else { - text = "Subscribers will be notified" + text = environment.strings.ScheduleMessage_SilentPosting_ChannelDisabled } } else { if isSilentPosting { - text = "Members will receive a silent notification" + text = environment.strings.ScheduleMessage_SilentPosting_GroupEnabled } else { - text = "Members will be notified" + text = environment.strings.ScheduleMessage_SilentPosting_GroupDisabled } } @@ -272,8 +269,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { case .poll: title = strings.CreatePoll_Deadline_Title case .search: - //TODO:localize - title = "Search" + title = strings.Conversation_CalendarSearch_Title } let titleSize = self.title.update( transition: transition, @@ -554,8 +550,7 @@ private final class ChatScheduleTimeSheetContentComponent: Component { case .poll: buttonTitle = strings.CreatePoll_Deadline_SetDeadline case .search: - //TODO:localize - buttonTitle = "Done" + buttonTitle = strings.Conversation_CalendarSearch_Done } let buttonSideInset: CGFloat = 30.0 diff --git a/submodules/TelegramUI/Components/ComposePollScreen/Sources/ComposePollScreen.swift b/submodules/TelegramUI/Components/ComposePollScreen/Sources/ComposePollScreen.swift index 42855d33c5..d365dfc98a 100644 --- a/submodules/TelegramUI/Components/ComposePollScreen/Sources/ComposePollScreen.swift +++ b/submodules/TelegramUI/Components/ComposePollScreen/Sources/ComposePollScreen.swift @@ -3099,9 +3099,8 @@ public class ComposePollScreen: ViewControllerComponentContainer, AttachmentCont text = presentationData.strings.CreatePoll_QuizCorrectOptionNeeded } case .countriesNeeded: - //TODO:localize title = nil - text = "Select at least one country" + text = presentationData.strings.CreatePoll_QuizCountryNeeded } let controller = UndoOverlayController( diff --git a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift index 09b4cb1251..40aa79c5bf 100644 --- a/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift +++ b/submodules/TelegramUI/Components/ContextControllerImpl/Sources/ContextActionsContainerNode.swift @@ -426,8 +426,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { icon = UIImage(bundleImageName: "Chat/Context Menu/Tip") case .deleteReaction: self.action = nil - //TODO:localize - self.text = "Tap and hold to delete reaction." + self.text = self.presentationData.strings.Chat_DeleteReactionInfo self.targetSelectionIndex = nil icon = nil isUserInteractionEnabled = false diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift index 799802ed35..be77e08247 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoProfileItems.swift @@ -378,8 +378,7 @@ func infoItems( if let reactionSourceMessageId = reactionSourceMessageId { if canDeleteReaction { - //TODO:localize - items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: ItemDeleteReaction, text: "Delete Reaction", color: .destructive, action: { + items[currentPeerInfoSection]!.append(PeerInfoScreenActionItem(id: ItemDeleteReaction, text: presentationData.strings.PeerInfo_DeleteReaction, color: .destructive, action: { interaction.openDeleteReaction(reactionSourceMessageId) })) } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index d388044837..2e441623ba 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -4592,20 +4592,20 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro guard let controller = self.controller, let navigationController = controller.navigationController as? NavigationController else { return } - guard let tabController = navigationController.viewControllers.first as? TabBarController else { + guard let navigationTarget = resolveChatListNavigationTarget(navigationController: navigationController, excluding: controller) else { return } - for childController in tabController.controllers { - if let chatListController = childController as? ChatListController { - chatListController.maybeAskForPeerChatRemoval(peer: EngineRenderedPeer(peer: peer), joined: false, deleteGloballyIfPossible: globally, completion: { [weak navigationController] deleted in - if deleted { - navigationController?.popToRoot(animated: true) - } - }, removed: { - }) - break + navigationTarget.chatListController.maybeAskForPeerChatRemoval(peer: EngineRenderedPeer(peer: peer), joined: false, deleteGloballyIfPossible: globally, completion: { [weak navigationController] deleted in + guard deleted, let navigationController = navigationController else { + return } - } + if let popToController = navigationTarget.popToController { + let _ = navigationController.popToViewController(popToController, animated: true) + } else { + navigationController.popToRoot(animated: true) + } + }, removed: { + }) } func deleteProfilePhoto(_ item: PeerInfoAvatarListItem) { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift index 3bc0da8950..32aa2f6619 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoSettingsItems.swift @@ -496,18 +496,17 @@ func settingsEditingItems(data: PeerInfoScreenData?, state: PeerInfoState, conte } } - //TODO:localize let automationBotTitle: String if let botPeer = data.businessConnectedBot { let _ = botPeer automationBotTitle = "@\(botPeer.compactDisplayTitle)" } else { - automationBotTitle = "Off" + automationBotTitle = presentationData.strings.Settings_ChatAutomationOff } - items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerChatAutomation, label: .text(automationBotTitle), additionalBadgeLabel: nil, text: "Chat Automation", icon: PresentationResourcesSettings.aiTools, action: { + items[.info]!.append(PeerInfoScreenDisclosureItem(id: ItemPeerChatAutomation, label: .text(automationBotTitle), additionalBadgeLabel: nil, text: presentationData.strings.Settings_ChatAutomation, icon: PresentationResourcesSettings.aiTools, action: { interaction.editingOpenBusinessChatBots() })) - items[.info]!.append(PeerInfoScreenCommentItem(id: ItemPeerChatAutomationHelp, text: "Add a bot to reply to messages on your behalf.")) + items[.info]!.append(PeerInfoScreenCommentItem(id: ItemPeerChatAutomationHelp, text: presentationData.strings.Settings_ChatAutomationInfo)) items[.account]!.append(PeerInfoScreenActionItem(id: ItemAddAccount, text: presentationData.strings.Settings_AddAnotherAccount, alignment: .center, action: { interaction.openSettings(.addAccount) diff --git a/submodules/TelegramUI/Components/Settings/QuickReplyNameAlertController/Sources/QuickReplyNameAlertController.swift b/submodules/TelegramUI/Components/Settings/QuickReplyNameAlertController/Sources/QuickReplyNameAlertController.swift index f44510235a..466a1b8bd8 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReplyNameAlertController/Sources/QuickReplyNameAlertController.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReplyNameAlertController/Sources/QuickReplyNameAlertController.swift @@ -49,7 +49,7 @@ public func quickReplyNameAlertController(context: AccountContext, updatedPresen component: AnyComponent( AlertInputFieldComponent( context: context, - initialValue: nil, + initialValue: value, placeholder: strings.QuickReply_ShortcutPlaceholder, characterLimit: characterLimit, hasClearButton: false, @@ -58,6 +58,21 @@ public func quickReplyNameAlertController(context: AccountContext, updatedPresen autocorrectionType: .no, isInitiallyFocused: true, externalState: inputState, + shouldChangeText: { updatedText in + if updatedText.isEmpty { + return true + } + for scalar in updatedText.unicodeScalars { + if scalar.value == 0x5f || scalar.value == 0x200c || scalar.value == 0xb7 || (scalar.value >= 0xd80 && scalar.value <= 0xdff) { + continue + } + if CharacterSet.letters.contains(scalar) || CharacterSet.decimalDigits.contains(scalar) { + continue + } + return false + } + return true + }, returnKeyAction: { applyImpl?() } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 521ea3d5c1..fa5f539165 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -9385,10 +9385,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard case let .peer(peerId) = self.chatLocation else { return } + let navigationTarget = self.effectiveNavigationController.flatMap { navigationController in + resolveChatListNavigationTarget(navigationController: navigationController, excluding: self) + } self.commitPurposefulAction() self.chatDisplayNode.historyNode.disconnect() let _ = self.context.engine.peers.removePeerChat(peerId: peerId, reportChatSpam: reportChatSpam).startStandalone() - self.effectiveNavigationController?.popToRoot(animated: true) + if let navigationController = self.effectiveNavigationController { + if let navigationTarget, let popToController = navigationTarget.popToController { + let _ = navigationController.popToViewController(popToController, animated: true) + } else { + navigationController.popToRoot(animated: true) + } + } let _ = self.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peerId, isBlocked: true).startStandalone() }