Various improvements

This commit is contained in:
Ilya Laktyushin 2024-08-10 18:41:17 +02:00
parent 8fdcb91bbc
commit d0156faede
19 changed files with 248 additions and 100 deletions

View File

@ -1045,6 +1045,8 @@ public protocol ChatController: ViewController {
func updateIsScrollingLockedAtTop(isScrollingLockedAtTop: Bool) func updateIsScrollingLockedAtTop(isScrollingLockedAtTop: Bool)
func playShakeAnimation() func playShakeAnimation()
func removeAd(opaqueId: Data)
} }
public protocol ChatMessagePreviewItemNode: AnyObject { public protocol ChatMessagePreviewItemNode: AnyObject {

View File

@ -17,18 +17,32 @@ public final class GalleryControllerActionInteraction {
public let openPeer: (EnginePeer) -> Void public let openPeer: (EnginePeer) -> Void
public let openHashtag: (String?, String) -> Void public let openHashtag: (String?, String) -> Void
public let openBotCommand: (String) -> Void public let openBotCommand: (String) -> Void
public let openAd: (MessageId) -> Void
public let addContact: (String) -> Void public let addContact: (String) -> Void
public let storeMediaPlaybackState: (MessageId, Double?, Double) -> Void public let storeMediaPlaybackState: (MessageId, Double?, Double) -> Void
public let editMedia: (MessageId, [UIView], @escaping () -> Void) -> Void public let editMedia: (MessageId, [UIView], @escaping () -> Void) -> Void
public let updateCanReadHistory: (Bool) -> Void public let updateCanReadHistory: (Bool) -> Void
public init(openUrl: @escaping (String, Bool) -> Void, openUrlIn: @escaping (String) -> Void, openPeerMention: @escaping (String) -> Void, openPeer: @escaping (EnginePeer) -> Void, openHashtag: @escaping (String?, String) -> Void, openBotCommand: @escaping (String) -> Void, addContact: @escaping (String) -> Void, storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void, editMedia: @escaping (MessageId, [UIView], @escaping () -> Void) -> Void, updateCanReadHistory: @escaping (Bool) -> Void) { public init(
openUrl: @escaping (String, Bool) -> Void,
openUrlIn: @escaping (String) -> Void,
openPeerMention: @escaping (String) -> Void,
openPeer: @escaping (EnginePeer) -> Void,
openHashtag: @escaping (String?, String) -> Void,
openBotCommand: @escaping (String) -> Void,
openAd: @escaping (MessageId) -> Void,
addContact: @escaping (String) -> Void,
storeMediaPlaybackState: @escaping (MessageId, Double?, Double) -> Void,
editMedia: @escaping (MessageId, [UIView], @escaping () -> Void) -> Void,
updateCanReadHistory: @escaping (Bool) -> Void)
{
self.openUrl = openUrl self.openUrl = openUrl
self.openUrlIn = openUrlIn self.openUrlIn = openUrlIn
self.openPeerMention = openPeerMention self.openPeerMention = openPeerMention
self.openPeer = openPeer self.openPeer = openPeer
self.openHashtag = openHashtag self.openHashtag = openHashtag
self.openBotCommand = openBotCommand self.openBotCommand = openBotCommand
self.openAd = openAd
self.addContact = addContact self.addContact = addContact
self.storeMediaPlaybackState = storeMediaPlaybackState self.storeMediaPlaybackState = storeMediaPlaybackState
self.editMedia = editMedia self.editMedia = editMedia

View File

@ -69,7 +69,7 @@ public final class AdInfoScreen: ViewController {
self.controller = controller self.controller = controller
self.context = context self.context = context
self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = controller.presentationData
self.titleNode = ImmediateTextNode() self.titleNode = ImmediateTextNode()
self.titleNode.maximumNumberOfLines = 1 self.titleNode.maximumNumberOfLines = 1
@ -211,11 +211,16 @@ public final class AdInfoScreen: ViewController {
} }
private let context: AccountContext private let context: AccountContext
private var presentationData: PresentationData fileprivate var presentationData: PresentationData
public init(context: AccountContext) { public init(context: AccountContext, forceDark: Bool = false) {
self.context = context self.context = context
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
var presentationData = context.sharedContext.currentPresentationData.with { $0 }
if forceDark {
presentationData = presentationData.withUpdated(theme: defaultDarkColorPresentationTheme)
}
self.presentationData = presentationData
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData)) super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: self.presentationData))

View File

@ -18,7 +18,7 @@ public enum PresentationContextType {
public final class PresentationContext { public final class PresentationContext {
private var _view: UIView? private var _view: UIView?
var view: UIView? { public var view: UIView? {
get { get {
return self._view return self._view
} set(value) { } set(value) {
@ -123,6 +123,9 @@ public final class PresentationContext {
return (containerLayout, CGRect(origin: CGPoint(), size: containerLayout.size)) return (containerLayout, CGRect(origin: CGPoint(), size: containerLayout.size))
} }
public init() {
}
public func present(_ controller: ContainableController, on level: PresentationSurfaceLevel, blockInteraction: Bool = false, completion: @escaping () -> Void) { public func present(_ controller: ContainableController, on level: PresentationSurfaceLevel, blockInteraction: Bool = false, completion: @escaping () -> Void) {
let controllerReady = controller.ready.get() let controllerReady = controller.ready.get()
|> filter({ $0 }) |> filter({ $0 })

View File

@ -49,6 +49,9 @@ swift_library(
"//submodules/TooltipUI", "//submodules/TooltipUI",
"//submodules/TelegramNotices", "//submodules/TelegramNotices",
"//submodules/Pasteboard", "//submodules/Pasteboard",
"//submodules/AdUI",
"//submodules/TelegramUI/Components/Ads/AdsInfoScreen",
"//submodules/TelegramUI/Components/Ads/AdsReportScreen",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -29,6 +29,7 @@ import Pasteboard
import Speak import Speak
import TranslateUI import TranslateUI
import TelegramNotices import TelegramNotices
import SolidRoundedButtonNode
private let deleteImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: .white) private let deleteImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionTrash"), color: .white)
private let actionImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionForward"), color: .white) private let actionImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/MessageSelectionForward"), color: .white)
@ -145,6 +146,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
private let textNode: ImmediateTextNodeWithEntities private let textNode: ImmediateTextNodeWithEntities
private var spoilerTextNode: ImmediateTextNodeWithEntities? private var spoilerTextNode: ImmediateTextNodeWithEntities?
private var dustNode: InvisibleInkDustNode? private var dustNode: InvisibleInkDustNode?
private var buttonNode: SolidRoundedButtonNode?
private var textSelectionNode: TextSelectionNode? private var textSelectionNode: TextSelectionNode?
@ -193,6 +195,13 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
var performAction: ((GalleryControllerInteractionTapAction) -> Void)? var performAction: ((GalleryControllerInteractionTapAction) -> Void)?
var openActionOptions: ((GalleryControllerInteractionTapAction, Message) -> Void)? var openActionOptions: ((GalleryControllerInteractionTapAction, Message) -> Void)?
private var isAd: Bool {
if self.currentMessage?.adAttribute != nil {
return true
}
return false
}
var content: ChatItemGalleryFooterContent = .info { var content: ChatItemGalleryFooterContent = .info {
didSet { didSet {
if self.content != oldValue { if self.content != oldValue {
@ -208,8 +217,9 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
self.currentIsPaused = true self.currentIsPaused = true
self.authorNameNode.isHidden = true self.authorNameNode.isHidden = true
self.dateNode.isHidden = true self.dateNode.isHidden = true
self.hasSeekControls = seekable self.hasSeekControls = seekable && !self.isAd
if status == .Local {
if status == .Local && !self.isAd {
self.playbackControlButton.isHidden = false self.playbackControlButton.isHidden = false
self.playPauseIconNode.enqueueState(.play, animated: true) self.playPauseIconNode.enqueueState(.play, animated: true)
} else { } else {
@ -236,16 +246,20 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
self.currentIsPaused = paused self.currentIsPaused = paused
self.authorNameNode.isHidden = true self.authorNameNode.isHidden = true
self.dateNode.isHidden = true self.dateNode.isHidden = true
self.hasSeekControls = seekable
self.playbackControlButton.isHidden = false
let icon: PlayPauseIconNodeState if !self.isAd {
if let wasPlaying = self.wasPlaying { self.playbackControlButton.isHidden = false
icon = wasPlaying ? .pause : .play let icon: PlayPauseIconNodeState
if let wasPlaying = self.wasPlaying {
icon = wasPlaying ? .pause : .play
} else {
icon = paused ? .play : .pause
}
self.playPauseIconNode.enqueueState(icon, animated: true)
self.hasSeekControls = seekable
} else { } else {
icon = paused ? .play : .pause self.hasSeekControls = false
} }
self.playPauseIconNode.enqueueState(icon, animated: true)
self.statusButtonNode.isHidden = true self.statusButtonNode.isHidden = true
self.statusNode.isHidden = true self.statusNode.isHidden = true
} }
@ -829,15 +843,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
if Namespaces.Message.allNonRegular.contains(message.id.namespace) || message.timestamp == 0 { if Namespaces.Message.allNonRegular.contains(message.id.namespace) || message.timestamp == 0 {
displayInfo = false displayInfo = false
} }
if let _ = message.adAttribute { var canFullscreen = false
displayInfo = false
}
var canDelete: Bool var canDelete: Bool
var canShare = !message.containsSecretMedia && !Namespaces.Message.allNonRegular.contains(message.id.namespace) && message.adAttribute == nil var canShare = !message.containsSecretMedia && !Namespaces.Message.allNonRegular.contains(message.id.namespace) && message.adAttribute == nil
var canFullscreen = false
var canEdit = false var canEdit = false
var isImage = false var isImage = false
var isVideo = false var isVideo = false
@ -924,6 +933,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
canDelete = false canDelete = false
} }
if let _ = message.adAttribute {
displayInfo = false
canFullscreen = false
}
var authorNameText: String? var authorNameText: String?
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported), let authorSignature = forwardInfo.authorSignature { if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported), let authorSignature = forwardInfo.authorSignature {
authorNameText = authorSignature authorNameText = authorSignature
@ -1044,6 +1058,22 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
self.actionButton.isHidden = !canShare self.actionButton.isHidden = !canShare
self.editButton.isHidden = !canEdit self.editButton.isHidden = !canEdit
if let adAttribute = message.adAttribute {
if self.buttonNode == nil {
let buttonNode = SolidRoundedButtonNode(title: adAttribute.buttonText, theme: SolidRoundedButtonTheme(backgroundColor: UIColor(rgb: 0xffffff, alpha: 0.15), foregroundColor: UIColor(rgb: 0xffffff)), height: 50.0, cornerRadius: 11.0)
buttonNode.pressed = { [weak self] in
guard let self else {
return
}
self.performAction?(.ad(message.id))
}
self.contentNode.addSubnode(buttonNode)
self.buttonNode = buttonNode
}
} else if let buttonNode = self.buttonNode {
buttonNode.removeFromSupernode()
}
self.requestLayout?(.immediate) self.requestLayout?(.immediate)
} }
} }
@ -1192,6 +1222,17 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
self.scrollWrapperNode.layer.mask?.frame = self.scrollWrapperNode.bounds self.scrollWrapperNode.layer.mask?.frame = self.scrollWrapperNode.bounds
self.scrollWrapperNode.layer.mask?.removeAllAnimations() self.scrollWrapperNode.layer.mask?.removeAllAnimations()
} }
if let buttonNode = self.buttonNode {
let buttonHeight = buttonNode.updateLayout(width: constrainSize.width, transition: transition)
transition.updateFrame(node: buttonNode, frame: CGRect(origin: CGPoint(x: sideInset, y: scrollWrapperNodeFrame.maxY + 8.0), size: CGSize(width: constrainSize.width, height: buttonHeight)))
if let _ = self.scrubberView {
panelHeight += 68.0
} else {
panelHeight += 22.0
}
}
} }
textFrame = CGRect(origin: CGPoint(x: sideInset, y: topInset + textOffset), size: textSize) textFrame = CGRect(origin: CGPoint(x: sideInset, y: topInset + textOffset), size: textSize)
@ -1227,6 +1268,10 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
} }
} }
if let _ = self.buttonNode {
panelHeight -= 44.0
}
let scrubberFrame = CGRect(origin: CGPoint(x: leftInset, y: scrubberY), size: CGSize(width: width - leftInset - rightInset, height: 34.0)) let scrubberFrame = CGRect(origin: CGPoint(x: leftInset, y: scrubberY), size: CGSize(width: width - leftInset - rightInset, height: 34.0))
scrubberView.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .immediate) scrubberView.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .immediate)
transition.updateBounds(layer: scrubberView.layer, bounds: CGRect(origin: CGPoint(), size: scrubberFrame.size)) transition.updateBounds(layer: scrubberView.layer, bounds: CGRect(origin: CGPoint(), size: scrubberFrame.size))
@ -1325,6 +1370,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
self.forwardButton.alpha = self.hasSeekControls ? 1.0 : 0.0 self.forwardButton.alpha = self.hasSeekControls ? 1.0 : 0.0
self.statusNode.alpha = 1.0 self.statusNode.alpha = 1.0
self.playbackControlButton.alpha = 1.0 self.playbackControlButton.alpha = 1.0
self.buttonNode?.alpha = 1.0
self.scrollWrapperNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) self.scrollWrapperNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15)
} }
@ -1349,6 +1395,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
self.forwardButton.alpha = 0.0 self.forwardButton.alpha = 0.0
self.statusNode.alpha = 0.0 self.statusNode.alpha = 0.0
self.playbackControlButton.alpha = 0.0 self.playbackControlButton.alpha = 0.0
self.buttonNode?.alpha = 0.0
self.scrollWrapperNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, completion: { _ in self.scrollWrapperNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, completion: { _ in
completion() completion()
}) })

