diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index b14b7a66e4..8701104e79 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -612,7 +612,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll } } - func setMessage(_ message: Message, displayInfo: Bool = true) { + func setMessage(_ message: Message, displayInfo: Bool = true, translateToLanguage: String? = nil) { self.currentMessage = message let canDelete: Bool @@ -734,7 +734,17 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll break } } - messageText = galleryCaptionStringWithAppliedEntities(message.text, entities: entities, message: message) + var text = message.text + if let translateToLanguage, !text.isEmpty { + for attribute in message.attributes { + if let attribute = attribute as? TranslationMessageAttribute, !attribute.text.isEmpty, attribute.toLang == translateToLanguage { + text = attribute.text + entities = attribute.entities + break + } + } + } + messageText = galleryCaptionStringWithAppliedEntities(text, entities: entities, message: message) } if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canFullscreen != !self.fullscreenButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText { diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index aca341401f..bd7971e572 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -15,6 +15,7 @@ import WebsiteType import OpenInExternalAppUI import ScreenCaptureDetection import UndoUI +import TranslateUI private func tagsForMessage(_ message: Message) -> MessageTags? { for media in message.media { @@ -146,12 +147,12 @@ private func galleryMessageCaptionText(_ message: Message) -> String { return message.text } -public func galleryItemForEntry(context: AccountContext, presentationData: PresentationData, entry: MessageHistoryEntry, isCentral: Bool = false, streamVideos: Bool, loopVideos: Bool = false, hideControls: Bool = false, fromPlayingVideo: Bool = false, isSecret: Bool = false, landscape: Bool = false, timecode: Double? = nil, playbackRate: @escaping () -> Double?, displayInfoOnTop: Bool = false, configuration: GalleryConfiguration? = nil, tempFilePath: String? = nil, playbackCompleted: @escaping () -> Void = {}, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void = { _ in }, openActionOptions: @escaping (GalleryControllerInteractionTapAction, Message) -> Void = { _, _ in }, storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void = { _, _, _ in }, generateStoreAfterDownload: ((Message, TelegramMediaFile) -> (() -> Void)?)? = nil, present: @escaping (ViewController, Any?) -> Void) -> GalleryItem? { +public func galleryItemForEntry(context: AccountContext, presentationData: PresentationData, entry: MessageHistoryEntry, isCentral: Bool = false, streamVideos: Bool, loopVideos: Bool = false, hideControls: Bool = false, fromPlayingVideo: Bool = false, isSecret: Bool = false, landscape: Bool = false, timecode: Double? = nil, playbackRate: @escaping () -> Double?, displayInfoOnTop: Bool = false, configuration: GalleryConfiguration? = nil, translateToLanguage: String? = nil, tempFilePath: String? = nil, playbackCompleted: @escaping () -> Void = {}, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void = { _ in }, openActionOptions: @escaping (GalleryControllerInteractionTapAction, Message) -> Void = { _, _ in }, storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void = { _, _, _ in }, generateStoreAfterDownload: ((Message, TelegramMediaFile) -> (() -> Void)?)? = nil, present: @escaping (ViewController, Any?) -> Void) -> GalleryItem? { let message = entry.message let location = entry.location if let (media, mediaImage) = mediaForMessage(message: message) { if let _ = media as? TelegramMediaImage { - return ChatImageGalleryItem(context: context, presentationData: presentationData, message: message, location: location, displayInfoOnTop: displayInfoOnTop, performAction: performAction, openActionOptions: openActionOptions, present: present) + return ChatImageGalleryItem(context: context, presentationData: presentationData, message: message, location: location, translateToLanguage: translateToLanguage, displayInfoOnTop: displayInfoOnTop, performAction: performAction, openActionOptions: openActionOptions, present: present) } else if let file = media as? TelegramMediaFile { if file.isVideo { let content: UniversalVideoContent @@ -172,8 +173,17 @@ public func galleryItemForEntry(context: AccountContext, presentationData: Prese break } } + var text = galleryMessageCaptionText(message) + if let translateToLanguage, !text.isEmpty { + for attribute in message.attributes { + if let attribute = attribute as? TranslationMessageAttribute, !attribute.text.isEmpty, attribute.toLang == translateToLanguage { + text = attribute.text + entities = attribute.entities + break + } + } + } - let text = galleryMessageCaptionText(message) if let result = addLocallyGeneratedEntities(text, enabledTypes: [.timecode], entities: entities, mediaDuration: file.duration.flatMap(Double.init)) { entities = result } @@ -437,15 +447,31 @@ public class GalleryController: ViewController, StandalonePresentableController, super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: GalleryController.darkNavigationTheme, strings: NavigationBarStrings(presentationStrings: self.presentationData.strings))) - let backItem = UIBarButtonItem(backButtonAppearanceWithTitle: presentationData.strings.Common_Back, target: self, action: #selector(self.donePressed)) + let backItem = UIBarButtonItem(backButtonAppearanceWithTitle: self.presentationData.strings.Common_Back, target: self, action: #selector(self.donePressed)) self.navigationItem.leftBarButtonItem = backItem self.statusBar.statusBarStyle = .White + let baseLanguageCode = self.presentationData.strings.baseLanguageCode let message: Signal + var translateToLanguage: Signal = .single(nil) switch source { case let .peerMessagesAtId(messageId, _, _): message = context.account.postbox.messageAtId(messageId) + translateToLanguage = chatTranslationState(context: context, peerId: messageId.peerId) + |> map { translationState in + if let translationState, translationState.isEnabled { + var translateToLanguage = translationState.toLang ?? baseLanguageCode + if translateToLanguage == "nb" { + translateToLanguage = "nl" + } else if translateToLanguage == "pt-br" { + translateToLanguage = "pt" + } + return translateToLanguage + } else { + return nil + } + } case let .standaloneMessage(m): message = .single(m) case let .custom(messages, messageId, _): @@ -455,7 +481,6 @@ public class GalleryController: ViewController, StandalonePresentableController, return messages.first(where: { $0.id == messageId }) } } - let messageView = message |> filter({ $0 != nil }) |> mapToSignal { message -> Signal in @@ -506,7 +531,11 @@ public class GalleryController: ViewController, StandalonePresentableController, } let syncResult = Atomic<(Bool, (() -> Void)?)>(value: (false, nil)) - self.disposable.set(combineLatest(messageView, self.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])).start(next: { [weak self] view, preferencesView in + self.disposable.set(combineLatest( + messageView, + self.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]), + translateToLanguage + ).start(next: { [weak self] view, preferencesView, translateToLanguage in let f: () -> Void = { if let strongSelf = self { if let view = view { @@ -560,7 +589,7 @@ public class GalleryController: ViewController, StandalonePresentableController, if entry.message.stableId == strongSelf.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: streamSingleVideo, fromPlayingVideo: isCentral && fromPlayingVideo, landscape: isCentral && landscape, timecode: isCentral ? timecode : nil, playbackRate: { return self?.playbackRate }, displayInfoOnTop: displayInfoOnTop, configuration: configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, generateStoreAfterDownload: strongSelf.generateStoreAfterDownload, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: streamSingleVideo, fromPlayingVideo: isCentral && fromPlayingVideo, landscape: isCentral && landscape, timecode: isCentral ? timecode : nil, playbackRate: { return self?.playbackRate }, displayInfoOnTop: displayInfoOnTop, configuration: configuration, translateToLanguage: translateToLanguage, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, generateStoreAfterDownload: strongSelf.generateStoreAfterDownload, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } diff --git a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift index ac7fce4146..3520026a4c 100644 --- a/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/ChatImageGalleryItem.swift @@ -113,16 +113,18 @@ class ChatImageGalleryItem: GalleryItem { let presentationData: PresentationData let message: Message let location: MessageHistoryEntryLocation? + let translateToLanguage: String? let displayInfoOnTop: Bool let performAction: (GalleryControllerInteractionTapAction) -> Void let openActionOptions: (GalleryControllerInteractionTapAction, Message) -> Void let present: (ViewController, Any?) -> Void - init(context: AccountContext, presentationData: PresentationData, message: Message, location: MessageHistoryEntryLocation?, displayInfoOnTop: Bool, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void, openActionOptions: @escaping (GalleryControllerInteractionTapAction, Message) -> Void, present: @escaping (ViewController, Any?) -> Void) { + init(context: AccountContext, presentationData: PresentationData, message: Message, location: MessageHistoryEntryLocation?, translateToLanguage: String? = nil, displayInfoOnTop: Bool, performAction: @escaping (GalleryControllerInteractionTapAction) -> Void, openActionOptions: @escaping (GalleryControllerInteractionTapAction, Message) -> Void, present: @escaping (ViewController, Any?) -> Void) { self.context = context self.presentationData = presentationData self.message = message self.location = location + self.translateToLanguage = translateToLanguage self.displayInfoOnTop = displayInfoOnTop self.performAction = performAction self.openActionOptions = openActionOptions @@ -132,7 +134,7 @@ class ChatImageGalleryItem: GalleryItem { func node(synchronous: Bool) -> GalleryItemNode { let node = ChatImageGalleryItemNode(context: self.context, presentationData: self.presentationData, performAction: self.performAction, openActionOptions: self.openActionOptions, present: self.present) - node.setMessage(self.message, displayInfo: !self.displayInfoOnTop) + node.setMessage(self.message, displayInfo: !self.displayInfoOnTop, translateToLanguage: self.translateToLanguage) for media in self.message.media { if let invoice = media as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia, case let .full(fullMedia) = extendedMedia, let image = fullMedia as? TelegramMediaImage { node.setImage(userLocation: .peer(self.message.id.peerId), imageReference: .message(message: MessageReference(self.message), media: image)) @@ -171,7 +173,7 @@ class ChatImageGalleryItem: GalleryItem { if self.displayInfoOnTop { node.titleContentView?.setMessage(self.message, presentationData: self.presentationData, accountPeerId: self.context.account.peerId) } - node.setMessage(self.message, displayInfo: !self.displayInfoOnTop) + node.setMessage(self.message, displayInfo: !self.displayInfoOnTop, translateToLanguage: self.translateToLanguage) } } @@ -198,6 +200,7 @@ class ChatImageGalleryItem: GalleryItem { final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { private let context: AccountContext private var message: Message? + private var translateToLanguage: String? private let presentationData: PresentationData private let imageNode: TransformImageNode @@ -322,10 +325,11 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode { transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(), size: statusSize)) } - fileprivate func setMessage(_ message: Message, displayInfo: Bool) { + fileprivate func setMessage(_ message: Message, displayInfo: Bool, translateToLanguage: String?) { self.message = message + self.translateToLanguage = translateToLanguage self.imageNode.captureProtected = message.isCopyProtected() - self.footerContentNode.setMessage(message, displayInfo: displayInfo) + self.footerContentNode.setMessage(message, displayInfo: displayInfo, translateToLanguage: translateToLanguage) } fileprivate func setImage(userLocation: MediaResourceUserLocation, imageReference: ImageMediaReference) { diff --git a/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift b/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift index b186f309fd..49ef4cb221 100644 --- a/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift +++ b/submodules/LegacyMediaPickerUI/Sources/LegacyPaintStickersContext.swift @@ -266,18 +266,6 @@ private class LegacyPaintTextEntity: LegacyPaintEntity { var mirrored: Bool { return false } - - var animated: Bool { - return self.entity.renderAnimationFrames != nil - } - - var duration: Double { - if let lastFrame = self.entity.renderAnimationFrames?.last { - return lastFrame.timestamp + lastFrame.duration - } else { - return 0.0 - } - } let entity: DrawingTextEntity @@ -286,42 +274,13 @@ private class LegacyPaintTextEntity: LegacyPaintEntity { } var cachedCIImage: CIImage? - var cachedFrameCIImage: (Double, CIImage)? - func image(for time: CMTime, fps: Int, completion: @escaping (CIImage?) -> Void) { var image: CIImage? - if let frames = self.entity.renderAnimationFrames { - var currentTime = CMTimeGetSeconds(time) - let duration = self.duration - while currentTime > duration { - currentTime -= duration - } - - for frame in frames { - if currentTime >= frame.timestamp && currentTime < frame.timestamp + frame.duration { - if let (timestamp, cachedImage) = self.cachedFrameCIImage, timestamp == frame.timestamp { - image = cachedImage - } else if let renderImage = CIImage(image: frame.image) { - self.cachedFrameCIImage = (frame.timestamp, renderImage) - image = renderImage - } - break - } - } - if image == nil { - if let (_, cachedImage) = self.cachedFrameCIImage { - image = cachedImage - } else if let firstFrame = frames.first { - image = CIImage(image: firstFrame.image) - } - } - } else { - if let cachedImage = self.cachedCIImage { - image = cachedImage - } else if let renderImage = entity.renderImage { - image = CIImage(image: renderImage) - self.cachedCIImage = image - } + if let cachedImage = self.cachedCIImage { + image = cachedImage + } else if let renderImage = entity.renderImage { + image = CIImage(image: renderImage) + self.cachedCIImage = image } completion(image) } @@ -499,8 +458,6 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender for entity in self.entities { if let sticker = entity as? LegacyPaintStickerEntity, sticker.animated { durations.append(sticker.duration) - } else if let text = entity as? LegacyPaintTextEntity, text.animated { - durations.append(.single(text.duration)) } }