diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e67ef92237..0651766d24 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7250,3 +7250,6 @@ Sorry for the inconvenience."; "Group.Members.Contacts" = "CONTACTS IN THIS GROUP"; "Group.Members.Other" = "OTHERS MEMBERS"; + +"SharedMedia.CommonGroupCount_1" = "%@ group in common"; +"SharedMedia.CommonGroupCount_any" = "%@ groups in common"; diff --git a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift index 15b6145ccb..3606de013b 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift @@ -679,7 +679,20 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll Queue.mainQueue().after(1.0) { var firstItem: StickerPackItem? if let firstStickerItem = firstStickerItem, let resource = firstStickerItem.resource as? TelegramMediaResource { - firstItem = StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: firstStickerItem.mimeType, size: nil, attributes: [.FileName(fileName: ""), .ImageSize(size: firstStickerItem.dimensions)]), indexKeys: []) + var fileAttributes: [TelegramMediaFileAttribute] = [] + if firstStickerItem.mimeType == "video/webm" { + fileAttributes.append(.FileName(fileName: "sticker.webm")) + fileAttributes.append(.Animated) + fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil)) + } else if firstStickerItem.mimeType == "application/x-tgsticker" { + fileAttributes.append(.FileName(fileName: "sticker.tgs")) + fileAttributes.append(.Animated) + fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil)) + } else { + fileAttributes.append(.FileName(fileName: "sticker.webp")) + } + fileAttributes.append(.ImageSize(size: firstStickerItem.dimensions)) + firstItem = StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: firstStickerItem.mimeType, size: nil, attributes: fileAttributes), indexKeys: []) } strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).string, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { action in if case .info = action { diff --git a/submodules/InstantPageUI/BUILD b/submodules/InstantPageUI/BUILD index 75a726f91c..3cc5b21b3a 100644 --- a/submodules/InstantPageUI/BUILD +++ b/submodules/InstantPageUI/BUILD @@ -25,6 +25,7 @@ swift_library( "//submodules/AppBundle:AppBundle", "//submodules/LocationResources:LocationResources", "//submodules/UndoUI:UndoUI", + "//submodules/Translate:Translate", ], visibility = [ "//visibility:public", diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index 1646b03baf..57f8406db3 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -16,6 +16,7 @@ import OpenInExternalAppUI import LocationUI import UndoUI import ContextUI +import Translate final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { private weak var controller: InstantPageController? @@ -1020,23 +1021,46 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { coveringRect = coveringRect.union(rects[i]) } - let controller = ContextMenuController(actions: [ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuCopy, accessibilityLabel: self.strings.Conversation_ContextMenuCopy), action: { - UIPasteboard.general.string = text - }), ContextMenuAction(content: .text(title: self.strings.Conversation_ContextMenuShare, accessibilityLabel: self.strings.Conversation_ContextMenuShare), action: { [weak self] in - if let strongSelf = self, let webPage = strongSelf.webPage, case let .Loaded(content) = webPage.content { - strongSelf.present(ShareController(context: strongSelf.context, subject: .quote(text: text, url: content.url)), nil) - } - })]) - controller.dismissed = { [weak self] in - self?.updateTextSelectionRects([], text: nil) - } - self.present(controller, ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self] in - if let strongSelf = self { - return (strongSelf.scrollNode, coveringRect.insetBy(dx: -3.0, dy: -3.0), strongSelf, strongSelf.bounds) + let context = self.context + let strings = self.strings + let _ = (context.sharedContext.accountManager.sharedData(keys: [ApplicationSpecificSharedDataKeys.translationSettings]) + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] sharedData in + let translationSettings: TranslationSettings + if let current = sharedData.entries[ApplicationSpecificSharedDataKeys.translationSettings]?.get(TranslationSettings.self) { + translationSettings = current } else { - return nil + translationSettings = TranslationSettings.defaultSettings } - })) + + var actions: [ContextMenuAction] = [ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuCopy, accessibilityLabel: strings.Conversation_ContextMenuCopy), action: { + UIPasteboard.general.string = text + }), ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuShare, accessibilityLabel: strings.Conversation_ContextMenuShare), action: { [weak self] in + if let strongSelf = self, let webPage = strongSelf.webPage, case let .Loaded(content) = webPage.content { + strongSelf.present(ShareController(context: strongSelf.context, subject: .quote(text: text, url: content.url)), nil) + } + })] + + + if canTranslateText(context: context, text: text, showTranslate: translationSettings.showTranslate, ignoredLanguages: translationSettings.ignoredLanguages) { + actions.append(ContextMenuAction(content: .text(title: strings.Conversation_ContextMenuTranslate, accessibilityLabel: strings.Conversation_ContextMenuTranslate), action: { + translateText(context: context, text: text) + })) + } + + let controller = ContextMenuController(actions: actions) + controller.dismissed = { [weak self] in + self?.updateTextSelectionRects([], text: nil) + } + self?.present(controller, ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self] in + if let strongSelf = self { + return (strongSelf.scrollNode, coveringRect.insetBy(dx: -3.0, dy: -3.0), strongSelf, strongSelf.bounds) + } else { + return nil + } + })) + }) + textSelectionNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18) } else if let textSelectionNode = self.textSelectionNode { self.textSelectionNode = nil diff --git a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift index 64861a4d90..b39946925d 100644 --- a/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift +++ b/submodules/ItemListStickerPackItem/Sources/ItemListStickerPackItem.swift @@ -196,7 +196,9 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode { let isVisible = self.visibility != .none if wasVisible != isVisible { - self.animationNode?.visibility = isVisible && (self.layoutParams?.0.playAnimatedStickers ?? true) + let visibility = isVisible && (self.layoutParams?.0.playAnimatedStickers ?? true) + self.videoNode?.update(isPlaying: visibility) + self.animationNode?.visibility = visibility } } } diff --git a/submodules/SparseItemGrid/Sources/SparseDiscreteScrollingArea.swift b/submodules/SparseItemGrid/Sources/SparseDiscreteScrollingArea.swift index f84066038b..83cddac3dd 100644 --- a/submodules/SparseItemGrid/Sources/SparseDiscreteScrollingArea.swift +++ b/submodules/SparseItemGrid/Sources/SparseDiscreteScrollingArea.swift @@ -354,7 +354,8 @@ public final class SparseDiscreteScrollingArea: ASDisplayNode { backgroundColor: theme.list.itemBlocksBackgroundColor, shadowColor: .black, foregroundColor: theme.list.itemPrimaryTextColor, - dateString: "Date" + dateString: "Date", + previousDateString: nil )), environment: {}, containerSize: containerSize diff --git a/submodules/SparseItemGrid/Sources/SparseItemGridScrollingArea.swift b/submodules/SparseItemGrid/Sources/SparseItemGridScrollingArea.swift index c0f4e37302..f34c4bb799 100644 --- a/submodules/SparseItemGrid/Sources/SparseItemGridScrollingArea.swift +++ b/submodules/SparseItemGrid/Sources/SparseItemGridScrollingArea.swift @@ -555,22 +555,170 @@ private final class ShadowRoundedRectangle: Component { } } +public final class RollingText: Component { + private final class MeasureState: Equatable { + let attributedText: NSAttributedString + let availableSize: CGSize + let size: CGSize + + init(attributedText: NSAttributedString, availableSize: CGSize, size: CGSize) { + self.attributedText = attributedText + self.availableSize = availableSize + self.size = size + } + + static func ==(lhs: MeasureState, rhs: MeasureState) -> Bool { + if !lhs.attributedText.isEqual(rhs.attributedText) { + return false + } + if lhs.availableSize != rhs.availableSize { + return false + } + if lhs.size != rhs.size { + return false + } + return true + } + } + + public final class View: UIView { + private var measureState: MeasureState? + private var containerView: UIImageView + + private var snapshotView: UIView? + + public override init(frame: CGRect) { + self.containerView = UIImageView() + + super.init(frame: frame) + + self.addSubview(self.containerView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func update(component: RollingText, availableSize: CGSize) -> CGSize { + let attributedText = NSAttributedString(string: component.text, attributes: [ + NSAttributedString.Key.font: component.font, + NSAttributedString.Key.foregroundColor: component.color + ]) + + if let measureState = self.measureState { + if measureState.attributedText.isEqual(to: attributedText) && measureState.availableSize == availableSize { + return measureState.size + } + } + + var boundingRect = attributedText.boundingRect(with: availableSize, options: .usesLineFragmentOrigin, context: nil) + boundingRect.size.width = ceil(boundingRect.size.width) + boundingRect.size.height = ceil(boundingRect.size.height) + + if let animation = component.animation { + if let snapshotView = self.snapshotView { + self.snapshotView = nil + snapshotView.removeFromSuperview() + + self.containerView.layer.removeAnimation(forKey: "opacity") + } + if let snapshotView = self.containerView.snapshotView(afterScreenUpdates: true) { + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: animation ? 12.0 : -12.0), duration: 0.2, removeOnCompletion: false, additive: true, completion: { [weak self, weak snapshotView] _ in + self?.snapshotView = nil + snapshotView?.removeFromSuperview() + }) + snapshotView.frame = CGRect(origin: CGPoint(x: boundingRect.width - snapshotView.frame.width, y: 0.0), size: snapshotView.frame.size) + + self.addSubview(snapshotView) + self.snapshotView = snapshotView + + self.containerView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.containerView.layer.animatePosition(from: animation ? CGPoint(x: 0.0, y: -12.0) : CGPoint(x: 0.0, y: 12.0), to: CGPoint(), duration: 0.2, additive: true) + } + } + + self.containerView.frame = CGRect(origin: CGPoint(), size: boundingRect.size) + + let measureState = MeasureState(attributedText: attributedText, availableSize: availableSize, size: boundingRect.size) + if #available(iOS 10.0, *) { + let renderer = UIGraphicsImageRenderer(bounds: CGRect(origin: CGPoint(), size: measureState.size)) + let image = renderer.image { context in + UIGraphicsPushContext(context.cgContext) + measureState.attributedText.draw(at: CGPoint()) + UIGraphicsPopContext() + } + self.containerView.image = image + } else { + UIGraphicsBeginImageContextWithOptions(measureState.size, false, 0.0) + measureState.attributedText.draw(at: CGPoint()) + self.containerView.image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + } + + self.measureState = measureState + + return boundingRect.size + } + } + + public let text: String + public let font: UIFont + public let color: UIColor + public let animation: Bool? + + public init(text: String, font: UIFont, color: UIColor, animation: Bool?) { + self.text = text + self.font = font + self.color = color + self.animation = animation + } + + public static func ==(lhs: RollingText, rhs: RollingText) -> Bool { + if lhs.text != rhs.text { + return false + } + if !lhs.font.isEqual(rhs.font) { + return false + } + if !lhs.color.isEqual(rhs.color) { + return false + } + if lhs.animation != rhs.animation { + return false + } + return true + } + + public func makeView() -> View { + return View() + } + + public func update(view: View, availableSize: CGSize, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize) + } +} + + final class SparseItemGridScrollingIndicatorComponent: CombinedComponent { let backgroundColor: UIColor let shadowColor: UIColor let foregroundColor: UIColor let dateString: String + let previousDateString: String? init( backgroundColor: UIColor, shadowColor: UIColor, foregroundColor: UIColor, - dateString: String + dateString: String, + previousDateString: String? ) { self.backgroundColor = backgroundColor self.shadowColor = shadowColor self.foregroundColor = foregroundColor self.dateString = dateString + self.previousDateString = previousDateString } static func ==(lhs: SparseItemGridScrollingIndicatorComponent, rhs: SparseItemGridScrollingIndicatorComponent) -> Bool { @@ -586,19 +734,90 @@ final class SparseItemGridScrollingIndicatorComponent: CombinedComponent { if lhs.dateString != rhs.dateString { return false } + if lhs.previousDateString != rhs.previousDateString { + return false + } return true } static var body: Body { let rect = Child(ShadowRoundedRectangle.self) - let text = Child(Text.self) + let textMonth = Child(RollingText.self) + let textYear = Child(RollingText.self) return { context in - let text = text.update( - component: Text( - text: context.component.dateString, - font: Font.medium(13.0), - color: context.component.foregroundColor + let components = context.component.dateString.components(separatedBy: " ") + let month = components.first ?? "" + let year = components.last ?? "" + + var monthAnimation: Bool? + var yearAnimation: Bool? + if let previousDateString = context.component.previousDateString { + func monthValue(_ string: String) -> Int { + switch string { + case "January": + return 1 + case "February": + return 2 + case "March": + return 3 + case "April": + return 4 + case "May": + return 5 + case "June": + return 6 + case "July": + return 7 + case "August": + return 8 + case "September": + return 9 + case "October": + return 10 + case "November": + return 11 + case "December": + return 12 + default: + return 0 + } + } + let monValue = monthValue(month) + let yearValue = Int(year) ?? 0 + + let previousComponents = previousDateString.components(separatedBy: " ") + let previousMonth = previousComponents.first ?? "" + let previousYear = previousComponents.last ?? "" + + let previousMonValue = monthValue(previousMonth) + let previousYearValue = Int(previousYear) ?? 0 + + if yearValue != previousYearValue { + yearAnimation = yearValue > previousYearValue + monthAnimation = yearAnimation + } else if monValue != previousMonValue { + monthAnimation = monValue > previousMonValue + } + } + + let textMonth = textMonth.update( + component: RollingText( + text: month, + font: Font.with(size: 13.0, design: .regular, weight: .medium, traits: .monospacedNumbers), + color: context.component.foregroundColor, + animation: monthAnimation + ), + availableSize: CGSize(width: 200.0, height: 100.0), + transition: .immediate + ) + + let textYear = textYear.update( + component: RollingText( + text: year, + font: Font.with(size: 13.0, design: .regular, weight: .medium, traits: .monospacedNumbers), + color: context.component.foregroundColor, + animation: yearAnimation ), availableSize: CGSize(width: 200.0, height: 100.0), transition: .immediate @@ -608,7 +827,7 @@ final class SparseItemGridScrollingIndicatorComponent: CombinedComponent { component: ShadowRoundedRectangle( color: context.component.backgroundColor ), - availableSize: CGSize(width: text.size.width + 26.0, height: 32.0), + availableSize: CGSize(width: textMonth.size.width + 3.0 + textYear.size.width + 26.0, height: 32.0), transition: .immediate ) @@ -620,10 +839,16 @@ final class SparseItemGridScrollingIndicatorComponent: CombinedComponent { context.add(rect .position(CGPoint(x: rectFrame.midX, y: rectFrame.midY)) ) + + let offset = CGSize(width: textMonth.size.width + 3.0 + textYear.size.width, height: textMonth.size.height).centered(in: rectFrame) - let textFrame = text.size.centered(in: rectFrame) - context.add(text - .position(CGPoint(x: textFrame.midX, y: textFrame.midY)) + let monthTextFrame = textMonth.size.leftCentered(in: rectFrame).offsetBy(dx: offset.minX, dy: 0.0) + let yearTextFrame = textYear.size.leftCentered(in: rectFrame).offsetBy(dx: offset.minX + monthTextFrame.width + 3.0, dy: 0.0) + context.add(textMonth + .position(CGPoint(x: monthTextFrame.midX, y: monthTextFrame.midY)) + ) + context.add(textYear + .position(CGPoint(x: yearTextFrame.midX, y: yearTextFrame.midY)) ) return rect.size @@ -900,6 +1125,8 @@ public final class SparseItemGridScrollingArea: ASDisplayNode { self.hapticFeedback.tap() } + private var dateString: String? + public func update( containerSize: CGSize, containerInsets: UIEdgeInsets, @@ -912,6 +1139,8 @@ public final class SparseItemGridScrollingArea: ASDisplayNode { ) { self.containerSize = containerSize self.theme = theme + let previousDateString = self.dateString + self.dateString = dateString if self.dateIndicator.alpha.isZero { let transition: ContainedViewLayoutTransition = .immediate @@ -928,7 +1157,8 @@ public final class SparseItemGridScrollingArea: ASDisplayNode { backgroundColor: theme.list.itemBlocksBackgroundColor, shadowColor: .black, foregroundColor: theme.list.itemPrimaryTextColor, - dateString: dateString + dateString: dateString, + previousDateString: previousDateString )), environment: {}, containerSize: containerSize diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index 37f5479b09..788cf5095d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -482,18 +482,15 @@ public final class TelegramMediaFile: Media, Equatable, Codable { if self.mimeType == "video/webm" { return true } - if let _ = self.fileName, self.mimeType == "video/webm" { + if self.mimeType == "video/webm" { var hasSticker = false - var hasAnimated = false for attribute in self.attributes { if case .Sticker = attribute { hasSticker = true - } - if case .Animated = attribute { - hasAnimated = true + break } } - return hasSticker && hasAnimated + return hasSticker } return false } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift index 294727ca33..3331fa05b5 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift @@ -48,8 +48,7 @@ func _internal_uploadSticker(account: Account, peer: Peer, resource: MediaResour case let .progress(progress): return .single(.progress(progress)) case let .inputFile(file): - var flags: Int32 = 0 - flags |= (1 << 4) + let flags: Int32 = 0 var attributes: [Api.DocumentAttribute] = [] attributes.append(.documentAttributeSticker(flags: 0, alt: alt, stickerset: .inputStickerSetEmpty, maskCoords: nil)) attributes.append(.documentAttributeImageSize(w: dimensions.width, h: dimensions.height)) @@ -134,8 +133,13 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri } if resources.count == stickers.count { var flags: Int32 = 0 - if case .animation = type { - flags |= (1 << 1) + switch type { + case .animation: + flags |= (1 << 1) + case .video: + flags |= (1 << 4) + default: + break } var inputStickers: [Api.InputStickerSetItem] = [] let stickerDocuments = thumbnail != nil ? resources.dropLast() : resources diff --git a/submodules/TelegramUI/Sources/ChatMediaInputMetaSectionItemNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputMetaSectionItemNode.swift index 7ee2b55b56..6588da8769 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputMetaSectionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputMetaSectionItemNode.swift @@ -239,11 +239,7 @@ final class ChatMediaInputMetaSectionItemNode: ListViewItemNode { } else { animatedStickerNode = AnimatedStickerNode() self.animatedStickerNode = animatedStickerNode - // if let placeholderNode = self.placeholderNode { - // self.scalingNode.insertSubnode(animatedStickerNode, belowSubnode: placeholderNode) - // } else { - self.scalingNode.addSubnode(animatedStickerNode) - // } + self.scalingNode.addSubnode(animatedStickerNode) animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: account, resource: file.resource), width: 128, height: 128, mode: .cached) } animatedStickerNode.visibility = self.visibilityStatus && loopAnimatedStickers diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift index 99cbcde95e..1248d10f8d 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputPanelItem.swift @@ -88,6 +88,7 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode private let imageNodeBackground: ASDisplayNode private let imageNode: TransformImageNode private var animationNode: AnimatedStickerNode? + private var videoStickerNode: VideoStickerNode? private var placeholderNode: StickerShimmerEffectNode? private var videoLayer: (SoftwareVideoThumbnailNode, SoftwareVideoLayerFrameManager, SampleBufferLayer)? private var currentImageResource: TelegramMediaResource? @@ -416,28 +417,37 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode animationNode.removeFromSupernode() } + if let videoStickerNode = strongSelf.videoStickerNode { + strongSelf.videoStickerNode = nil + videoStickerNode.removeFromSupernode() + } + if let animatedStickerFile = animatedStickerFile { - let animationNode: AnimatedStickerNode - if let currentAnimationNode = strongSelf.animationNode { - animationNode = currentAnimationNode + if animatedStickerFile.isVideoSticker { + } else { - animationNode = AnimatedStickerNode() - animationNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0) - animationNode.visibility = true - if let placeholderNode = strongSelf.placeholderNode { - strongSelf.insertSubnode(animationNode, belowSubnode: placeholderNode) + let animationNode: AnimatedStickerNode + if let currentAnimationNode = strongSelf.animationNode { + animationNode = currentAnimationNode } else { - strongSelf.addSubnode(animationNode) + animationNode = AnimatedStickerNode() + animationNode.transform = CATransform3DMakeRotation(CGFloat.pi / 2.0, 0.0, 0.0, 1.0) + animationNode.visibility = true + if let placeholderNode = strongSelf.placeholderNode { + strongSelf.insertSubnode(animationNode, belowSubnode: placeholderNode) + } else { + strongSelf.addSubnode(animationNode) + } + strongSelf.animationNode = animationNode } - strongSelf.animationNode = animationNode + animationNode.started = { [weak self] in + self?.imageNode.alpha = 0.0 + } + let dimensions = animatedStickerFile.dimensions ?? PixelDimensions(width: 512, height: 512) + let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)) + strongSelf.fetchDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(animatedStickerFile), resource: animatedStickerFile.resource).start()) + animationNode.setup(source: AnimatedStickerResourceSource(account: item.account, resource: animatedStickerFile.resource), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) } - animationNode.started = { [weak self] in - self?.imageNode.alpha = 0.0 - } - let dimensions = animatedStickerFile.dimensions ?? PixelDimensions(width: 512, height: 512) - let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 160.0, height: 160.0)) - strongSelf.fetchDisposable.set(freeMediaFileResourceInteractiveFetched(account: item.account, fileReference: stickerPackFileReference(animatedStickerFile), resource: animatedStickerFile.resource).start()) - animationNode.setup(source: AnimatedStickerResourceSource(account: item.account, resource: animatedStickerFile.resource), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached) } } diff --git a/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift b/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift index 4e7f9e15d7..2777027bdf 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickerGridItem.swift @@ -132,7 +132,9 @@ final class HorizontalStickerGridItemNode: GridItemNode { func setup(account: Account, item: HorizontalStickerGridItem) { if self.currentState == nil || self.currentState!.0 !== account || self.currentState!.1.file.id != item.file.id { if let dimensions = item.file.dimensions { - if item.file.isAnimatedSticker { + if item.file.isVideoSticker { + + } else if item.file.isAnimatedSticker { let animationNode: AnimatedStickerNode if let currentAnimationNode = self.animationNode { animationNode = currentAnimationNode diff --git a/submodules/TelegramUI/Sources/MediaInputPaneTrendingItem.swift b/submodules/TelegramUI/Sources/MediaInputPaneTrendingItem.swift index 5867512049..6f43518638 100644 --- a/submodules/TelegramUI/Sources/MediaInputPaneTrendingItem.swift +++ b/submodules/TelegramUI/Sources/MediaInputPaneTrendingItem.swift @@ -115,7 +115,9 @@ final class TrendingTopItemNode: ASDisplayNode { self.file = item.file self.itemSize = itemSize - if item.file.isAnimatedSticker { + if item.file.isVideoSticker { + + } else if item.file.isAnimatedSticker { let animationNode: AnimatedStickerNode if let currentAnimationNode = self.animationNode { animationNode = currentAnimationNode diff --git a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift index 9fc677bac6..b9f72ceb4e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/Panes/PeerInfoGroupsInCommonPaneNode.swift @@ -79,7 +79,15 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode { } var status: Signal { - return .single(nil) + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + return self.groupsInCommonContext.state + |> map { state in + if let count = state.count { + return PeerInfoStatusData(text: presentationData.strings.SharedMedia_CommonGroupCount(Int32(count)), isActivity: false) + } else { + return nil + } + } } var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)? diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index f31c8449f0..d1ae497b0f 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -590,6 +590,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen if availablePanes != nil, groupsInCommon != nil, let cachedData = peerView.cachedData as? CachedUserData { if cachedData.commonGroupCount != 0 { availablePanes?.append(.groupsInCommon) + } else if hintGroupInCommon != nil { + availablePanes?.append(.groupsInCommon) } } else if hintGroupInCommon != nil { availablePanes = [.groupsInCommon] diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift index 8d889b81d6..960de1fea6 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoPaneContainerNode.swift @@ -468,6 +468,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat private(set) var currentPaneKey: PeerInfoPaneKey? var pendingSwitchToPaneKey: PeerInfoPaneKey? + var expandOnSwitch = false var currentPane: PeerInfoPaneWrapper? { if let currentPaneKey = self.currentPaneKey { @@ -550,6 +551,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat } } else if strongSelf.pendingSwitchToPaneKey != key { strongSelf.pendingSwitchToPaneKey = key + strongSelf.expandOnSwitch = true if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams { strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring)) @@ -967,7 +969,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat } } if let previousCurrentPaneKey = previousCurrentPaneKey, self.currentPaneKey != previousCurrentPaneKey { - self.currentPaneUpdated?(true) + self.currentPaneUpdated?(self.expandOnSwitch) + self.expandOnSwitch = false } if updateCurrentPaneStatus { self.currentPaneStatusPromise.set(self.currentPane?.node.status ?? .single(nil)) diff --git a/submodules/TelegramUI/Sources/StickerPaneSearchStickerItem.swift b/submodules/TelegramUI/Sources/StickerPaneSearchStickerItem.swift index 3fb947655c..c10c0851c1 100644 --- a/submodules/TelegramUI/Sources/StickerPaneSearchStickerItem.swift +++ b/submodules/TelegramUI/Sources/StickerPaneSearchStickerItem.swift @@ -156,7 +156,9 @@ final class StickerPaneSearchStickerItemNode: GridItemNode { self.textNode.attributedText = NSAttributedString(string: code ?? "", font: textFont, textColor: .black) if let dimensions = stickerItem.file.dimensions { - if stickerItem.file.isAnimatedSticker { + if stickerItem.file.isVideoSticker { + + } else if stickerItem.file.isAnimatedSticker { if self.animationNode == nil { let animationNode = AnimatedStickerNode() animationNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.imageNodeTap(_:)))) diff --git a/submodules/UndoUI/BUILD b/submodules/UndoUI/BUILD index 3887213ddc..44c97c3572 100644 --- a/submodules/UndoUI/BUILD +++ b/submodules/UndoUI/BUILD @@ -26,6 +26,7 @@ swift_library( "//submodules/SlotMachineAnimationNode:SlotMachineAnimationNode", "//submodules/AvatarNode:AvatarNode", "//submodules/AccountContext:AccountContext", + "//submodules/SoftwareVideo:SoftwareVideo", ], visibility = [ "//visibility:public", diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index de84de3069..95f9a9f082 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -4,6 +4,7 @@ import AsyncDisplayKit import Display import SwiftSignalKit import TelegramCore +import Postbox import TelegramPresentationData import TextFormat import Markdown @@ -16,6 +17,7 @@ import AnimationUI import StickerResources import AvatarNode import AccountContext +import SoftwareVideo final class UndoOverlayControllerNode: ViewControllerTracingNode { private let elevatedLayout: Bool @@ -26,6 +28,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { private let iconCheckNode: RadialStatusNode? private let animationNode: AnimationNode? private var animatedStickerNode: AnimatedStickerNode? + private var videoNode: VideoStickerNode? private var slotMachineNode: SlotMachineAnimationNode? private var stillStickerNode: TransformImageNode? private var stickerImageSize: CGSize? @@ -92,6 +95,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = nil self.animatedStickerNode = nil + self.videoNode = nil self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) displayUndo = true self.originalRemainingSeconds = 5 @@ -112,6 +116,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.animationNode = AnimationNode(animation: "anim_infotip", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) } self.animatedStickerNode = nil + self.videoNode = nil self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) displayUndo = undo @@ -122,6 +127,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_archiveswipe", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) displayUndo = undo @@ -132,6 +138,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_infotip", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) displayUndo = undo @@ -142,6 +149,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: isOn ? "anim_autoremove_on" : "anim_autoremove_off", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil if let title = title { self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) } @@ -154,6 +162,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -168,6 +177,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_infotip", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -182,6 +192,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil undoTextColor = UIColor(rgb: 0xff7b74) @@ -200,6 +211,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_linkcopied", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -214,6 +226,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_banned", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -231,6 +244,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = nil self.animatedStickerNode = nil + self.videoNode = nil self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) displayUndo = false self.originalRemainingSeconds = 5 @@ -240,6 +254,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let formattedString = presentationData.strings.ChatList_AddedToFolderTooltip(chatTitle, folderTitle) @@ -257,7 +272,8 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_success", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil - + self.videoNode = nil + self.videoNode = nil let formattedString = presentationData.strings.ChatList_RemovedFromFolderTooltip(chatTitle, folderTitle) let string = NSMutableAttributedString(attributedString: NSAttributedString(string: formattedString.string, font: Font.regular(14.0), textColor: .white)) @@ -274,6 +290,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_payment", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let formattedString = presentationData.strings.Checkout_SuccessfulTooltip(currencyValue, itemTitle) @@ -291,6 +308,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: isHidden ? "anim_message_hidepin" : "anim_message_unpin", colors: ["info1.info1.stroke": self.animationBackgroundColor, "info2.info2.Fill": self.animationBackgroundColor], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -325,6 +343,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_swipereply", colors: [:], scale: 1.0) self.animatedStickerNode = nil + self.videoNode = nil self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) self.textNode.maximumNumberOfLines = 2 @@ -342,23 +361,22 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { enum StickerPackThumbnailItem { case still(TelegramMediaImageRepresentation) - case animated(EngineMediaResource) + case animated(EngineMediaResource, Bool) } var thumbnailItem: StickerPackThumbnailItem? var resourceReference: MediaResourceReference? if let thumbnail = info.thumbnail { - if info.flags.contains(.isAnimated) { - thumbnailItem = .animated(EngineMediaResource(thumbnail.resource)) - resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource) + if info.flags.contains(.isAnimated) || info.flags.contains(.isVideo) { + thumbnailItem = .animated(EngineMediaResource(thumbnail.resource), info.flags.contains(.isVideo)) } else { thumbnailItem = .still(thumbnail) - resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource) } + resourceReference = MediaResourceReference.stickerPackThumbnail(stickerPack: .id(id: info.id.id, accessHash: info.accessHash), resource: thumbnail.resource) } else if let item = topItem { - if item.file.isAnimatedSticker { - thumbnailItem = .animated(EngineMediaResource(item.file.resource)) + if item.file.isAnimatedSticker || item.file.isVideoSticker { + thumbnailItem = .animated(EngineMediaResource(item.file.resource), item.file.isVideoSticker) resourceReference = MediaResourceReference.media(media: .standalone(media: item.file), resource: item.file.resource) } else if let dimensions = item.file.dimensions, let resource = chatMessageStickerResource(file: item.file, small: true) as? TelegramMediaResource { thumbnailItem = .still(TelegramMediaImageRepresentation(dimensions: dimensions, resource: resource, progressiveSizes: [], immediateThumbnailData: nil)) @@ -378,7 +396,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.stickerImageSize = stillImageSize updatedImageSignal = chatMessageStickerPackThumbnail(postbox: context.account.postbox, resource: representation.resource) - case let .animated(resource): + case let .animated(resource, _): self.stickerImageSize = imageBoundingSize updatedImageSignal = chatMessageStickerPackThumbnail(postbox: context.account.postbox, resource: resource._asResource(), animated: true) @@ -416,10 +434,20 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { switch thumbnailItem { case .still: break - case let .animated(resource): - let animatedStickerNode = AnimatedStickerNode() - self.animatedStickerNode = animatedStickerNode - animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: context.account, resource: resource._asResource()), width: 80, height: 80, mode: .cached) + case let .animated(resource, isVideo): + if isVideo { + let videoNode = VideoStickerNode() + self.videoNode = videoNode + + if let resource = resource._asResource() as? TelegramMediaResource { + let dummyFile = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 1), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/webm", size: resource.size ?? 1, attributes: [.Video(duration: 1, size: PixelDimensions(width: 100, height: 100), flags: [])]) + videoNode.update(account: context.account, fileReference: .standalone(media: dummyFile)) + } + } else { + let animatedStickerNode = AnimatedStickerNode() + self.animatedStickerNode = animatedStickerNode + animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: context.account, resource: resource._asResource()), width: 80, height: 80, mode: .cached) + } } } case let .dice(dice, context, text, action): @@ -482,6 +510,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: cancelled ? "anim_proximity_cancelled" : "anim_proximity_set", colors: [:], scale: 0.45) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -500,6 +529,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = nil self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -517,6 +547,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: slowdown ? "anim_voicespeedstop" : "anim_voicespeed", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -532,6 +563,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: savedMessages ? "anim_savedmessages" : "anim_forward", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -547,6 +579,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_gigagroup", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -562,6 +595,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_linkrevoked", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -577,6 +611,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_vcrecord", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -592,6 +627,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_vcflag", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -607,6 +643,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_vcspeak", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -704,6 +741,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_copy", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white) let bold = MarkdownAttributeSet(font: Font.semibold(14.0), textColor: .white) @@ -739,6 +777,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.iconCheckNode = nil self.animationNode = AnimationNode(animation: "anim_inviterequest", colors: [:], scale: 0.066) self.animatedStickerNode = nil + self.videoNode = nil self.titleNode.attributedText = NSAttributedString(string: title, font: Font.semibold(14.0), textColor: .white) self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(14.0), textColor: .white) self.textNode.maximumNumberOfLines = 2 @@ -785,6 +824,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.animationNode.flatMap(self.panelWrapperNode.addSubnode) self.stillStickerNode.flatMap(self.panelWrapperNode.addSubnode) self.animatedStickerNode.flatMap(self.panelWrapperNode.addSubnode) + self.videoNode.flatMap(self.panelWrapperNode.addSubnode) self.slotMachineNode.flatMap(self.panelWrapperNode.addSubnode) self.avatarNode.flatMap(self.panelWrapperNode.addSubnode) self.panelWrapperNode.addSubnode(self.titleNode) @@ -814,6 +854,9 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { self.animatedStickerNode?.started = { [weak self] in self?.stillStickerNode?.isHidden = true } + self.videoNode?.started = { [weak self] in + self?.stillStickerNode?.isHidden = true + } } deinit { @@ -998,12 +1041,20 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { transition.updateFrame(node: stillStickerNode, frame: iconFrame) } - if let animatedStickerNode = self.animatedStickerNode { + if let videoNode = self.videoNode { + videoNode.updateLayout(size: iconFrame.size) + transition.updateFrame(node: videoNode, frame: iconFrame) + } else if let animatedStickerNode = self.animatedStickerNode { animatedStickerNode.updateLayout(size: iconFrame.size) transition.updateFrame(node: animatedStickerNode, frame: iconFrame) } else if let slotMachineNode = self.slotMachineNode { transition.updateFrame(node: slotMachineNode, frame: iconFrame) } + } else if let videoNode = self.videoNode { + let iconSize = CGSize(width: 32.0, height: 32.0) + let iconFrame = CGRect(origin: CGPoint(x: floor((leftInset - iconSize.width) / 2.0), y: floor((contentHeight - iconSize.height) / 2.0)), size: iconSize) + videoNode.updateLayout(size: iconFrame.size) + transition.updateFrame(node: videoNode, frame: iconFrame) } else if let animatedStickerNode = self.animatedStickerNode { let iconSize = CGSize(width: 32.0, height: 32.0) let iconFrame = CGRect(origin: CGPoint(x: floor((leftInset - iconSize.width) / 2.0), y: floor((contentHeight - iconSize.height) / 2.0)), size: iconSize) @@ -1054,6 +1105,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { }) } + self.videoNode?.update(isPlaying: true) self.animatedStickerNode?.visibility = true self.checkTimer()