View File

@ -487,6 +487,7 @@ public enum GalleryControllerInteractionTapAction {
case botCommand(String) case botCommand(String)
case hashtag(String?, String) case hashtag(String?, String)
case timecode(Double, String) case timecode(Double, String)
case ad(MessageId)
} }
public enum GalleryControllerItemNodeAction { public enum GalleryControllerItemNodeAction {
@ -962,6 +963,8 @@ public class GalleryController: ViewController, StandalonePresentableController,
strongSelf.actionInteraction?.openHashtag(peerName, hashtag) strongSelf.actionInteraction?.openHashtag(peerName, hashtag)
case let .timecode(timecode, _): case let .timecode(timecode, _):
strongSelf.galleryNode.pager.centralItemNode()?.processAction(.timecode(timecode)) strongSelf.galleryNode.pager.centralItemNode()?.processAction(.timecode(timecode))
case let .ad(messageId):
strongSelf.actionInteraction?.openAd(messageId)
} }
} }
} }
@ -1217,6 +1220,8 @@ public class GalleryController: ViewController, StandalonePresentableController,
]) ])
]) ])
strongSelf.present(actionSheet, in: .window(.root)) strongSelf.present(actionSheet, in: .window(.root))
case .ad:
break
} }
} }
} }

View File

@ -22,6 +22,9 @@ import UndoUI
import ContextUI import ContextUI
import SaveToCameraRoll import SaveToCameraRoll
import Pasteboard import Pasteboard
import AdUI
import AdsInfoScreen
import AdsReportScreen
enum ChatMediaGalleryThumbnail: Equatable { enum ChatMediaGalleryThumbnail: Equatable {
case image(ImageMediaReference) case image(ImageMediaReference)
@ -545,40 +548,38 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
if adAttribute.canReport { if adAttribute.canReport {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AboutAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AboutAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
if let navigationController = self?.baseNavigationController() as? NavigationController {
// controllerInteraction.navigationController()?.pushViewController(AdsInfoScreen(context: context)) navigationController.pushViewController(AdsInfoScreen(context: context))
}
}))) })))
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_ReportAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_ReportAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.default) f(.default)
let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil) let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|> deliverOnMainQueue).start(next: { result in |> deliverOnMainQueue).start(next: { [weak self] result in
if case let .options(title, options) = result { if case let .options(title, options) = result {
let _ = title if let navigationController = self?.baseNavigationController() as? NavigationController {
let _ = options navigationController.pushViewController(
// controllerInteraction.navigationController()?.pushViewController( AdsReportScreen(
// AdsReportScreen( context: context,
// context: context, peerId: message.id.peerId,
// peerId: message.id.peerId, opaqueId: adAttribute.opaqueId,
// opaqueId: adAttribute.opaqueId, title: title,
// title: title, options: options,
// options: options, forceDark: true,
// completed: { [weak interfaceInteraction] in completed: {
// guard let interfaceInteraction else { if let navigationController = self?.baseNavigationController() as? NavigationController, let chatController = navigationController.viewControllers.last as? ChatController {
// return chatController.removeAd(opaqueId: adAttribute.opaqueId)
// } }
// guard let chatController = interfaceInteraction.chatController() as? ChatControllerImpl else { }
// return )
// } )
// chatController.removeAd(opaqueId: adAttribute.opaqueId) }
// }
// )
// )
} }
}) })
}))) })))
@ -587,40 +588,53 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_RemoveAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_RemoveAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { c, _ in }, iconSource: nil, action: { [weak self] c, _ in
c?.dismiss(completion: { c?.dismiss(completion: {
// controllerInteraction.openNoAdsDemo() var replaceImpl: ((ViewController) -> Void)?
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: true, action: {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: true, dismissed: nil)
replaceImpl?(controller)
}, dismissed: nil)
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
if let navigationController = self?.baseNavigationController() as? NavigationController {
navigationController.pushViewController(controller)
}
}) })
}))) })))
} else { } else {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Info, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Info, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
// controllerInteraction.navigationController()?.pushViewController(AdInfoScreen(context: context)) if let navigationController = self?.baseNavigationController() as? NavigationController {
navigationController.pushViewController(AdInfoScreen(context: context, forceDark: true))
}
}))) })))
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
if !context.isPremium && !premiumConfiguration.isPremiumDisabled { if !context.isPremium && !premiumConfiguration.isPremiumDisabled {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Hide, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Hide, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { c, _ in }, iconSource: nil, action: { [weak self] c, _ in
c?.dismiss(completion: { c?.dismiss(completion: {
var replaceImpl: ((ViewController) -> Void)? var replaceImpl: ((ViewController) -> Void)?
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: false, action: { let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: true, action: {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil) let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: true, dismissed: nil)
replaceImpl?(controller) replaceImpl?(controller)
}, dismissed: nil) }, dismissed: nil)
replaceImpl = { [weak controller] c in replaceImpl = { [weak controller] c in
controller?.replace(with: c) controller?.replace(with: c)
} }
// controllerInteraction.navigationController()?.pushViewController(controller) if let navigationController = self?.baseNavigationController() as? NavigationController {
navigationController.pushViewController(controller)
}
}) })
}))) })))
} }
if !message.text.isEmpty { if !message.text.isEmpty {
actions.append(.separator) actions.append(.separator)
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuCopy, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuCopy, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.actionSheet.primaryTextColor)

View File

@ -24,6 +24,9 @@ import AVKit
import TextFormat import TextFormat
import SliderContextItem import SliderContextItem
import Pasteboard import Pasteboard
import AdUI
import AdsInfoScreen
import AdsReportScreen
public enum UniversalVideoGalleryItemContentInfo { public enum UniversalVideoGalleryItemContentInfo {
case message(Message, Int?) case message(Message, Int?)
@ -1478,6 +1481,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
hasMoreButton = false hasMoreButton = false
} }
if let _ = message.adAttribute {
hasMoreButton = true
}
if hasMoreButton { if hasMoreButton {
let moreMenuItem = UIBarButtonItem(customDisplayNode: self.moreBarButton)! let moreMenuItem = UIBarButtonItem(customDisplayNode: self.moreBarButton)!
moreMenuItem.accessibilityLabel = self.presentationData.strings.Common_More moreMenuItem.accessibilityLabel = self.presentationData.strings.Common_More
@ -2527,40 +2534,38 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
if adAttribute.canReport { if adAttribute.canReport {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AboutAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AboutAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
if let navigationController = self?.baseNavigationController() as? NavigationController {
// controllerInteraction.navigationController()?.pushViewController(AdsInfoScreen(context: context)) navigationController.pushViewController(AdsInfoScreen(context: context, forceDark: true))
}
}))) })))
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_ReportAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_ReportAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.default) f(.default)
let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil) let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|> deliverOnMainQueue).start(next: { result in |> deliverOnMainQueue).start(next: { [weak self] result in
if case let .options(title, options) = result { if case let .options(title, options) = result {
let _ = title if let navigationController = self?.baseNavigationController() as? NavigationController {
let _ = options navigationController.pushViewController(
// controllerInteraction.navigationController()?.pushViewController( AdsReportScreen(
// AdsReportScreen( context: context,
// context: context, peerId: message.id.peerId,
// peerId: message.id.peerId, opaqueId: adAttribute.opaqueId,
// opaqueId: adAttribute.opaqueId, title: title,
// title: title, options: options,
// options: options, forceDark: true,
// completed: { [weak interfaceInteraction] in completed: {
// guard let interfaceInteraction else { if let navigationController = self?.baseNavigationController() as? NavigationController, let chatController = navigationController.viewControllers.last as? ChatController {
// return chatController.removeAd(opaqueId: adAttribute.opaqueId)
// } }
// guard let chatController = interfaceInteraction.chatController() as? ChatControllerImpl else { }
// return )
// } )
// chatController.removeAd(opaqueId: adAttribute.opaqueId) }
// }
// )
// )
} }
}) })
}))) })))
@ -2569,34 +2574,48 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_RemoveAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_RemoveAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { c, _ in }, iconSource: nil, action: { [weak self] c, _ in
c?.dismiss(completion: { c?.dismiss(completion: {
// controllerInteraction.openNoAdsDemo() var replaceImpl: ((ViewController) -> Void)?
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: true, action: {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: true, dismissed: nil)
replaceImpl?(controller)
}, dismissed: nil)
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
if let navigationController = self?.baseNavigationController() as? NavigationController {
navigationController.pushViewController(controller)
}
}) })
}))) })))
} else { } else {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Info, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Info, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { [weak self] _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
// controllerInteraction.navigationController()?.pushViewController(AdInfoScreen(context: context)) if let navigationController = self?.baseNavigationController() as? NavigationController {
navigationController.pushViewController(AdInfoScreen(context: context, forceDark: true))
}
}))) })))
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
if !context.isPremium && !premiumConfiguration.isPremiumDisabled { if !context.isPremium && !premiumConfiguration.isPremiumDisabled {
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Hide, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Hide, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { c, _ in }, iconSource: nil, action: { [weak self] c, _ in
c?.dismiss(completion: { c?.dismiss(completion: {
var replaceImpl: ((ViewController) -> Void)? var replaceImpl: ((ViewController) -> Void)?
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: false, action: { let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: true, action: {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil) let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: true, dismissed: nil)
replaceImpl?(controller) replaceImpl?(controller)
}, dismissed: nil) }, dismissed: nil)
replaceImpl = { [weak controller] c in replaceImpl = { [weak controller] c in
controller?.replace(with: c) controller?.replace(with: c)
} }
// controllerInteraction.navigationController()?.pushViewController(controller) if let navigationController = self?.baseNavigationController() as? NavigationController {
navigationController.pushViewController(controller)
}
}) })
}))) })))
} }

