diff --git a/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift b/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift index acd11ff715..abab2b30c7 100644 --- a/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift +++ b/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift @@ -92,6 +92,11 @@ public final class AvatarVideoNode: ASDisplayNode { } } } + if animationFile.isCustomTemplateEmoji { + animationNode.dynamicColor = .white + } else { + animationNode.dynamicColor = nil + } self.backgroundNode.addSubnode(animationNode) } else { let itemNativeFitSize = self.internalSize.width > 100.0 ? CGSize(width: 192.0, height: 192.0) : CGSize(width: 64.0, height: 64.0) @@ -129,6 +134,7 @@ public final class AvatarVideoNode: ASDisplayNode { } } itemLayer.layerTintColor = UIColor.white.cgColor + self.itemLayer = itemLayer self.backgroundNode.layer.addSublayer(itemLayer) } diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index 4b488a6276..547603e4c4 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -312,7 +312,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch updatedItems.append(.separator) updatedItems.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.setItems(chatContextMenuItems(context: context, peerId: peerId, promoInfo: promoInfo, source: source, chatListController: chatListController, joined: joined) |> map { ContextController.Items(content: .list($0)) }, minHeight: nil) }))) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index ec18cf508e..0b3757cf34 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -1491,10 +1491,12 @@ public final class ChatListNode: ListView { if product.id.hasSuffix(".annual") { let fraction = Float(product.priceCurrencyAndAmount.amount) / Float(12) / Float(shortestOptionPrice.0) let discount = Int32(round((1.0 - fraction) * 20.0) * 5.0) - if suggestions.contains(.annualPremium) { - return .premiumAnnualDiscount(discount: discount) - } else if suggestions.contains(.upgradePremium) { - return .premiumUpgrade(discount: discount) + if discount > 0 { + if suggestions.contains(.annualPremium) { + return .premiumAnnualDiscount(discount: discount) + } else if suggestions.contains(.upgradePremium) { + return .premiumUpgrade(discount: discount) + } } break } diff --git a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift index e1cb4444da..493722ee9a 100644 --- a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift @@ -340,7 +340,11 @@ private final class ContextControllerActionsListActionItemNode: HighlightTrackin if let titleVerticalOffset { titleFrame = titleFrame.offsetBy(dx: 0.0, dy: titleVerticalOffset) } - let subtitleFrame = CGRect(origin: CGPoint(x: sideInset, y: titleFrame.maxY + titleSubtitleSpacing), size: subtitleSize) + var subtitleFrame = CGRect(origin: CGPoint(x: sideInset, y: titleFrame.maxY + titleSubtitleSpacing), size: subtitleSize) + if self.item.iconPosition == .left { + titleFrame = titleFrame.offsetBy(dx: 36.0, dy: 0.0) + subtitleFrame = subtitleFrame.offsetBy(dx: 36.0, dy: 0.0) + } transition.updateFrame(node: self.highlightBackgroundNode, frame: CGRect(origin: CGPoint(), size: size), beginWithCurrentState: true) transition.updateFrameAdditive(node: self.titleLabelNode, frame: titleFrame) @@ -348,7 +352,12 @@ private final class ContextControllerActionsListActionItemNode: HighlightTrackin if let iconSize = iconSize { let iconWidth = max(standardIconWidth, iconSize.width) - let iconFrame = CGRect(origin: CGPoint(x: size.width - iconSideInset - iconWidth + floor((iconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize) + let iconFrame = CGRect( + origin: CGPoint( + x: self.item.iconPosition == .left ? iconSideInset : size.width - iconSideInset - iconWidth + floor((iconWidth - iconSize.width) / 2.0), + y: floor((size.height - iconSize.height) / 2.0) + ), + size: iconSize) transition.updateFrame(node: self.iconNode, frame: iconFrame, beginWithCurrentState: true) if let animationNode = self.animationNode { transition.updateFrame(node: animationNode, frame: iconFrame, beginWithCurrentState: true) diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 5e69293fca..a5446f038f 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2631,7 +2631,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { items.append(.separator) items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in guard let strongSelf = self else { c.dismiss(completion: nil) return diff --git a/submodules/PeerInfoUI/Sources/PeerReportController.swift b/submodules/PeerInfoUI/Sources/PeerReportController.swift index a8c0e71276..d26b4c00d8 100644 --- a/submodules/PeerInfoUI/Sources/PeerReportController.swift +++ b/submodules/PeerInfoUI/Sources/PeerReportController.swift @@ -166,7 +166,7 @@ public func presentPeerReportOptions(context: AccountContext, parent: ViewContro items.append(.separator) items.append(.action(ContextMenuActionItem(text: presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) - }, action: { (c, _) in + }, iconPosition: .left, action: { (c, _) in backAction(c) }))) } diff --git a/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift b/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift index 52d97567e5..3c33297a21 100644 --- a/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift +++ b/submodules/SettingsUI/Sources/Data and Storage/DataAndStorageSettingsController.swift @@ -422,7 +422,7 @@ private enum DataAndStorageEntry: ItemListNodeEntry { }, tag: DataAndStorageEntryTag.saveEditedPhotos) case let .pauseMusicOnRecording(_, text, value): return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in - arguments.toggleSaveEditedPhotos(value) + arguments.togglePauseMusicOnRecording(value) }, tag: DataAndStorageEntryTag.saveEditedPhotos) case let .openLinksIn(_, text, value): return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: { diff --git a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift index 4cb8d7a64a..c7adeb131a 100644 --- a/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift +++ b/submodules/SettingsUI/Sources/Language Selection/LocalizationListControllerNode.swift @@ -468,9 +468,11 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { if let activeLanguage = activeLanguageCode, supportedTranslationLanguages.contains(activeLanguage) { ignoredLanguages = [activeLanguage] } - let systemLanguage = systemLanguageCode() - if !ignoredLanguages.contains(systemLanguage) { - ignoredLanguages.append(systemLanguage) + let systemLanguages = systemLanguageCodes() + for systemLanguage in systemLanguages { + if !ignoredLanguages.contains(systemLanguage) { + ignoredLanguages.append(systemLanguage) + } } } } else { @@ -478,9 +480,10 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { if let activeLanguage = activeLanguageCode, supportedTranslationLanguages.contains(activeLanguage) { ignoredLanguages = [activeLanguage] } - let systemLanguageCode = systemLanguageCode() - if !ignoredLanguages.contains(systemLanguageCode) { - ignoredLanguages.append(systemLanguageCode) + for systemLanguageCode in systemLanguageCodes() { + if !ignoredLanguages.contains(systemLanguageCode) { + ignoredLanguages.append(systemLanguageCode) + } } } @@ -561,14 +564,18 @@ final class LocalizationListControllerNode: ViewControllerTracingNode { let transition = preparedLanguageListNodeTransition(presentationData: presentationData, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, openSearch: openSearch, toggleShowTranslate: { value in let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in var updated = current.withUpdatedShowTranslate(value) - if !value { + if !updated.showTranslate && !updated.translateChats { updated = updated.withUpdatedIgnoredLanguages(nil) } return updated }).start() }, toggleTranslateChats: { value in let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in - return current.withUpdatedTranslateChats(value) + var updated = current.withUpdatedTranslateChats(value) + if !updated.showTranslate && !updated.translateChats { + updated = updated.withUpdatedIgnoredLanguages(nil) + } + return updated }).start() }, openDoNotTranslate: { [weak self] in if let strongSelf = self { diff --git a/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift b/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift index c934f0fc34..3a7af62bca 100644 --- a/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift +++ b/submodules/SettingsUI/Sources/Language Selection/TranslatonSettingsController.swift @@ -69,19 +69,36 @@ private enum TranslationSettingsControllerEntry: ItemListNodeEntry { } } -private func translationSettingsControllerEntries(theme: PresentationTheme, strings: PresentationStrings, settings: TranslationSettings, languages: [(String, String, String)]) -> [TranslationSettingsControllerEntry] { +private func translationSettingsControllerEntries(theme: PresentationTheme, strings: PresentationStrings, initiallySelectedLanguages: Set, settings: TranslationSettings, languages: [(String, String, String)]) -> [TranslationSettingsControllerEntry] { var entries: [TranslationSettingsControllerEntry] = [] - + var index: Int32 = 0 var selectedLanguages: Set if let ignoredLanguages = settings.ignoredLanguages { selectedLanguages = Set(ignoredLanguages) } else { - selectedLanguages = Set([strings.baseLanguageCode, systemLanguageCode()]) + selectedLanguages = Set([strings.baseLanguageCode]) + for language in systemLanguageCodes() { + selectedLanguages.insert(language) + } } + + var addedLanguages = Set() + for (code, title, subtitle) in languages { - entries.append(.language(index, theme, title, subtitle, selectedLanguages.contains(code), code)) - index += 1 + if !addedLanguages.contains(code), initiallySelectedLanguages.contains(code) { + addedLanguages.insert(code) + entries.append(.language(index, theme, title, subtitle, selectedLanguages.contains(code), code)) + index += 1 + } + } + + for (code, title, subtitle) in languages { + if !addedLanguages.contains(code) { + addedLanguages.insert(code) + entries.append(.language(index, theme, title, subtitle, selectedLanguages.contains(code), code)) + index += 1 + } } return entries @@ -97,11 +114,15 @@ public func translationSettingsController(context: AccountContext) -> ViewContro let _ = updateTranslationSettingsInteractively(accountManager: context.sharedContext.accountManager, { current in var updated = current var updatedIgnoredLanguages = updated.ignoredLanguages ?? [] - if value { - if current.ignoredLanguages == nil { - updatedIgnoredLanguages.append(interfaceLanguageCode) - updatedIgnoredLanguages.append(systemLanguageCode()) + if current.ignoredLanguages == nil { + updatedIgnoredLanguages.append(interfaceLanguageCode) + for language in systemLanguageCodes() { + if !updatedIgnoredLanguages.contains(language) { + updatedIgnoredLanguages.append(language) + } } + } + if value { if !updatedIgnoredLanguages.contains(code) { updatedIgnoredLanguages.append(code) } @@ -142,13 +163,33 @@ public func translationSettingsController(context: AccountContext) -> ViewContro } } } + + let initiallySelectedLanguages = Atomic?>(value: nil) let sharedData = context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]) let signal = combineLatest(queue: Queue.mainQueue(), context.sharedContext.presentationData, sharedData) |> map { presentationData, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in let settings = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) ?? TranslationSettings.defaultSettings + + let initiallySelectedLanguages = initiallySelectedLanguages.modify({ current in + if let current { + return current + } else { + var selectedLanguages: Set + if let ignoredLanguages = settings.ignoredLanguages { + selectedLanguages = Set(ignoredLanguages) + } else { + selectedLanguages = Set([presentationData.strings.baseLanguageCode]) + for language in systemLanguageCodes() { + selectedLanguages.insert(language) + } + } + return selectedLanguages + } + }) + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DoNotTranslate_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: translationSettingsControllerEntries(theme: presentationData.theme, strings: presentationData.strings, settings: settings, languages: languages), style: .blocks, animateChanges: false) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: translationSettingsControllerEntries(theme: presentationData.theme, strings: presentationData.strings, initiallySelectedLanguages: initiallySelectedLanguages ?? Set(), settings: settings, languages: languages), style: .blocks, animateChanges: false) return (controllerState, (listState, arguments)) } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index a646415d40..5f5f53e49e 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -2860,7 +2860,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController items.append(.separator) items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) - }, action: { [weak self] (c, _) in + }, iconPosition: .left, action: { [weak self] (c, _) in guard let strongSelf = self else { return } @@ -2955,7 +2955,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController items.append(.separator) items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) - }, action: { (c, _) in + }, iconPosition: .left, action: { (c, _) in guard let strongSelf = self else { return } @@ -3001,7 +3001,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController items.append(.separator) items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) - }, action: { [weak self] (c, _) in + }, iconPosition: .left, action: { [weak self] (c, _) in guard let strongSelf = self else { return } diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift index c3eb03752b..e0b8a2cf0b 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramUser.swift @@ -203,13 +203,20 @@ extension TelegramUser { let restrictionInfo: PeerAccessRestrictionInfo? = rhs.restrictionInfo let accessHash: TelegramPeerAccessHash? - if let rhsAccessHashValue = lhs.accessHash, case .personal = rhsAccessHashValue { + if let rhsAccessHashValue = rhs.accessHash, case .personal = rhsAccessHashValue { accessHash = rhsAccessHashValue } else { accessHash = lhs.accessHash ?? rhs.accessHash } - return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: rhs.username, phone: lhs.phone, photo: rhs.photo.isEmpty ? lhs.photo : rhs.photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: rhs.usernames) + let photo: [TelegramMediaImageRepresentation] + if case .genericPublic = rhs.accessHash { + photo = lhs.photo + } else { + photo = rhs.photo + } + + return TelegramUser(id: lhs.id, accessHash: accessHash, firstName: lhs.firstName, lastName: lhs.lastName, username: rhs.username, phone: lhs.phone, photo: photo, botInfo: botInfo, restrictionInfo: restrictionInfo, flags: userFlags, emojiStatus: emojiStatus, usernames: rhs.usernames) } } } diff --git a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift index bb4b3e6f47..3e880801b2 100644 --- a/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift +++ b/submodules/TelegramUI/Components/AvatarEditorScreen/Sources/AvatarPreviewComponent.swift @@ -99,7 +99,6 @@ final class AvatarPreviewComponent: Component { let hadFile = self.component?.file != nil var fileUpdated = false if self.component?.file?.fileId != component.file?.fileId { - self.imageNode.isHidden = false fileUpdated = true } @@ -130,9 +129,8 @@ final class AvatarPreviewComponent: Component { }) } + self.imageNode.isHidden = false if file.isAnimatedSticker || file.isVideoSticker || file.mimeType == "video/webm" { - self.imageNode.isHidden = false - if self.animationNode == nil { let animationNode = DefaultAnimatedStickerNodeImpl() animationNode.autoplay = false @@ -150,7 +148,6 @@ final class AvatarPreviewComponent: Component { animationNode.visibility = false self.animationNode = nil animationNode.removeFromSupernode() - self.imageNode.isHidden = false } self.imageNode.setSignal(chatMessageSticker(account: component.context.account, userLocation: .other, file: file, small: false, synchronousLoad: false)) self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: component.context.account, userLocation: .other, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: false)).start()) @@ -204,6 +201,14 @@ final class AvatarPreviewComponent: Component { let source = AnimatedStickerResourceSource(account: component.context.account, resource: file.resource, isVideo: file.isVideoSticker || file.mimeType == "video/webm") self.animationNode?.setup(source: source, width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .count(1), mode: .direct(cachePathPrefix: nil)) self.animationNode?.visibility = true + + if let animationNode = self.animationNode as? DefaultAnimatedStickerNodeImpl { + if file.isCustomTemplateEmoji { + animationNode.dynamicColor = .white + } else { + animationNode.dynamicColor = nil + } + } self.cachedDisposable.set((source.cachedDataPath(width: 384, height: 384) |> deliverOn(Queue.concurrentDefaultQueue())).start()) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index e05b04b864..70d2465c2c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10074,7 +10074,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) |> deliverOnMainQueue).start(completed: { [weak self] in if let strongSelf = self, type == .translated { - Queue.mainQueue().after(0.3) { + Queue.mainQueue().after(0.15) { strongSelf.chatDisplayNode.historyNode.refreshPollActionsForVisibleMessages() } } @@ -10106,7 +10106,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { var ignoredLanguages = Set() ignoredLanguages.insert(strongSelf.presentationData.strings.baseLanguageCode) - ignoredLanguages.insert(systemLanguageCode()) + for language in systemLanguageCodes() { + ignoredLanguages.insert(language) + } ignoredLanguages.insert(langCode) updated.ignoredLanguages = Array(ignoredLanguages) } diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift index 10c8229697..afc5c9fd49 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoBubbleContentNode.swift @@ -241,7 +241,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode { let videoFrame = CGRect(origin: CGPoint(x: 1.0, y: 1.0), size: videoLayout.contentSize) - let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none, shareButtonOffset: isExpanded ? nil : CGPoint(x: displaySize.width + 4.0, y: -25.0), hidesHeaders: !isExpanded, avatarOffset: !isExpanded && isPlaying ? -100.0 : 0.0) + let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none, shareButtonOffset: isExpanded ? nil : CGPoint(x: avatarInset + displaySize.width + 4.0, y: -25.0), hidesHeaders: !isExpanded, avatarOffset: !isExpanded && isPlaying ? -100.0 : 0.0) let videoFrameWidth = videoFrame.width + 2.0 diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index a684a302fa..316ad982f5 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -21,6 +21,7 @@ import ChatPresentationInterfaceState import TextNodeWithEntities import AnimationCache import MultiAnimationRenderer +import TranslateUI private enum PinnedMessageAnimation { case slideToTop @@ -70,6 +71,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { private var currentLayout: (CGFloat, CGFloat, CGFloat)? private var currentMessage: ChatPinnedMessage? private var previousMediaReference: AnyMediaReference? + private var currentTranslateToLanguage: String? + private let translationDisposable = MetaDisposable() private var isReplyThread: Bool = false @@ -229,6 +232,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { deinit { self.fetchDisposable.dispose() self.statusDisposable?.dispose() + self.translationDisposable.dispose() } private var theme: PresentationTheme? @@ -473,7 +477,30 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { self.clippingContainer.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight)) self.contentContainer.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: panelHeight)) - if self.currentLayout?.0 != width || self.currentLayout?.1 != leftInset || self.currentLayout?.2 != rightInset || messageUpdated || themeUpdated { + var translateToLanguage: String? + if let translationState = interfaceState.translationState, translationState.isEnabled { + translateToLanguage = translationState.toLang + if translateToLanguage == "nb" { + translateToLanguage = "nl" + } else if translateToLanguage == "pt-br" { + translateToLanguage = "pt" + } + } + + var currentTranslateToLanguageUpdated = false + if self.currentTranslateToLanguage != translateToLanguage { + self.currentTranslateToLanguage = translateToLanguage + currentTranslateToLanguageUpdated = true + } + + if currentTranslateToLanguageUpdated || messageUpdated, let message = interfaceState.pinnedMessage?.message { + if let translation = message.attributes.first(where: { $0 is TranslationMessageAttribute }) as? TranslationMessageAttribute, translation.toLang == translateToLanguage { + } else if let translateToLanguage { + self.translationDisposable.set(translateMessageIds(context: self.context, messageIds: [message.id], toLang: translateToLanguage).start()) + } + } + + if self.currentLayout?.0 != width || self.currentLayout?.1 != leftInset || self.currentLayout?.2 != rightInset || messageUpdated || themeUpdated || currentTranslateToLanguageUpdated { self.currentLayout = (width, leftInset, rightInset) let previousMessageWasNil = self.currentMessage == nil @@ -481,7 +508,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { if let currentMessage = self.currentMessage, let currentLayout = self.currentLayout { self.dustNode?.update(revealed: false, animated: false) - self.enqueueTransition(width: currentLayout.0, panelHeight: panelHeight, leftInset: currentLayout.1, rightInset: currentLayout.2, transition: .immediate, animation: messageUpdatedAnimation, pinnedMessage: currentMessage, theme: interfaceState.theme, strings: interfaceState.strings, nameDisplayOrder: interfaceState.nameDisplayOrder, dateTimeFormat: interfaceState.dateTimeFormat, accountPeerId: self.context.account.peerId, firstTime: previousMessageWasNil, isReplyThread: isReplyThread) + self.enqueueTransition(width: currentLayout.0, panelHeight: panelHeight, leftInset: currentLayout.1, rightInset: currentLayout.2, transition: .immediate, animation: messageUpdatedAnimation, pinnedMessage: currentMessage, theme: interfaceState.theme, strings: interfaceState.strings, nameDisplayOrder: interfaceState.nameDisplayOrder, dateTimeFormat: interfaceState.dateTimeFormat, accountPeerId: self.context.account.peerId, firstTime: previousMessageWasNil, isReplyThread: isReplyThread, translateToLanguage: translateToLanguage) } } @@ -498,7 +525,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { return LayoutResult(backgroundHeight: panelHeight, insetHeight: panelHeight) } - private func enqueueTransition(width: CGFloat, panelHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, animation: PinnedMessageAnimation?, pinnedMessage: ChatPinnedMessage, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: PeerId, firstTime: Bool, isReplyThread: Bool) { + private func enqueueTransition(width: CGFloat, panelHeight: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, animation: PinnedMessageAnimation?, pinnedMessage: ChatPinnedMessage, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: PeerId, firstTime: Bool, isReplyThread: Bool, translateToLanguage: String?) { let message = pinnedMessage.message var animationTransition: ContainedViewLayoutTransition = .immediate @@ -652,7 +679,20 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { let messageText: NSAttributedString let textFont = Font.regular(15.0) if isText { - let entities = (message.textEntitiesAttribute?.entities ?? []).filter { entity in + var text = message.text + var messageEntities = message.textEntitiesAttribute?.entities ?? [] + + if let translateToLanguage = translateToLanguage, !text.isEmpty { + for attribute in message.attributes { + if let attribute = attribute as? TranslationMessageAttribute, !attribute.text.isEmpty, attribute.toLang == translateToLanguage { + text = attribute.text + messageEntities = attribute.entities + break + } + } + } + + let entities = messageEntities.filter { entity in switch entity.type { case .Spoiler, .CustomEmoji: return true @@ -662,9 +702,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { } let textColor = theme.chat.inputPanel.primaryTextColor if entities.count > 0 { - messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message) + messageText = stringWithAppliedEntities(trimToLineCount(text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message) } else { - messageText = NSAttributedString(string: foldLineBreaks(textString.string), font: textFont, textColor: textColor) + messageText = NSAttributedString(string: foldLineBreaks(text), font: textFont, textColor: textColor) } } else { messageText = NSAttributedString(string: foldLineBreaks(textString.string), font: textFont, textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor) diff --git a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift index 0c90682b14..42cb875ff3 100644 --- a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift @@ -174,9 +174,9 @@ final class ChatTranslationPanelNode: ASDisplayNode { }, action: { c, _ in var subItems: [ContextMenuItem] = [] - subItems.append(.action(ContextMenuActionItem(text: presentationData.strings.Common_Back, icon: { theme in + subItems.append(.action(ContextMenuActionItem(text: presentationData.strings.ChatList_Context_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.popItems() }))) subItems.append(.separator) @@ -184,8 +184,19 @@ final class ChatTranslationPanelNode: ASDisplayNode { let enLocale = Locale(identifier: "en") var languages: [(String, String, String)] = [] var addedLanguages = Set() - for code in popularTranslationLanguages { - if let title = enLocale.localizedString(forLanguageCode: code) { + + var topLanguages: [String] = [] + var langCode = languageCode + if langCode == "nb" { + langCode = "nl" + } else if langCode == "pt-br" { + langCode = "pt" + } + topLanguages.append(langCode) + topLanguages.append(contentsOf: popularTranslationLanguages) + + for code in topLanguages { + if !addedLanguages.contains(code), let title = enLocale.localizedString(forLanguageCode: code) { let languageLocale = Locale(identifier: code) let subtitle = languageLocale.localizedString(forLanguageCode: code) ?? title let value = (code, title.capitalized, subtitle.capitalized) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 3d998e9e8b..ce567f5da3 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4261,7 +4261,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate subItems.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.popItems() }))) subItems.append(.separator) @@ -4766,7 +4766,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.popItems() }))) subItems.append(.separator) @@ -4941,7 +4941,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.popItems() }))) subItems.append(.separator) @@ -5075,7 +5075,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate subItems.append(.action(ContextMenuActionItem(text: strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.popItems() }))) subItems.append(.separator) @@ -5432,7 +5432,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate subItems.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) - }, action: { c, _ in + }, iconPosition: .left, action: { c, _ in c.popItems() }))) subItems.append(.separator) @@ -6239,7 +6239,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate items.append(.separator) items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.actionSheet.primaryTextColor) - }, action: { (c, _) in + }, iconPosition: .left, action: { (c, _) in if let backAction = backAction { backAction(c) } diff --git a/submodules/TranslateUI/Sources/ChatTranslation.swift b/submodules/TranslateUI/Sources/ChatTranslation.swift index 27edbd09d7..9136a63b55 100644 --- a/submodules/TranslateUI/Sources/ChatTranslation.swift +++ b/submodules/TranslateUI/Sources/ChatTranslation.swift @@ -165,7 +165,9 @@ public func chatTranslationState(context: AccountContext, peerId: EnginePeer.Id) dontTranslateLanguages = Set(ignoredLanguages) } else { dontTranslateLanguages.insert(baseLang) - dontTranslateLanguages.insert(systemLanguageCode()) + for language in systemLanguageCodes() { + dontTranslateLanguages.insert(language) + } } return cachedChatTranslationState(engine: context.engine, peerId: peerId) diff --git a/submodules/TranslateUI/Sources/Translate.swift b/submodules/TranslateUI/Sources/Translate.swift index 1aaa3e889b..a7ba897139 100644 --- a/submodules/TranslateUI/Sources/Translate.swift +++ b/submodules/TranslateUI/Sources/Translate.swift @@ -179,10 +179,11 @@ public func canTranslateText(context: AccountContext, text: String, showTranslat } } -public func systemLanguageCode() -> String { - if let systemLanguage = Locale.preferredLanguages.first { - let language = systemLanguage.components(separatedBy: "-").first ?? systemLanguage - return language +public func systemLanguageCodes() -> [String] { + var languages: [String] = [] + for language in Locale.preferredLanguages.prefix(2) { + let language = language.components(separatedBy: "-").first ?? language + languages.append(language) } - return "" + return languages }