Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2024-09-25 17:05:24 +04:00
commit a1b70a7070
12 changed files with 261 additions and 177 deletions

View File

@ -568,6 +568,7 @@ public enum PeerInfoControllerMode {
case forumTopic(thread: ChatReplyThreadMessage) case forumTopic(thread: ChatReplyThreadMessage)
case recommendedChannels case recommendedChannels
case myProfile case myProfile
case myProfileGifts
} }
public enum ContactListActionItemInlineIconPosition { public enum ContactListActionItemInlineIconPosition {
@ -975,6 +976,8 @@ public protocol SharedAccountContext: AnyObject {
func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController
func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, forceDark: Bool, action: @escaping () -> Void, dismissed: (() -> Void)?) -> ViewController func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, forceDark: Bool, action: @escaping () -> Void, dismissed: (() -> Void)?) -> ViewController
func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController
func makeStarsGiftController(context: AccountContext, birthdays: [EnginePeer.Id: TelegramBirthday]?, completion: @escaping (([EnginePeer.Id]) -> Void)) -> ViewController
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController

View File

@ -191,7 +191,7 @@ func _internal_keepCachedStarGiftsUpdated(postbox: Postbox, network: Network) ->
func managedStarGiftsUpdates(postbox: Postbox, network: Network) -> Signal<Never, NoError> { func managedStarGiftsUpdates(postbox: Postbox, network: Network) -> Signal<Never, NoError> {
let poll = _internal_keepCachedStarGiftsUpdated(postbox: postbox, network: network) let poll = _internal_keepCachedStarGiftsUpdated(postbox: postbox, network: network)
return (poll |> then(.complete() |> suspendAwareDelay(2.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart return (poll |> then(.complete() |> suspendAwareDelay(1.0 * 60.0 * 60.0, queue: Queue.concurrentDefaultQueue()))) |> restart
} }
func _internal_convertStarGift(account: Account, messageId: EngineMessage.Id) -> Signal<Never, NoError> { func _internal_convertStarGift(account: Account, messageId: EngineMessage.Id) -> Signal<Never, NoError> {

View File

@ -228,7 +228,8 @@ private final class SheetPageContent: CombinedComponent {
component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: strings.ReportAd_Help_URL, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {}) component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: strings.ReportAd_Help_URL, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
} }
)), )),
items: items items: items,
isModal: true
), ),
environment: {}, environment: {},
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude),

View File

@ -332,6 +332,9 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
case let .starGift(gift, convertStars, giftText, entities, nameHidden, savedToProfile, converted): case let .starGift(gift, convertStars, giftText, entities, nameHidden, savedToProfile, converted):
let _ = nameHidden let _ = nameHidden
//TODO:localize //TODO:localize
if !incoming {
buttonTitle = ""
}
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? "" let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
title = "Gift from \(authorName)" title = "Gift from \(authorName)"
if let giftText, !giftText.isEmpty { if let giftText, !giftText.isEmpty {
@ -397,8 +400,11 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: buttonTitle, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: buttonTitle, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
let (ribbonTextLayout, ribbonTextApply) = makeRibbonTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: ribbonTitle, font: Font.semibold(11.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) let (ribbonTextLayout, ribbonTextApply) = makeRibbonTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: ribbonTitle, font: Font.semibold(11.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
giftSize.height = titleLayout.size.height + textSpacing + subtitleLayout.size.height + 212.0 giftSize.height = titleLayout.size.height + textSpacing + subtitleLayout.size.height + 164.0
if !buttonTitle.isEmpty {
giftSize.height += 48.0
}
var labelRects = labelLayout.linesRects() var labelRects = labelLayout.linesRects()
if labelRects.count > 1 { if labelRects.count > 1 {
@ -458,6 +464,9 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
let animationFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - iconSize.width) / 2.0), y: mediaBackgroundFrame.minY - 16.0 + iconOffset), size: iconSize) let animationFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - iconSize.width) / 2.0), y: mediaBackgroundFrame.minY - 16.0 + iconOffset), size: iconSize)
strongSelf.animationNode.frame = animationFrame strongSelf.animationNode.frame = animationFrame
strongSelf.buttonNode.isHidden = buttonTitle.isEmpty
strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty
if strongSelf.item == nil { if strongSelf.item == nil {
strongSelf.animationNode.started = { [weak self] in strongSelf.animationNode.started = { [weak self] in
if let strongSelf = self { if let strongSelf = self {

View File

@ -162,7 +162,7 @@ private final class SheetPageContent: CombinedComponent {
transition: .immediate transition: .immediate
) )
context.add(back context.add(back
.position(CGPoint(x: sideInset + back.size.width / 2.0 - (component.title != nil ? 8.0 : 0.0), y: contentSize.height + back.size.height / 2.0)) .position(CGPoint(x: sideInset + back.size.width / 2.0 - (!component.isFirst ? 8.0 : 0.0), y: contentSize.height + back.size.height / 2.0))
) )
let constrainedTitleWidth = context.availableSize.width - (back.size.width + 16.0) * 2.0 let constrainedTitleWidth = context.availableSize.width - (back.size.width + 16.0) * 2.0
@ -280,7 +280,8 @@ private final class SheetPageContent: CombinedComponent {
maximumNumberOfLines: 0 maximumNumberOfLines: 0
)), )),
footer: footer, footer: footer,
items: items items: items,
isModal: true
), ),
environment: {}, environment: {},
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude), availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: .greatestFiniteMagnitude),
@ -696,12 +697,10 @@ public final class ContentReportScreen: ViewControllerComponentContainer {
switch result { switch result {
case .reported: case .reported:
Queue.mainQueue().after(0.1) {
completed()
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
Queue.mainQueue().after(0.4, { Queue.mainQueue().after(0.4, {
completed()
(navigationController?.viewControllers.last as? ViewController)?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return true }), in: .current) (navigationController?.viewControllers.last as? ViewController)?.present(UndoOverlayController(presentationData: presentationData, content: .emoji(name: "PoliceCar", text: presentationData.strings.Report_Succeed), elevatedLayout: false, action: { _ in return true }), in: .current)
}) })
} }