View File

@ -488,7 +488,8 @@ public final class AdsInfoScreen: ViewControllerComponentContainer {
private let context: AccountContext private let context: AccountContext
public init( public init(
context: AccountContext context: AccountContext,
forceDark: Bool = false
) { ) {
self.context = context self.context = context
@ -503,7 +504,7 @@ public final class AdsInfoScreen: ViewControllerComponentContainer {
), ),
navigationBarAppearance: .none, navigationBarAppearance: .none,
statusBarStyle: .ignore, statusBarStyle: .ignore,
theme: .default theme: forceDark ? .dark : .default
) )
self.navigationPresentation = .modal self.navigationPresentation = .modal

View File

@ -573,6 +573,7 @@ public final class AdsReportScreen: ViewControllerComponentContainer {
opaqueId: Data, opaqueId: Data,
title: String, title: String,
options: [ReportAdMessageResult.Option], options: [ReportAdMessageResult.Option],
forceDark: Bool = false,
completed: @escaping () -> Void completed: @escaping () -> Void
) { ) {
self.context = context self.context = context
@ -593,7 +594,7 @@ public final class AdsReportScreen: ViewControllerComponentContainer {
), ),
navigationBarAppearance: .none, navigationBarAppearance: .none,
statusBarStyle: .ignore, statusBarStyle: .ignore,
theme: .default theme: forceDark ? .dark : .default
) )
self.navigationPresentation = .flatModal self.navigationPresentation = .flatModal

View File

@ -5957,7 +5957,16 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
} }
override public func makeProgress() -> Promise<Bool>? { override public func makeProgress() -> Promise<Bool>? {
return self.unlockButtonNode?.makeProgress() if let unlockButtonNode = self.unlockButtonNode {
return unlockButtonNode.makeProgress()
} else {
for contentNode in self.contentNodes {
if let webpageContentNode = contentNode as? ChatMessageWebpageBubbleContentNode {
return webpageContentNode.contentNode.makeProgress()
}
}
}
return nil
} }
override public func targetReactionView(value: MessageReaction.Reaction) -> UIView? { override public func targetReactionView(value: MessageReaction.Reaction) -> UIView? {

View File

@ -5113,6 +5113,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
strongSelf.openHashtag(hashtag, peerName: peerName) strongSelf.openHashtag(hashtag, peerName: peerName)
} }
}, openBotCommand: { _ in }, openBotCommand: { _ in
}, openAd: { _ in
}, addContact: { [weak self] phoneNumber in }, addContact: { [weak self] phoneNumber in
if let strongSelf = self { if let strongSelf = self {
strongSelf.context.sharedContext.openAddContact(context: strongSelf.context, firstName: "", lastName: "", phoneNumber: phoneNumber, label: defaultContactLabel, present: { [weak self] controller, arguments in strongSelf.context.sharedContext.openAddContact(context: strongSelf.context, firstName: "", lastName: "", phoneNumber: phoneNumber, label: defaultContactLabel, present: { [weak self] controller, arguments in

View File

@ -2805,6 +2805,7 @@ final class StorageUsageScreenComponent: Component {
} }
let _ = self let _ = self
}, openBotCommand: { _ in }, openBotCommand: { _ in
}, openAd: { _ in
}, addContact: { _ in }, addContact: { _ in
}, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in }, storeMediaPlaybackState: { [weak self] messageId, timestamp, playbackRate in
guard let self else { guard let self else {

View File

@ -295,6 +295,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let galleryHiddenMesageAndMediaDisposable = MetaDisposable() let galleryHiddenMesageAndMediaDisposable = MetaDisposable()
let temporaryHiddenGalleryMediaDisposable = MetaDisposable() let temporaryHiddenGalleryMediaDisposable = MetaDisposable()
let galleryPresentationContext = PresentationContext()
let chatBackgroundNode: WallpaperBackgroundNode let chatBackgroundNode: WallpaperBackgroundNode
public private(set) var controllerInteraction: ChatControllerInteraction? public private(set) var controllerInteraction: ChatControllerInteraction?
var interfaceInteraction: ChatPanelInterfaceInteraction? var interfaceInteraction: ChatPanelInterfaceInteraction?
@ -1274,7 +1276,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: openChatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: strongSelf.chatLocationContextHolder, message: message, mediaIndex: params.mediaIndex, standalone: standalone, reverseMessageGalleryOrder: false, mode: mode, navigationController: strongSelf.effectiveNavigationController, dismissInput: { return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: openChatLocation, chatFilterTag: chatFilterTag, chatLocationContextHolder: strongSelf.chatLocationContextHolder, message: message, mediaIndex: params.mediaIndex, standalone: standalone, reverseMessageGalleryOrder: false, mode: mode, navigationController: strongSelf.effectiveNavigationController, dismissInput: {
self?.chatDisplayNode.dismissInput() self?.chatDisplayNode.dismissInput()
}, present: { c, a in }, present: { c, a in
self?.present(c, in: .window(.root), with: a, blockInteraction: true) if c is GalleryController {
c.presentationArguments = a
self?.galleryPresentationContext.present(c, on: PresentationSurfaceLevel(rawValue: 0), blockInteraction: true, completion: {})
} else {
self?.present(c, in: .window(.root), with: a, blockInteraction: true)
}
}, transitionNode: { messageId, media, adjustRect in }, transitionNode: { messageId, media, adjustRect in
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
if let strongSelf = self { if let strongSelf = self {
@ -1369,6 +1376,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self { if let strongSelf = self {
strongSelf.controllerInteraction?.sendBotCommand(nil, command) strongSelf.controllerInteraction?.sendBotCommand(nil, command)
} }
}, openAd: { [weak self] messageId in
if let strongSelf = self {
strongSelf.controllerInteraction?.activateAdAction(messageId, nil)
}
}, addContact: { [weak self] phoneNumber in }, addContact: { [weak self] phoneNumber in
if let strongSelf = self { if let strongSelf = self {
strongSelf.controllerInteraction?.addContact(phoneNumber) strongSelf.controllerInteraction?.addContact(phoneNumber)
@ -3857,6 +3868,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let self, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId), let adAttribute = message.adAttribute else { guard let self, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId), let adAttribute = message.adAttribute else {
return return
} }
var progress = progress
if progress == nil {
self.chatDisplayNode.historyNode.forEachVisibleMessageItemNode { itemView in
if itemView.item?.message.id == messageId {
progress = itemView.makeProgress()
}
}
}
self.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId) self.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId)
self.controllerInteraction?.openUrl(ChatControllerInteraction.OpenUrl(url: adAttribute.url, concealed: false, external: true, progress: progress)) self.controllerInteraction?.openUrl(ChatControllerInteraction.OpenUrl(url: adAttribute.url, concealed: false, external: true, progress: progress))
}, openRequestedPeerSelection: { [weak self] messageId, peerType, buttonId, maxQuantity in }, openRequestedPeerSelection: { [weak self] messageId, peerType, buttonId, maxQuantity in
@ -7178,6 +7199,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.loadDisplayNodeImpl() self.loadDisplayNodeImpl()
self.galleryPresentationContext.view = self.view
} }
override public func viewWillAppear(_ animated: Bool) { override public func viewWillAppear(_ animated: Bool) {

View File

@ -2058,6 +2058,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
childrenLayout.intrinsicInsets = UIEdgeInsets(top: listInsets.top, left: listInsets.left, bottom: listInsets.bottom, right: listInsets.right) childrenLayout.intrinsicInsets = UIEdgeInsets(top: listInsets.top, left: listInsets.left, bottom: listInsets.bottom, right: listInsets.right)
} }
self.controller?.presentationContext.containerLayoutUpdated(childrenLayout, transition: transition) self.controller?.presentationContext.containerLayoutUpdated(childrenLayout, transition: transition)
self.controller?.galleryPresentationContext.containerLayoutUpdated(layout, transition: transition)
listViewTransaction(ListViewUpdateSizeAndInsets(size: contentBounds.size, insets: listInsets, scrollIndicatorInsets: listScrollIndicatorInsets, duration: duration, curve: curve, ensureTopInsetForOverlayHighlightedItems: ensureTopInsetForOverlayHighlightedItems), additionalScrollDistance, scrollToTop, { [weak self] in listViewTransaction(ListViewUpdateSizeAndInsets(size: contentBounds.size, insets: listInsets, scrollIndicatorInsets: listScrollIndicatorInsets, duration: duration, curve: curve, ensureTopInsetForOverlayHighlightedItems: ensureTopInsetForOverlayHighlightedItems), additionalScrollDistance, scrollToTop, { [weak self] in
if let strongSelf = self { if let strongSelf = self {

View File

@ -9,7 +9,7 @@ import TelegramPresentationData
import PresentationDataUtils import PresentationDataUtils
import ChatMessageItemView import ChatMessageItemView
extension ChatControllerImpl { public extension ChatControllerImpl {
func removeAd(opaqueId: Data) { func removeAd(opaqueId: Data) {
var foundItemNode: ChatMessageItemView? var foundItemNode: ChatMessageItemView?
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in self.chatDisplayNode.historyNode.forEachItemNode { itemNode in

View File

@ -594,7 +594,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, iconSource: nil, action: { _, f in }, iconSource: nil, action: { _, f in
f(.dismissWithoutContent) f(.dismissWithoutContent)
controllerInteraction.navigationController()?.pushViewController(AdInfoScreen(context: context)) controllerInteraction.navigationController()?.pushViewController(AdInfoScreen(context: context, forceDark: true))
}))) })))
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })

View File

@ -2156,7 +2156,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
} }
return controller return controller
default: default:
return PremiumDemoScreen(context: context, subject: mappedSubject, action: action) return PremiumDemoScreen(context: context, subject: mappedSubject, forceDark: forceDark, action: action)
} }
} }