View File

@ -82,7 +82,10 @@ private final class GiftViewSheetContent: CombinedComponent {
super.init() super.init()
if let arguments = subject.arguments { if let arguments = subject.arguments {
let peerIds: [EnginePeer.Id] = [arguments.peerId, context.account.peerId] var peerIds: [EnginePeer.Id] = [arguments.peerId, context.account.peerId]
if let fromPeerId = arguments.fromPeerId {
peerIds.append(fromPeerId)
}
self.disposable = (context.engine.data.get( self.disposable = (context.engine.data.get(
EngineDataMap( EngineDataMap(
peerIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.Peer in peerIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.Peer in
@ -204,7 +207,11 @@ private final class GiftViewSheetContent: CombinedComponent {
descriptionText = "You converted this gift to \(convertStars) Stars. [More About Stars >]()" descriptionText = "You converted this gift to \(convertStars) Stars. [More About Stars >]()"
} }
} else if let peerId = component.subject.arguments?.peerId, let peer = state.peerMap[peerId] { } else if let peerId = component.subject.arguments?.peerId, let peer = state.peerMap[peerId] {
descriptionText = "\(peer.compactDisplayTitle) can keep this gift in their Profile or convert it to \(convertStars) Stars. [More About Stars >]()" if case .message = component.subject {
descriptionText = "\(peer.compactDisplayTitle) can keep this gift in their Profile or convert it to \(convertStars) Stars. [More About Stars >]()"
} else {
descriptionText = ""
}
} else { } else {
descriptionText = "" descriptionText = ""
} }
@ -273,10 +280,10 @@ private final class GiftViewSheetContent: CombinedComponent {
let tableLinkColor = theme.list.itemAccentColor let tableLinkColor = theme.list.itemAccentColor
var tableItems: [TableComponent.Item] = [] var tableItems: [TableComponent.Item] = []
if let peerId = component.subject.arguments?.peerId, let peer = state.peerMap[peerId] { if let peerId = component.subject.arguments?.fromPeerId, let peer = state.peerMap[peerId] {
tableItems.append(.init( tableItems.append(.init(
id: "to", id: "from",
title: incoming ? strings.Stars_Transaction_From : strings.Stars_Transaction_To, title: strings.Stars_Transaction_From,
component: AnyComponent( component: AnyComponent(
Button( Button(
content: AnyComponent( content: AnyComponent(
@ -287,24 +294,24 @@ private final class GiftViewSheetContent: CombinedComponent {
) )
), ),
action: { action: {
if "".isEmpty { // if "".isEmpty {
component.openPeer(peer) // component.openPeer(peer)
Queue.mainQueue().after(1.0, { // Queue.mainQueue().after(1.0, {
component.cancel(false) // component.cancel(false)
}) // })
} else { // } else {
if let controller = controller() as? GiftViewScreen, let navigationController = controller.navigationController, let chatController = navigationController.viewControllers.first(where: { $0 is ChatController }) as? ChatController { if let controller = controller() as? GiftViewScreen, let navigationController = controller.navigationController, let chatController = navigationController.viewControllers.first(where: { $0 is ChatController }) as? ChatController {
chatController.playShakeAnimation() chatController.playShakeAnimation()
} }
component.cancel(true) component.cancel(true)
} // }
} }
) )
) )
)) ))
} else { } else {
tableItems.append(.init( tableItems.append(.init(
id: "from", id: "from_anon",
title: strings.Stars_Transaction_From, title: strings.Stars_Transaction_From,
component: AnyComponent( component: AnyComponent(
PeerCellComponent( PeerCellComponent(
@ -430,6 +437,8 @@ private final class GiftViewSheetContent: CombinedComponent {
.position(CGPoint(x: context.availableSize.width / 2.0, y: descriptionOrigin + description.size.height / 2.0)) .position(CGPoint(x: context.availableSize.width / 2.0, y: descriptionOrigin + description.size.height / 2.0))
) )
originY += description.size.height + 10.0 originY += description.size.height + 10.0
} else {
originY += 11.0
} }
let amountSpacing: CGFloat = 1.0 let amountSpacing: CGFloat = 1.0
@ -439,7 +448,11 @@ private final class GiftViewSheetContent: CombinedComponent {
var amountOrigin = originY var amountOrigin = originY
if "".isEmpty { if "".isEmpty {
amountOrigin -= descriptionSize.height + 10.0 amountOrigin -= descriptionSize.height + 10.0
originY += amount.size.height + 26.0 if descriptionSize.height > 0 {
originY += amount.size.height + 26.0
} else {
originY += amount.size.height + 2.0
}
} else { } else {
originY += amount.size.height + 20.0 originY += amount.size.height + 20.0
} }
@ -696,14 +709,14 @@ public class GiftViewScreen: ViewControllerComponentContainer {
case message(EngineMessage) case message(EngineMessage)
case profileGift(EnginePeer.Id, ProfileGiftsContext.State.StarGift) case profileGift(EnginePeer.Id, ProfileGiftsContext.State.StarGift)
var arguments: (peerId: EnginePeer.Id, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, convertStars: Int64, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool)? { var arguments: (peerId: EnginePeer.Id, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, convertStars: Int64, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool)? {
switch self { switch self {
case let .message(message): case let .message(message):
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted) = action.action { if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction, case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted) = action.action {
return (message.id.peerId, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, convertStars, text, entities, nameHidden, savedToProfile, converted) return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, convertStars, text, entities, nameHidden, savedToProfile, converted)
} }
case let .profileGift(peerId, gift): case let .profileGift(peerId, gift):
return (peerId, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.convertStars ?? 0, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false) return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.convertStars ?? 0, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false)
} }
return nil return nil
} }
@ -792,9 +805,25 @@ public class GiftViewScreen: ViewControllerComponentContainer {
presentationData: presentationData, presentationData: presentationData,
content: .sticker(context: context, file: arguments.gift.file, loop: false, title: added ? "Gift Saved to Profile" : "Gift Removed from Profile", text: added ? "The gift is now displayed in [your profile]()." : "The gift is no longer displayed in [your profile]().", undoText: nil, customAction: nil), content: .sticker(context: context, file: arguments.gift.file, loop: false, title: added ? "Gift Saved to Profile" : "Gift Removed from Profile", text: added ? "The gift is now displayed in [your profile]()." : "The gift is no longer displayed in [your profile]().", undoText: nil, customAction: nil),
elevatedLayout: lastController is ChatController, elevatedLayout: lastController is ChatController,
action: { action in action: { [weak navigationController] action in
if case .info = action { if case .info = action, let navigationController {
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|> deliverOnMainQueue).start(next: { [weak navigationController] peer in
guard let peer, let navigationController else {
return
}
if let controller = context.sharedContext.makePeerInfoController(
context: context,
updatedPresentationData: nil,
peer: peer._asPeer(),
mode: .myProfileGifts,
avatarInitiallyExpanded: false,
fromChat: false,
requestsContext: nil
) {
navigationController.pushViewController(controller, animated: true)
}
})
} }
return true return true
} }
@ -823,8 +852,12 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|> deliverOnMainQueue).startStandalone() |> deliverOnMainQueue).startStandalone()
} }
self?.dismissAnimated() self?.dismissAnimated()
if let navigationController { if let navigationController {
if let starsContext = context.starsContext {
navigationController.pushViewController(context.sharedContext.makeStarsTransactionsScreen(context: context, starsContext: starsContext), animated: true)
}
Queue.mainQueue().after(0.5) { Queue.mainQueue().after(0.5) {
if let lastController = navigationController.viewControllers.last as? ViewController { if let lastController = navigationController.viewControllers.last as? ViewController {
let resultController = UndoOverlayController( let resultController = UndoOverlayController(

View File

@ -41,17 +41,20 @@ public final class ListSectionContentView: UIView {
public final class Configuration { public final class Configuration {
public let theme: PresentationTheme public let theme: PresentationTheme
public let isModal: Bool
public let displaySeparators: Bool public let displaySeparators: Bool
public let extendsItemHighlightToSection: Bool public let extendsItemHighlightToSection: Bool
public let background: ListSectionComponent.Background public let background: ListSectionComponent.Background
public init( public init(
theme: PresentationTheme, theme: PresentationTheme,
isModal: Bool = false,
displaySeparators: Bool, displaySeparators: Bool,
extendsItemHighlightToSection: Bool, extendsItemHighlightToSection: Bool,
background: ListSectionComponent.Background background: ListSectionComponent.Background
) { ) {
self.theme = theme self.theme = theme
self.isModal = isModal
self.displaySeparators = displaySeparators self.displaySeparators = displaySeparators
self.extendsItemHighlightToSection = extendsItemHighlightToSection self.extendsItemHighlightToSection = extendsItemHighlightToSection
self.background = background self.background = background
@ -116,7 +119,7 @@ public final class ListSectionContentView: UIView {
backgroundColor = configuration.theme.list.itemHighlightedBackgroundColor backgroundColor = configuration.theme.list.itemHighlightedBackgroundColor
} else { } else {
transition = .easeInOut(duration: 0.2) transition = .easeInOut(duration: 0.2)
backgroundColor = configuration.theme.list.itemBlocksBackgroundColor backgroundColor = configuration.isModal ? configuration.theme.list.itemModalBlocksBackgroundColor : configuration.theme.list.itemBlocksBackgroundColor
} }
self.externalContentBackgroundView.updateColor(color: backgroundColor, transition: transition) self.externalContentBackgroundView.updateColor(color: backgroundColor, transition: transition)
@ -144,7 +147,7 @@ public final class ListSectionContentView: UIView {
if self.highlightedItemId != nil && configuration.extendsItemHighlightToSection { if self.highlightedItemId != nil && configuration.extendsItemHighlightToSection {
backgroundColor = configuration.theme.list.itemHighlightedBackgroundColor backgroundColor = configuration.theme.list.itemHighlightedBackgroundColor
} else { } else {
backgroundColor = configuration.theme.list.itemBlocksBackgroundColor backgroundColor = configuration.isModal ? configuration.theme.list.itemModalBlocksBackgroundColor : configuration.theme.list.itemBlocksBackgroundColor
} }
self.externalContentBackgroundView.updateColor(color: backgroundColor, transition: transition) self.externalContentBackgroundView.updateColor(color: backgroundColor, transition: transition)
@ -305,6 +308,7 @@ public final class ListSectionComponent: Component {
public let header: AnyComponent<Empty>? public let header: AnyComponent<Empty>?
public let footer: AnyComponent<Empty>? public let footer: AnyComponent<Empty>?
public let items: [AnyComponentWithIdentity<Empty>] public let items: [AnyComponentWithIdentity<Empty>]
public let isModal: Bool
public let displaySeparators: Bool public let displaySeparators: Bool
public let extendsItemHighlightToSection: Bool public let extendsItemHighlightToSection: Bool
@ -314,6 +318,7 @@ public final class ListSectionComponent: Component {
header: AnyComponent<Empty>?, header: AnyComponent<Empty>?,
footer: AnyComponent<Empty>?, footer: AnyComponent<Empty>?,
items: [AnyComponentWithIdentity<Empty>], items: [AnyComponentWithIdentity<Empty>],
isModal: Bool = false,
displaySeparators: Bool = true, displaySeparators: Bool = true,
extendsItemHighlightToSection: Bool = false extendsItemHighlightToSection: Bool = false
) { ) {
@ -322,6 +327,7 @@ public final class ListSectionComponent: Component {
self.header = header self.header = header
self.footer = footer self.footer = footer
self.items = items self.items = items
self.isModal = isModal
self.displaySeparators = displaySeparators self.displaySeparators = displaySeparators
self.extendsItemHighlightToSection = extendsItemHighlightToSection self.extendsItemHighlightToSection = extendsItemHighlightToSection
} }
@ -342,6 +348,9 @@ public final class ListSectionComponent: Component {
if lhs.items != rhs.items { if lhs.items != rhs.items {
return false return false
} }
if lhs.isModal != rhs.isModal {
return false
}
if lhs.displaySeparators != rhs.displaySeparators { if lhs.displaySeparators != rhs.displaySeparators {
return false return false
} }
@ -448,6 +457,7 @@ public final class ListSectionComponent: Component {
let contentResult = self.contentView.update( let contentResult = self.contentView.update(
configuration: ListSectionContentView.Configuration( configuration: ListSectionContentView.Configuration(
theme: component.theme, theme: component.theme,
isModal: component.isModal,
displaySeparators: component.displaySeparators, displaySeparators: component.displaySeparators,
extendsItemHighlightToSection: component.extendsItemHighlightToSection, extendsItemHighlightToSection: component.extendsItemHighlightToSection,
background: component.background background: component.background
@ -522,17 +532,20 @@ public final class ListSubSectionComponent: Component {
public let theme: PresentationTheme public let theme: PresentationTheme
public let leftInset: CGFloat public let leftInset: CGFloat
public let items: [AnyComponentWithIdentity<Empty>] public let items: [AnyComponentWithIdentity<Empty>]
public let isModal: Bool
public let displaySeparators: Bool public let displaySeparators: Bool
public init( public init(
theme: PresentationTheme, theme: PresentationTheme,
leftInset: CGFloat, leftInset: CGFloat,
items: [AnyComponentWithIdentity<Empty>], items: [AnyComponentWithIdentity<Empty>],
isModal: Bool = false,
displaySeparators: Bool = true displaySeparators: Bool = true
) { ) {
self.theme = theme self.theme = theme
self.leftInset = leftInset self.leftInset = leftInset
self.items = items self.items = items
self.isModal = isModal
self.displaySeparators = displaySeparators self.displaySeparators = displaySeparators
} }
@ -546,6 +559,9 @@ public final class ListSubSectionComponent: Component {
if lhs.items != rhs.items { if lhs.items != rhs.items {
return false return false
} }
if lhs.isModal != rhs.isModal {
return false
}
if lhs.displaySeparators != rhs.displaySeparators { if lhs.displaySeparators != rhs.displaySeparators {
return false return false
} }
@ -615,6 +631,7 @@ public final class ListSubSectionComponent: Component {
let contentResult = self.contentView.update( let contentResult = self.contentView.update(
configuration: ListSectionContentView.Configuration( configuration: ListSectionContentView.Configuration(
theme: component.theme, theme: component.theme,
isModal: component.isModal,
displaySeparators: component.displaySeparators, displaySeparators: component.displaySeparators,
extendsItemHighlightToSection: false, extendsItemHighlightToSection: false,
background: .none(clipped: false) background: .none(clipped: false)

View File

@ -8250,9 +8250,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
private func openReport(type: PeerInfoReportType, contextController: ContextControllerProtocol?, backAction: ((ContextControllerProtocol) -> Void)?) { private func openReport(type: PeerInfoReportType, contextController: ContextControllerProtocol?, backAction: ((ContextControllerProtocol) -> Void)?) {
guard let controller = self.controller else {
return
}
self.view.endEditing(true) self.view.endEditing(true)
switch type { switch type {
@ -8291,20 +8288,28 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
]) ])
self.controller?.present(actionSheet, in: .window(.root)) self.controller?.present(actionSheet, in: .window(.root))
default: default:
let options: [PeerReportOption] contextController?.dismiss()
if case .user = type {
options = [.spam, .fake, .violence, .pornography, .childAbuse]
} else {
options = [.spam, .fake, .violence, .pornography, .childAbuse, .copyright, .other]
}
presentPeerReportOptions(context: self.context, parent: controller, contextController: contextController, backAction: backAction, subject: .peer(self.peerId), options: options, passthrough: true, completion: { [weak self] reason, _ in self.context.sharedContext.makeContentReportScreen(context: self.context, subject: .peer(self.peerId), forceDark: false, present: { [weak self] controller in
if let reason = reason { self?.controller?.push(controller)
DispatchQueue.main.async { }, completion: {
self?.openChatForReporting(reason)
}
}
}) })
// let options: [PeerReportOption]
// if case .user = type {
// options = [.spam, .fake, .violence, .pornography, .childAbuse]
// } else {
// options = [.spam, .fake, .violence, .pornography, .childAbuse, .copyright, .other]
// }
//
// presentPeerReportOptions(context: self.context, parent: controller, contextController: contextController, backAction: backAction, subject: .peer(self.peerId), options: options, passthrough: true, completion: { [weak self] reason, _ in
// if let reason = reason {
// DispatchQueue.main.async {
// self?.openChatForReporting(reason)
// }
// }
// })
} }
} }
@ -11645,13 +11650,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
strongSelf.view.endEditing(true) strongSelf.view.endEditing(true)
strongSelf.controller?.present(peerReportOptionsController(context: strongSelf.context, subject: .messages(Array(messageIds).sorted()), passthrough: false, present: { c, a in strongSelf.context.sharedContext.makeContentReportScreen(context: strongSelf.context, subject: .messages(Array(messageIds).sorted()), forceDark: false, present: { [weak self] controller in
self?.controller?.present(c, in: .window(.root), with: a) self?.controller?.push(controller)
}, push: { c in }, completion: {})
self?.controller?.push(c)
}, completion: { _, _ in }), in: .window(.root))
}, displayCopyProtectionTip: { [weak self] node, save in }, displayCopyProtectionTip: { [weak self] node, save in
if let strongSelf = self, let peer = strongSelf.data?.peer, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty { if let strongSelf = self, let peer = strongSelf.data?.peer, let messageIds = strongSelf.state.selectedMessageIds, !messageIds.isEmpty {
let _ = (strongSelf.context.engine.data.get(EngineDataMap( let _ = (strongSelf.context.engine.data.get(EngineDataMap(
@ -12284,6 +12285,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
private weak var requestsContext: PeerInvitationImportersContext? private weak var requestsContext: PeerInvitationImportersContext?
fileprivate let starsContext: StarsContext? fileprivate let starsContext: StarsContext?
private let switchToRecommendedChannels: Bool private let switchToRecommendedChannels: Bool
private let switchToGifts: Bool
private let chatLocation: ChatLocation private let chatLocation: ChatLocation
private let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil) private let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
@ -12340,7 +12342,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)? private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, isMyProfile: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil, switchToRecommendedChannels: Bool = false) { public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, isMyProfile: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil, switchToRecommendedChannels: Bool = false, switchToGifts: Bool = false) {
self.context = context self.context = context
self.updatedPresentationData = updatedPresentationData self.updatedPresentationData = updatedPresentationData
self.peerId = peerId self.peerId = peerId
@ -12354,6 +12356,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
self.hintGroupInCommon = hintGroupInCommon self.hintGroupInCommon = hintGroupInCommon
self.requestsContext = requestsContext self.requestsContext = requestsContext
self.switchToRecommendedChannels = switchToRecommendedChannels self.switchToRecommendedChannels = switchToRecommendedChannels
self.switchToGifts = switchToGifts
if let forumTopicThread = forumTopicThread { if let forumTopicThread = forumTopicThread {
self.chatLocation = .replyThread(message: forumTopicThread) self.chatLocation = .replyThread(message: forumTopicThread)
@ -12694,7 +12697,13 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
} }
override public func loadDisplayNode() { override public func loadDisplayNode() {
self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded, isOpenedFromChat: self.isOpenedFromChat, nearbyPeerDistance: self.nearbyPeerDistance, reactionSourceMessageId: self.reactionSourceMessageId, callMessages: self.callMessages, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: self.hintGroupInCommon, requestsContext: self.requestsContext, starsContext: self.starsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, initialPaneKey: self.switchToRecommendedChannels ? .recommended : nil) var initialPaneKey: PeerInfoPaneKey?
if self.switchToRecommendedChannels {
initialPaneKey = .recommended
} else if self.switchToGifts {
initialPaneKey = .gifts
}
self.displayNode = PeerInfoScreenNode(controller: self, context: self.context, peerId: self.peerId, avatarInitiallyExpanded: self.avatarInitiallyExpanded, isOpenedFromChat: self.isOpenedFromChat, nearbyPeerDistance: self.nearbyPeerDistance, reactionSourceMessageId: self.reactionSourceMessageId, callMessages: self.callMessages, isSettings: self.isSettings, isMyProfile: self.isMyProfile, hintGroupInCommon: self.hintGroupInCommon, requestsContext: self.requestsContext, starsContext: self.starsContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, initialPaneKey: initialPaneKey)
self.controllerNode.accountsAndPeers.set(self.accountsAndPeers.get() |> map { $0.1 }) self.controllerNode.accountsAndPeers.set(self.accountsAndPeers.get() |> map { $0.1 })
self.controllerNode.activeSessionsContextAndCount.set(self.activeSessionsContextAndCount.get()) self.controllerNode.activeSessionsContextAndCount.set(self.activeSessionsContextAndCount.get())
self.cachedDataPromise.set(self.controllerNode.cachedDataPromise.get()) self.cachedDataPromise.set(self.controllerNode.cachedDataPromise.get())

View File

@ -87,6 +87,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
guard let self else { guard let self else {
return return
} }
let isFirstTime = starsProducts == nil
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
self.statusPromise.set(.single(PeerInfoStatusData(text: presentationData.strings.SharedMedia_GiftCount(state.count ?? 0), isActivity: true, key: .gifts))) self.statusPromise.set(.single(PeerInfoStatusData(text: presentationData.strings.SharedMedia_GiftCount(state.count ?? 0), isActivity: true, key: .gifts)))
self.starsProducts = state.gifts self.starsProducts = state.gifts
@ -96,7 +97,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.ready.set(.single(true)) self.ready.set(.single(true))
} }
self.updateScrolling() self.updateScrolling(transition: isFirstTime ? .immediate : .easeInOut(duration: 0.25))
}) })
} }
@ -119,10 +120,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
public func scrollViewDidScroll(_ scrollView: UIScrollView) { public func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.updateScrolling() self.updateScrolling(transition: .immediate)
} }
func updateScrolling() { func updateScrolling(transition: ComponentTransition) {
if let starsProducts = self.starsProducts, let params = self.currentParams { if let starsProducts = self.starsProducts, let params = self.currentParams {
let optionSpacing: CGFloat = 10.0 let optionSpacing: CGFloat = 10.0
let sideInset = params.sideInset + 16.0 let sideInset = params.sideInset + 16.0
@ -140,13 +141,14 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
let itemId = AnyHashable(product.date) let itemId = AnyHashable(product.date)
validIds.append(itemId) validIds.append(itemId)
let itemTransition = ComponentTransition.immediate var itemTransition = transition
let visibleItem: ComponentView<Empty> let visibleItem: ComponentView<Empty>
if let current = self.starsItems[itemId] { if let current = self.starsItems[itemId] {
visibleItem = current visibleItem = current
} else { } else {
visibleItem = ComponentView() visibleItem = ComponentView()
self.starsItems[itemId] = visibleItem self.starsItems[itemId] = visibleItem
itemTransition = .immediate
} }
var isVisible = false var isVisible = false
@ -221,6 +223,26 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
} }
var removeIds: [AnyHashable] = []
for (id, item) in self.starsItems {
if !validIds.contains(id) {
removeIds.append(id)
if let itemView = item.view {
if !transition.animation.isImmediate {
itemView.layer.animateScale(from: 1.0, to: 0.01, duration: 0.25, removeOnCompletion: false)
itemView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
itemView.removeFromSuperview()
})
} else {
itemView.removeFromSuperview()
}
}
}
}
for id in removeIds {
self.starsItems.removeValue(forKey: id)
}
var contentHeight = ceil(CGFloat(starsProducts.count) / 3.0) * starsOptionSize.height + 60.0 + 16.0 var contentHeight = ceil(CGFloat(starsProducts.count) / 3.0) * starsOptionSize.height + 60.0 + 16.0
if self.peerId == self.context.account.peerId { if self.peerId == self.context.account.peerId {
@ -354,7 +376,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
self.scrollNode.view.isScrollEnabled = !isScrollingLockedAtTop self.scrollNode.view.isScrollEnabled = !isScrollingLockedAtTop
self.updateScrolling() self.updateScrolling(transition: ComponentTransition(transition))
} }
public func findLoadedMessage(id: MessageId) -> Message? { public func findLoadedMessage(id: MessageId) -> Message? {

View File

@ -1037,7 +1037,7 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
guard let self else { guard let self else {
return return
} }
let controller = self.context.sharedContext.makePremiumGiftController(context: self.context, source: .stars(birthdays), completion: { [weak self] peerIds in let controller = self.context.sharedContext.makeStarsGiftController(context: self.context, birthdays: birthdays, completion: { [weak self] peerIds in
guard let self, let peerId = peerIds.first else { guard let self, let peerId = peerIds.first else {
return return
} }

View File

@ -741,6 +741,9 @@ public final class TextFieldComponent: Component {
} }
self.insertText(NSAttributedString(string: insertString)) self.insertText(NSAttributedString(string: insertString))
} else if (range.length == 0 && text == "\n"), let returnKeyAction = component.returnKeyAction {
returnKeyAction()
return false
} }
return false return false
} }

View File

@ -2204,6 +2204,75 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return PremiumLimitScreen(context: context, subject: mappedSubject, count: count, forceDark: forceDark, cancel: cancel, action: action) return PremiumLimitScreen(context: context, subject: mappedSubject, count: count, forceDark: forceDark, cancel: cancel, action: action)
} }
public func makeStarsGiftController(context: AccountContext, birthdays: [EnginePeer.Id: TelegramBirthday]?, completion: @escaping (([EnginePeer.Id]) -> Void)) -> ViewController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var presentBirthdayPickerImpl: (() -> Void)?
let starsMode: ContactSelectionControllerMode = .starsGifting(birthdays: birthdays, hasActions: false)
let contactOptions: Signal<[ContactListAdditionalOption], NoError> = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Birthday(id: context.account.peerId))
|> map { birthday in
if birthday == nil {
return [ContactListAdditionalOption(
title: presentationData.strings.Premium_Gift_ContactSelection_AddBirthday,
icon: .generic(UIImage(bundleImageName: "Contact List/AddBirthdayIcon")!),
action: {
presentBirthdayPickerImpl?()
},
clearHighlightAutomatically: true
)]
} else {
return []
}
}
|> deliverOnMainQueue
let options = Promise<[StarsGiftOption]>()
options.set(context.engine.payments.starsGiftOptions(peerId: nil))
let controller = context.sharedContext.makeContactSelectionController(ContactSelectionControllerParams(
context: context,
mode: starsMode,
autoDismiss: false,
title: { strings in return strings.Stars_Purchase_GiftStars },
options: contactOptions
))
let _ = (controller.result
|> deliverOnMainQueue).start(next: { result in
if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer {
completion([peer.id])
}
})
presentBirthdayPickerImpl = { [weak controller] in
guard let controller else {
return
}
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .setupBirthday).startStandalone()
let settingsPromise: Promise<AccountPrivacySettings?>
if let rootController = context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface, let current = rootController.getPrivacySettings() {
settingsPromise = current
} else {
settingsPromise = Promise()
settingsPromise.set(.single(nil) |> then(context.engine.privacy.requestAccountPrivacySettings() |> map(Optional.init)))
}
let birthdayController = BirthdayPickerScreen(context: context, settings: settingsPromise.get(), openSettings: {
context.sharedContext.makeBirthdayPrivacyController(context: context, settings: settingsPromise, openedFromBirthdayScreen: true, present: { [weak controller] c in
controller?.push(c)
})
}, completion: { [weak controller] value in
let _ = context.engine.accountData.updateBirthday(birthday: value).startStandalone()
controller?.present(UndoOverlayController(presentationData: presentationData, content: .actionSucceeded(title: nil, text: presentationData.strings.Birthday_Added, cancel: nil, destructive: false), elevatedLayout: false, action: { _ in
return true
}), in: .current)
})
controller.push(birthdayController)
}
return controller
}
public func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController { public func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 } let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -2247,122 +2316,37 @@ public final class SharedAccountContextImpl: SharedAccountContext {
var sendMessageImpl: ((EnginePeer) -> Void)? var sendMessageImpl: ((EnginePeer) -> Void)?
//TODO:localize //TODO:localize
let controller: ViewController let options = Promise<[PremiumGiftCodeOption]>()
// if case .stars = source { options.set(context.engine.payments.premiumGiftCodeOptions(peerId: nil))
// let options = Promise<[StarsGiftOption]>() let controller = context.sharedContext.makeContactSelectionController(ContactSelectionControllerParams(
// options.set(context.engine.payments.starsGiftOptions(peerId: nil)) context: context,
let options = Promise<[PremiumGiftCodeOption]>() mode: starsMode,
options.set(context.engine.payments.premiumGiftCodeOptions(peerId: nil)) autoDismiss: false,
let contactsController = context.sharedContext.makeContactSelectionController(ContactSelectionControllerParams( title: { strings in return "Gift Premium or Stars" },
context: context, options: contactOptions,
mode: starsMode, openProfile: { peer in
autoDismiss: false, openProfileImpl?(peer)
title: { strings in return "Gift Premium or Stars" }, },
options: contactOptions, sendMessage: { peer in
openProfile: { peer in sendMessageImpl?(peer)
openProfileImpl?(peer) }
}, ))
sendMessage: { peer in let _ = combineLatest(queue: Queue.mainQueue(), contactsController.result, options.get())
sendMessageImpl?(peer) .startStandalone(next: { [weak controller] result, options in
} if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext {
)) let premiumOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
let _ = combineLatest(queue: Queue.mainQueue(), contactsController.result, options.get()) let giftController = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumOptions)
.startStandalone(next: { [weak contactsController] result, options in giftController.navigationPresentation = .modal
if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext { controller?.push(giftController)
let premiumOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
let giftController = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peer.id, premiumOptions: premiumOptions)
giftController.navigationPresentation = .modal
contactsController?.push(giftController)
// completion?([peer.id]) // completion?([peer.id])
if case .chatList = source, let _ = currentBirthdays { if case .chatList = source, let _ = currentBirthdays {
let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone() let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone()
}
} }
}) }
controller = contactsController })
// } else {
// let options = Promise<[PremiumGiftCodeOption]>()
// options.set(context.engine.payments.premiumGiftCodeOptions(peerId: nil))
// let contactsController = context.sharedContext.makeContactMultiselectionController(
// ContactMultiselectionControllerParams(
// context: context,
// mode: mode,
// options: contactOptions,
// isPeerEnabled: { peer in
// if case let .user(user) = peer, user.botInfo == nil && !peer.isService && !user.flags.contains(.isSupport) {
// return true
// } else {
// return false
// }
// },
// limit: limit,
// reachedLimit: { limit in
// reachedLimitImpl?(limit)
// },
// openProfile: { peer in
// openProfileImpl?(peer)
// },
// sendMessage: { peer in
// sendMessageImpl?(peer)
// }
// )
// )
// let _ = combineLatest(queue: Queue.mainQueue(), contactsController.result, options.get())
// .startStandalone(next: { [weak contactsController] result, options in
// guard let controller = contactsController else {
// return
// }
// var peerIds: [PeerId] = []
// if case let .result(peerIdsValue, _) = result {
// peerIds = peerIdsValue.compactMap({ peerId in
// if case let .peer(peerId) = peerId {
// return peerId
// } else {
// return nil
// }
// })
// }
// guard !peerIds.isEmpty else {
// return
// }
//
// let mappedOptions = options.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
// var pushImpl: ((ViewController) -> Void)?
// var filterImpl: (() -> Void)?
// let giftController = PremiumGiftScreen(context: context, peerIds: peerIds, options: mappedOptions, source: source, pushController: { c in
// pushImpl?(c)
// }, completion: {
// filterImpl?()
//
// if case .chatList = source, let _ = currentBirthdays {
// let _ = context.engine.notices.dismissServerProvidedSuggestion(suggestion: .todayBirthdays).startStandalone()
// }
// })
// pushImpl = { [weak giftController] c in
// giftController?.push(c)
// }
// filterImpl = { [weak giftController] in
// if let navigationController = giftController?.navigationController as? NavigationController {
// var controllers = navigationController.viewControllers
// controllers = controllers.filter { !($0 is ContactMultiselectionController) && !($0 is PremiumGiftScreen) }
// navigationController.setViewControllers(controllers, animated: true)
// }
// }
// controller.push(giftController)
// })
// controller = contactsController
// }
// reachedLimitImpl = { [weak controller] limit in
// guard let controller else {
// return
// }
// HapticFeedback().error()
// controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.Premium_Gift_ContactSelection_MaximumReached("\(limit)").string, timeout: nil, customUndoText: nil), elevatedLayout: true, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
// }
sendMessageImpl = { [weak self, weak controller] peer in sendMessageImpl = { [weak self, weak controller] peer in
guard let self, let controller, let navigationController = controller.navigationController as? NavigationController else { guard let self, let controller, let navigationController = controller.navigationController as? NavigationController else {
return return
@ -2864,6 +2848,7 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation
var hintGroupInCommon: PeerId? var hintGroupInCommon: PeerId?
var forumTopicThread: ChatReplyThreadMessage? var forumTopicThread: ChatReplyThreadMessage?
var isMyProfile = false var isMyProfile = false
var switchToGifts = false
switch mode { switch mode {
case let .nearbyPeer(distance): case let .nearbyPeer(distance):
@ -2880,10 +2865,13 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation
forumTopicThread = thread forumTopicThread = thread
case .myProfile: case .myProfile:
isMyProfile = true isMyProfile = true
case .myProfileGifts:
isMyProfile = true
switchToGifts = true
default: default:
break break
} }
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nearbyPeerDistance, reactionSourceMessageId: reactionSourceMessageId, callMessages: callMessages, isMyProfile: isMyProfile, hintGroupInCommon: hintGroupInCommon, forumTopicThread: forumTopicThread) return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nearbyPeerDistance, reactionSourceMessageId: reactionSourceMessageId, callMessages: callMessages, isMyProfile: isMyProfile, hintGroupInCommon: hintGroupInCommon, forumTopicThread: forumTopicThread, switchToGifts: switchToGifts)
} else if peer is TelegramSecretChat { } else if peer is TelegramSecretChat {
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: []) return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [])
} }