diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 00df14bac7..a47e1d7ea5 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -329,8 +329,10 @@ public enum ResolvedUrl { case collectible(gift: StarGift.UniqueGift?) case messageLink(link: TelegramResolvedMessageLink?) case stars + case ton case shareStory(Int64) case storyFolder(peerId: PeerId, id: Int64) + case giftCollection(peerId: PeerId, id: Int64) } public enum ResolveUrlResult { @@ -669,6 +671,7 @@ public enum PeerInfoControllerMode { case groupsInCommon case monoforum(EnginePeer.Id) case storyAlbum(id: Int64) + case giftCollection(id: Int64) } public enum ContactListActionItemInlineIconPosition { diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 59c01ae2cf..bd6c07b708 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -1204,6 +1204,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[555358088] = { return Api.WebPage.parse_webPageEmpty($0) } dict[1930545681] = { return Api.WebPage.parse_webPageNotModified($0) } dict[-1328464313] = { return Api.WebPage.parse_webPagePending($0) } + dict[835375875] = { return Api.WebPageAttribute.parse_webPageAttributeStarGiftCollection($0) } dict[1355547603] = { return Api.WebPageAttribute.parse_webPageAttributeStickerSet($0) } dict[781501415] = { return Api.WebPageAttribute.parse_webPageAttributeStory($0) } dict[1421174295] = { return Api.WebPageAttribute.parse_webPageAttributeTheme($0) } diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index 921f3b6b5f..cc6313ea7d 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -1,5 +1,6 @@ public extension Api { indirect enum WebPageAttribute: TypeConstructorDescription { + case webPageAttributeStarGiftCollection(icons: [Api.Document]) case webPageAttributeStickerSet(flags: Int32, stickers: [Api.Document]) case webPageAttributeStory(flags: Int32, peer: Api.Peer, id: Int32, story: Api.StoryItem?) case webPageAttributeTheme(flags: Int32, documents: [Api.Document]?, settings: Api.ThemeSettings?) @@ -7,6 +8,16 @@ public extension Api { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { + case .webPageAttributeStarGiftCollection(let icons): + if boxed { + buffer.appendInt32(835375875) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(icons.count)) + for item in icons { + item.serialize(buffer, true) + } + break case .webPageAttributeStickerSet(let flags, let stickers): if boxed { buffer.appendInt32(1355547603) @@ -50,6 +61,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { + case .webPageAttributeStarGiftCollection(let icons): + return ("webPageAttributeStarGiftCollection", [("icons", icons as Any)]) case .webPageAttributeStickerSet(let flags, let stickers): return ("webPageAttributeStickerSet", [("flags", flags as Any), ("stickers", stickers as Any)]) case .webPageAttributeStory(let flags, let peer, let id, let story): @@ -61,6 +74,19 @@ public extension Api { } } + public static func parse_webPageAttributeStarGiftCollection(_ reader: BufferReader) -> WebPageAttribute? { + var _1: [Api.Document]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.WebPageAttribute.webPageAttributeStarGiftCollection(icons: _1!) + } + else { + return nil + } + } public static func parse_webPageAttributeStickerSet(_ reader: BufferReader) -> WebPageAttribute? { var _1: Int32? _1 = reader.readInt32() @@ -1328,39 +1354,3 @@ public extension Api.account { } } -public extension Api.account { - enum Takeout: TypeConstructorDescription { - case takeout(id: Int64) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .takeout(let id): - if boxed { - buffer.appendInt32(1304052993) - } - serializeInt64(id, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .takeout(let id): - return ("takeout", [("id", id as Any)]) - } - } - - public static func parse_takeout(_ reader: BufferReader) -> Takeout? { - var _1: Int64? - _1 = reader.readInt64() - let _c1 = _1 != nil - if _c1 { - return Api.account.Takeout.takeout(id: _1!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index fe6078fe6d..0d3383bf64 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -1,3 +1,39 @@ +public extension Api.account { + enum Takeout: TypeConstructorDescription { + case takeout(id: Int64) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .takeout(let id): + if boxed { + buffer.appendInt32(1304052993) + } + serializeInt64(id, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .takeout(let id): + return ("takeout", [("id", id as Any)]) + } + } + + public static func parse_takeout(_ reader: BufferReader) -> Takeout? { + var _1: Int64? + _1 = reader.readInt64() + let _c1 = _1 != nil + if _c1 { + return Api.account.Takeout.takeout(id: _1!) + } + else { + return nil + } + } + + } +} public extension Api.account { enum Themes: TypeConstructorDescription { case themes(hash: Int64, themes: [Api.Theme]) diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaWebpage.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaWebpage.swift index 9bb922487e..b439a8aff7 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaWebpage.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaWebpage.swift @@ -28,6 +28,10 @@ func telegramMediaWebpageAttributeFromApiWebpageAttribute(_ attribute: Api.WebPa return .starGift(TelegramMediaWebpageStarGiftAttribute(gift: starGift)) } return nil + case let .webPageAttributeStarGiftCollection(icons): + var files: [TelegramMediaFile] = [] + files = icons.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) } + return .giftCollection(TelegramMediaWebpageGiftCollectionAttribute(files: files)) case .webPageAttributeStory: return nil } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaWebpage.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaWebpage.swift index a6187637cb..3f03b7e088 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaWebpage.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaWebpage.swift @@ -7,6 +7,7 @@ private enum TelegramMediaWebpageAttributeTypes: Int32 { case theme case stickerPack case starGift + case giftCollection } public enum TelegramMediaWebpageAttribute: PostboxCoding, Equatable { @@ -14,33 +15,39 @@ public enum TelegramMediaWebpageAttribute: PostboxCoding, Equatable { case theme(TelegraMediaWebpageThemeAttribute) case stickerPack(TelegramMediaWebpageStickerPackAttribute) case starGift(TelegramMediaWebpageStarGiftAttribute) + case giftCollection(TelegramMediaWebpageGiftCollectionAttribute) public init(decoder: PostboxDecoder) { switch decoder.decodeInt32ForKey("r", orElse: 0) { - case TelegramMediaWebpageAttributeTypes.theme.rawValue: - self = .theme(decoder.decodeObjectForKey("a", decoder: { TelegraMediaWebpageThemeAttribute(decoder: $0) }) as! TelegraMediaWebpageThemeAttribute) - case TelegramMediaWebpageAttributeTypes.stickerPack.rawValue: - self = .stickerPack(decoder.decodeObjectForKey("a", decoder: { TelegramMediaWebpageStickerPackAttribute(decoder: $0) }) as! TelegramMediaWebpageStickerPackAttribute) - case TelegramMediaWebpageAttributeTypes.starGift.rawValue: - self = .starGift(decoder.decodeObjectForKey("a", decoder: { TelegramMediaWebpageStarGiftAttribute(decoder: $0) }) as! TelegramMediaWebpageStarGiftAttribute) - default: - self = .unsupported + case TelegramMediaWebpageAttributeTypes.theme.rawValue: + self = .theme(decoder.decodeObjectForKey("a", decoder: { TelegraMediaWebpageThemeAttribute(decoder: $0) }) as! TelegraMediaWebpageThemeAttribute) + case TelegramMediaWebpageAttributeTypes.stickerPack.rawValue: + self = .stickerPack(decoder.decodeObjectForKey("a", decoder: { TelegramMediaWebpageStickerPackAttribute(decoder: $0) }) as! TelegramMediaWebpageStickerPackAttribute) + case TelegramMediaWebpageAttributeTypes.starGift.rawValue: + self = .starGift(decoder.decodeObjectForKey("a", decoder: { TelegramMediaWebpageStarGiftAttribute(decoder: $0) }) as! TelegramMediaWebpageStarGiftAttribute) + case TelegramMediaWebpageAttributeTypes.giftCollection.rawValue: + self = .giftCollection(decoder.decodeObjectForKey("a", decoder: { TelegramMediaWebpageGiftCollectionAttribute(decoder: $0) }) as! TelegramMediaWebpageGiftCollectionAttribute) + default: + self = .unsupported } } public func encode(_ encoder: PostboxEncoder) { switch self { - case .unsupported: - encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.unsupported.rawValue, forKey: "r") - case let .theme(attribute): - encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.theme.rawValue, forKey: "r") - encoder.encodeObject(attribute, forKey: "a") - case let .stickerPack(attribute): - encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.stickerPack.rawValue, forKey: "r") - encoder.encodeObject(attribute, forKey: "a") - case let .starGift(attribute): - encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.starGift.rawValue, forKey: "r") - encoder.encodeObject(attribute, forKey: "a") + case .unsupported: + encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.unsupported.rawValue, forKey: "r") + case let .theme(attribute): + encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.theme.rawValue, forKey: "r") + encoder.encodeObject(attribute, forKey: "a") + case let .stickerPack(attribute): + encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.stickerPack.rawValue, forKey: "r") + encoder.encodeObject(attribute, forKey: "a") + case let .starGift(attribute): + encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.starGift.rawValue, forKey: "r") + encoder.encodeObject(attribute, forKey: "a") + case let .giftCollection(attribute): + encoder.encodeInt32(TelegramMediaWebpageAttributeTypes.giftCollection.rawValue, forKey: "r") + encoder.encodeObject(attribute, forKey: "a") } } } @@ -159,6 +166,35 @@ public final class TelegramMediaWebpageStarGiftAttribute: PostboxCoding, Equatab } } +public final class TelegramMediaWebpageGiftCollectionAttribute: PostboxCoding, Equatable { + public static func == (lhs: TelegramMediaWebpageGiftCollectionAttribute, rhs: TelegramMediaWebpageGiftCollectionAttribute) -> Bool { + if lhs.files.count != rhs.files.count { + return false + } else { + for i in 0 ..< lhs.files.count { + if !lhs.files[i].isEqual(to: rhs.files[i]) { + return false + } + } + } + return true + } + + public let files: [TelegramMediaFile] + + public init(files: [TelegramMediaFile]) { + self.files = files + } + + public init(decoder: PostboxDecoder) { + self.files = decoder.decodeObjectArrayForKey("files") + } + + public func encode(_ encoder: PostboxEncoder) { + encoder.encodeObjectArray(self.files, forKey: "files") + } +} + public final class TelegramMediaWebpageLoadedContent: PostboxCoding, Equatable { public let url: String public let displayUrl: String diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift index 34af883bd3..286640e38c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift @@ -1838,11 +1838,11 @@ private final class ProfileGiftsContextImpl { return true } switch gift.gift { - case .generic(let gift): + case let .generic(gift): if gift.id == id { return true } - case .unique(let uniqueGift): + case let .unique(uniqueGift): if uniqueGift.id == id { return true } @@ -1861,11 +1861,11 @@ private final class ProfileGiftsContextImpl { return true } switch gift.gift { - case .generic(let gift): + case let .generic(gift): if gift.id == id { return true } - case .unique(let uniqueGift): + case let .unique(uniqueGift): if uniqueGift.id == id { return true } diff --git a/submodules/TelegramStringFormatting/Sources/TonFormat.swift b/submodules/TelegramStringFormatting/Sources/TonFormat.swift index dd2d735a11..e01787e320 100644 --- a/submodules/TelegramStringFormatting/Sources/TonFormat.swift +++ b/submodules/TelegramStringFormatting/Sources/TonFormat.swift @@ -11,6 +11,20 @@ public func formatTonAddress(_ address: String) -> String { return address } +public func convertStarsToTon(_ amount: StarsAmount, tonUsdRate: Double, starsUsdRate: Double) -> Int64 { + let usdRate = starsUsdRate / 1000.0 / 100.0 + let usdValue = Double(amount.value) * usdRate + let tonValue = usdValue / tonUsdRate * 1000000000.0 + return Int64(tonValue) +} + +public func convertTonToStars(_ amount: StarsAmount, tonUsdRate: Double, starsUsdRate: Double) -> Int64 { + let usdRate = starsUsdRate / 1000.0 / 100.0 + let usdValue = Double(amount.value) / 1000000000 * tonUsdRate + let starsValue = usdValue / usdRate + return Int64(starsValue) +} + public func formatTonUsdValue(_ value: Int64, divide: Bool = true, rate: Double = 1.0, dateTimeFormat: PresentationDateTimeFormat) -> String { let decimalSeparator = dateTimeFormat.decimalSeparator let normalizedValue: Double = divide ? Double(value) / 1000000000 : Double(value) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift index 70025dff94..2ee5c14240 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageWebpageBubbleContentNode/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -476,6 +476,9 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent entities = nil case "telegram_call": actionTitle = item.presentationData.strings.Chat_ViewGroupCall + case "telegram_collection": + //TODO:localize + actionTitle = "VIEW COLLECTION" default: break } @@ -484,6 +487,9 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent if case let .stickerPack(stickerPack) = attribute, !stickerPack.files.isEmpty { mediaAndFlags = (stickerPack.files, [.preferMediaInline, .stickerPack]) break + } else if case let .giftCollection(giftCollection) = attribute, !giftCollection.files.isEmpty { + mediaAndFlags = (giftCollection.files, [.preferMediaInline, .stickerPack]) + break } } diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift index fb24a05de9..9e7a6a6e9f 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift @@ -1454,10 +1454,14 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { break case .stars: break + case .ton: + break case .shareStory: break case .storyFolder: break + case .giftCollection: + break } } })) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 05827b0c89..cec20ee874 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -843,9 +843,9 @@ private final class GiftViewSheetContent: CombinedComponent { } switch self.subject { case let .profileGift(peerId, currentSubject): - self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellAmounts(nil)))) + self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellAmounts(nil).withResellForTonOnly(false)))) case let .uniqueGift(_, recipientPeerId): - self.subject = .uniqueGift(gift.withResellAmounts(nil), recipientPeerId) + self.subject = .uniqueGift(gift.withResellAmounts(nil).withResellForTonOnly(false), recipientPeerId) default: break } @@ -919,9 +919,9 @@ private final class GiftViewSheetContent: CombinedComponent { switch self.subject { case let .profileGift(peerId, currentSubject): - self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellAmounts([price])))) + self.subject = .profileGift(peerId, currentSubject.withGift(.unique(gift.withResellAmounts([price]).withResellForTonOnly(price.currency == .ton)))) case let .uniqueGift(_, recipientPeerId): - self.subject = .uniqueGift(gift.withResellAmounts([price]), recipientPeerId) + self.subject = .uniqueGift(gift.withResellAmounts([price]).withResellForTonOnly(price.currency == .ton), recipientPeerId) default: break } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift index 4197ba7446..aa6594e25f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoPaneContainerNode.swift @@ -528,6 +528,7 @@ private final class PeerInfoPendingPane { chatLocationContextHolder: Atomic, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?, initialStoryFolderId: Int64?, + initialGiftCollectionId: Int64?, key: PeerInfoPaneKey, hasBecomeReady: @escaping (PeerInfoPaneKey) -> Void, parentController: ViewController?, @@ -577,7 +578,7 @@ private final class PeerInfoPendingPane { } } } - paneNode = PeerInfoGiftsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, profileGiftsCollections: data.profileGiftsCollectionsContext!, profileGifts: data.profileGiftsContext!, canManage: canManage, canGift: canGift) + paneNode = PeerInfoGiftsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, profileGiftsCollections: data.profileGiftsCollectionsContext!, profileGifts: data.profileGiftsContext!, canManage: canManage, canGift: canGift, initialGiftCollectionId: initialGiftCollectionId) case .stories, .storyArchive, .botPreview: var canManage = false if let peer = data.peer { @@ -730,6 +731,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat private var pendingPanes: [PeerInfoPaneKey: PeerInfoPendingPane] = [:] private var shouldFadeIn = false private var initialStoryFolderId: Int64? + private var initialGiftCollectionId: Int64? private var transitionFraction: CGFloat = 0.0 @@ -755,7 +757,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat private let initialPaneKey: PeerInfoPaneKey? - init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, peerId: PeerId, chatLocation: ChatLocation, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?, chatLocationContextHolder: Atomic, isMediaOnly: Bool, initialPaneKey: PeerInfoPaneKey?, initialStoryFolderId: Int64?) { + init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)?, peerId: PeerId, chatLocation: ChatLocation, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?, chatLocationContextHolder: Atomic, isMediaOnly: Bool, initialPaneKey: PeerInfoPaneKey?, initialStoryFolderId: Int64?, initialGiftCollectionId: Int64?) { self.context = context self.updatedPresentationData = updatedPresentationData self.peerId = peerId @@ -765,6 +767,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat self.isMediaOnly = isMediaOnly self.initialPaneKey = initialPaneKey self.initialStoryFolderId = initialStoryFolderId + self.initialGiftCollectionId = initialGiftCollectionId self.additionalBackgroundNode = ASDisplayNode() @@ -1103,12 +1106,19 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat if self.pendingPanes[key] == nil, let data { var leftScope = false var initialStoryFolderId: Int64? + var initialGiftCollectionId: Int64? if case .stories = key { if let initialStoryFolderIdValue = self.initialStoryFolderId { self.initialStoryFolderId = nil initialStoryFolderId = initialStoryFolderIdValue } } + if case .gifts = key { + if let initialGiftCollectionIdValue = self.initialGiftCollectionId { + self.initialGiftCollectionId = nil + initialGiftCollectionId = initialGiftCollectionIdValue + } + } let pane = PeerInfoPendingPane( context: self.context, updatedPresentationData: self.updatedPresentationData, @@ -1128,6 +1138,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat chatLocationContextHolder: self.chatLocationContextHolder, sharedMediaFromForumTopic: self.sharedMediaFromForumTopic, initialStoryFolderId: initialStoryFolderId, + initialGiftCollectionId: initialGiftCollectionId, key: key, hasBecomeReady: { [weak self] key in let apply: () -> Void = { diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 7ae3a0bd34..5a84b6a764 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -2908,6 +2908,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro private let chatLocation: ChatLocation private let chatLocationContextHolder: Atomic private let switchToStoryFolder: Int64? + private let switchToGiftCollection: Int64? private let sharedMediaFromForumTopic: (EnginePeer.Id, Int64)? let isSettings: Bool @@ -3032,7 +3033,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } private var didSetReady = false - init(controller: PeerInfoScreenImpl, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, requestsContext: PeerInvitationImportersContext?, profileGiftsContext: ProfileGiftsContext?, starsContext: StarsContext?, tonContext: StarsContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, switchToStoryFolder: Int64?, initialPaneKey: PeerInfoPaneKey?, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?) { + init(controller: PeerInfoScreenImpl, context: AccountContext, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool, isMyProfile: Bool, hintGroupInCommon: PeerId?, requestsContext: PeerInvitationImportersContext?, profileGiftsContext: ProfileGiftsContext?, starsContext: StarsContext?, tonContext: StarsContext?, chatLocation: ChatLocation, chatLocationContextHolder: Atomic, switchToStoryFolder: Int64?, switchToGiftCollection: Int64?, initialPaneKey: PeerInfoPaneKey?, sharedMediaFromForumTopic: (EnginePeer.Id, Int64)?) { self.controller = controller self.context = context self.peerId = peerId @@ -3049,6 +3050,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.isMediaOnly = context.account.peerId == peerId && !isSettings && !isMyProfile self.initialExpandPanes = initialPaneKey != nil self.switchToStoryFolder = switchToStoryFolder + self.switchToGiftCollection = switchToGiftCollection self.sharedMediaFromForumTopic = sharedMediaFromForumTopic self.scrollNode = ASScrollNode() @@ -3060,7 +3062,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro forumTopicThreadId = message.threadId } self.headerNode = PeerInfoHeaderNode(context: context, controller: controller, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isMediaOnly: self.isMediaOnly, isSettings: isSettings, isMyProfile: isMyProfile, forumTopicThreadId: forumTopicThreadId, chatLocation: self.chatLocation) - self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, chatLocation: chatLocation, sharedMediaFromForumTopic: sharedMediaFromForumTopic, chatLocationContextHolder: chatLocationContextHolder, isMediaOnly: self.isMediaOnly, initialPaneKey: initialPaneKey, initialStoryFolderId: switchToStoryFolder) + self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, chatLocation: chatLocation, sharedMediaFromForumTopic: sharedMediaFromForumTopic, chatLocationContextHolder: chatLocationContextHolder, isMediaOnly: self.isMediaOnly, initialPaneKey: initialPaneKey, initialStoryFolderId: switchToStoryFolder, initialGiftCollectionId: switchToGiftCollection) super.init() @@ -11391,12 +11393,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } }))) -// items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in -// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) -// }, action: { [weak self] _, f in -// f(.default) -// self?.openShareLink(url: "https://t.me/") -// }))) + if let addressName = data.peer?.addressName, !addressName.isEmpty { + items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_ShareCollection, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, f in + f(.default) + if let pane, case let .collection(id) = pane.currentCollection { + self?.openShareLink(url: "https://t.me/\(addressName)/c/\(id)") + } + }))) + } } if canReorder { @@ -13103,6 +13109,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc private let switchToGifts: Bool private let switchToGroupsInCommon: Bool private let switchToStoryFolder: Int64? + private let switchToGiftCollection: Int64? private let sharedMediaFromForumTopic: (EnginePeer.Id, Int64)? let chatLocation: ChatLocation private let chatLocationContextHolder = Atomic(value: nil) @@ -13179,7 +13186,8 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc switchToRecommendedChannels: Bool = false, switchToGifts: Bool = false, switchToGroupsInCommon: Bool = false, - switchToStoryFolder: Int64? = nil + switchToStoryFolder: Int64? = nil, + switchToGiftCollection: Int64? = nil ) { self.context = context self.updatedPresentationData = updatedPresentationData @@ -13198,6 +13206,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc self.switchToGifts = switchToGifts self.switchToGroupsInCommon = switchToGroupsInCommon self.switchToStoryFolder = switchToStoryFolder + self.switchToGiftCollection = switchToGiftCollection self.sharedMediaFromForumTopic = sharedMediaFromForumTopic if let forumTopicThread = forumTopicThread { @@ -13565,8 +13574,10 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc initialPaneKey = .groupsInCommon } else if self.switchToStoryFolder != nil { initialPaneKey = .stories + } else if self .switchToGiftCollection != nil { + 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, profileGiftsContext: self.profileGiftsContext, starsContext: self.starsContext, tonContext: self.tonContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, switchToStoryFolder: self.switchToStoryFolder, initialPaneKey: initialPaneKey, sharedMediaFromForumTopic: self.sharedMediaFromForumTopic) + 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, profileGiftsContext: self.profileGiftsContext, starsContext: self.starsContext, tonContext: self.tonContext, chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, switchToStoryFolder: self.switchToStoryFolder, switchToGiftCollection: self.switchToGiftCollection, initialPaneKey: initialPaneKey, sharedMediaFromForumTopic: self.sharedMediaFromForumTopic) self.controllerNode.accountsAndPeers.set(self.accountsAndPeers.get() |> map { $0.1 }) self.controllerNode.activeSessionsContextAndCount.set(self.activeSessionsContextAndCount.get()) self.cachedDataPromise.set(self.controllerNode.cachedDataPromise.get()) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/GiftsListView.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/GiftsListView.swift index 40d9a077e5..e1d4f54e32 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/GiftsListView.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/GiftsListView.swift @@ -80,6 +80,8 @@ final class GiftsListView: UIView { private var selectedItemsMap: [AnyHashable: ProfileGiftsContext.State.StarGift] = [:] var selectionUpdated: () -> Void = { } + var displayUnpinScreen: ((ProfileGiftsContext.State.StarGift, (() -> Void)?) -> Void)? + var selectedItems: [ProfileGiftsContext.State.StarGift] { var gifts: [ProfileGiftsContext.State.StarGift] = [] var existingIds = Set() @@ -645,9 +647,9 @@ final class GiftsListView: UIView { } if let reference = product.reference { if pinnedToTop && self.pinnedReferences.count >= self.maxPinnedCount { -// self.displayUnpinScreen(gift: product, completion: { + self.displayUnpinScreen?(product, { dismissImpl?() -// }) + }) return false } self.profileGifts.updateStarGiftPinnedToTop(reference: reference, pinnedToTop: pinnedToTop) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift index f43ec92a6b..0596997045 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoVisualMediaPaneNode/Sources/PeerInfoGiftsPaneNode.swift @@ -70,6 +70,8 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr private let profileGifts: ProfileGiftsContext private let canManage: Bool private let canGift: Bool + private let initialGiftCollectionId: Int64? + private var resultsAreEmpty = false private let chatControllerInteraction: ChatControllerInteraction @@ -130,7 +132,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr private let collectionsMaxCount: Int - public init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, profileGiftsCollections: ProfileGiftsCollectionsContext, profileGifts: ProfileGiftsContext, canManage: Bool, canGift: Bool) { + public init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, profileGiftsCollections: ProfileGiftsCollectionsContext, profileGifts: ProfileGiftsContext, canManage: Bool, canGift: Bool, initialGiftCollectionId: Int64?) { self.context = context self.peerId = peerId self.chatControllerInteraction = chatControllerInteraction @@ -138,6 +140,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.profileGifts = profileGifts self.canManage = canManage self.canGift = canGift + self.initialGiftCollectionId = initialGiftCollectionId if let value = context.currentAppConfiguration.with({ $0 }).data?["stargifts_collections_limit"] as? Double { self.collectionsMaxCount = Int(value) @@ -150,6 +153,12 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.giftsListView = GiftsListView(context: context, peerId: peerId, profileGifts: profileGifts, giftsCollections: profileGiftsCollections, canSelect: false) super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.scrollNode) + + self.statusPromise.set(self.giftsListView.status) + self.ready.set(self.giftsListView.isReady) self.giftsListView.onContentUpdated = { [weak self] in guard let self else { @@ -159,19 +168,18 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.update(size: params.size, topInset: params.topInset, sideInset: params.sideInset, bottomInset: params.bottomInset, deviceMetrics: params.deviceMetrics, visibleHeight: params.visibleHeight, isScrollingLockedAtTop: params.isScrollingLockedAtTop, expandProgress: params.expandProgress, navigationHeight: params.navigationHeight, presentationData: params.presentationData, synchronous: true, transition: .immediate) } } - - self.addSubnode(self.backgroundNode) - self.addSubnode(self.scrollNode) - - self.statusPromise.set(self.giftsListView.status) - self.ready.set(self.giftsListView.isReady) - self.giftsListView.contextAction = { [weak self] gift, view, gesture in guard let self else { return } self.contextAction(gift: gift, view: view, gesture: gesture) } + self.giftsListView.displayUnpinScreen = { [weak self] gift, completion in + guard let self else { + return + } + self.displayUnpinScreen(gift: gift, completion: completion) + } self.collectionsDisposable = (profileGiftsCollections.state |> deliverOnMainQueue).start(next: { [weak self] state in @@ -181,6 +189,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.collections = state.collections self.updateScrolling(transition: .easeInOut(duration: 0.2)) }) + + if let initialGiftCollectionId { + self.setCurrentCollection(collection: .collection(Int32(initialGiftCollectionId))) + } } deinit { @@ -435,13 +447,19 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr self.update(size: params.size, topInset: params.topInset, sideInset: params.sideInset, bottomInset: params.bottomInset, deviceMetrics: params.deviceMetrics, visibleHeight: params.visibleHeight, isScrollingLockedAtTop: params.isScrollingLockedAtTop, expandProgress: params.expandProgress, navigationHeight: params.navigationHeight, presentationData: params.presentationData, synchronous: true, transition: .immediate) } } - self.giftsListView.parentController = self.parentController + self.giftsListView.displayUnpinScreen = { [weak self] gift, completion in + guard let self else { + return + } + self.displayUnpinScreen(gift: gift, completion: completion) + } self.giftsListView.contextAction = { [weak self] gift, view, gesture in guard let self else { return } self.contextAction(gift: gift, view: view, gesture: gesture) } + self.giftsListView.parentController = self.parentController self.giftsListView.frame = previousGiftsListView.frame self.scrollNode.view.insertSubview(self.giftsListView, aboveSubview: previousGiftsListView) @@ -494,6 +512,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr } }))) + // items.append(.action(ContextMenuActionItem(text: params.presentationData.strings.PeerInfo_Gifts_ShareCollection, icon: { theme in // return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.actionSheet.primaryTextColor) // }, action: { [weak self] _, f in diff --git a/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift b/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift index d21a0a07a9..207c556cf0 100644 --- a/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift @@ -627,20 +627,14 @@ private final class SheetContent: CombinedComponent { } if state.currency == .stars { if let amount = state.amount, let tonUsdRate = withdrawConfiguration.tonUsdRate, let usdWithdrawRate = withdrawConfiguration.usdWithdrawRate { - let usdRate = usdWithdrawRate / 1000.0 / 100.0 - let usdValue = Double(amount.value) * usdRate - let tonValue = usdValue / tonUsdRate * 1000000000.0 - state.amount = StarsAmount(value: max(min(Int64(tonValue), resaleConfiguration.starGiftResaleMaxTonAmount), resaleConfiguration.starGiftResaleMinTonAmount), nanos: 0) + state.amount = StarsAmount(value: max(min(convertStarsToTon(amount, tonUsdRate: tonUsdRate, starsUsdRate: usdWithdrawRate), resaleConfiguration.starGiftResaleMaxTonAmount), resaleConfiguration.starGiftResaleMinTonAmount), nanos: 0) } else { state.amount = StarsAmount(value: 0, nanos: 0) } state.currency = .ton } else { if let amount = state.amount, let tonUsdRate = withdrawConfiguration.tonUsdRate, let usdWithdrawRate = withdrawConfiguration.usdWithdrawRate { - let usdRate = usdWithdrawRate / 1000.0 / 100.0 - let usdValue = Double(amount.value) / 1000000000 * tonUsdRate - let starsValue = usdValue / usdRate - state.amount = StarsAmount(value: max(min(Int64(starsValue), resaleConfiguration.starGiftResaleMaxStarsAmount), resaleConfiguration.starGiftResaleMinStarsAmount), nanos: 0) + state.amount = StarsAmount(value: max(min(convertTonToStars(amount, tonUsdRate: tonUsdRate, starsUsdRate: usdWithdrawRate), resaleConfiguration.starGiftResaleMaxStarsAmount), resaleConfiguration.starGiftResaleMinStarsAmount), nanos: 0) } else { state.amount = StarsAmount(value: 0, nanos: 0) } diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 2f9e8b5979..cea864b2ff 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -883,6 +883,15 @@ func openResolvedUrlImpl( navigationController.pushViewController(controller, animated: true) } } + case .ton: + dismissInput() + if let tonContext = context.tonContext { + let controller = context.sharedContext.makeStarsTransactionsScreen(context: context, starsContext: tonContext) + controller.navigationPresentation = .modal + if let navigationController { + navigationController.pushViewController(controller, animated: true) + } + } case let .joinVoiceChat(peerId, invite): let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) |> deliverOnMainQueue).start(next: { peer in @@ -1519,5 +1528,26 @@ func openResolvedUrlImpl( } navigationController?.pushViewController(controller) } + case let .giftCollection(peerId, id): + Task { @MainActor [weak navigationController] in + guard let peer = await context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ).get() else { + return + } + + guard let controller = context.sharedContext.makePeerInfoController( + context: context, + updatedPresentationData: updatedPresentationData, + peer: peer._asPeer(), + mode: .giftCollection(id: id), + avatarInitiallyExpanded: false, + fromChat: false, + requestsContext: nil + ) else { + return + } + navigationController?.pushViewController(controller) + } } } diff --git a/submodules/TelegramUI/Sources/OpenUrl.swift b/submodules/TelegramUI/Sources/OpenUrl.swift index 97ef621b84..99acb8c94b 100644 --- a/submodules/TelegramUI/Sources/OpenUrl.swift +++ b/submodules/TelegramUI/Sources/OpenUrl.swift @@ -1031,6 +1031,8 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur } else { if parsedUrl.host == "stars" { handleResolvedUrl(.stars) + } else if parsedUrl.host == "ton" { + handleResolvedUrl(.ton) } else if parsedUrl.host == "importStickers" { handleResolvedUrl(.importStickers) } else if parsedUrl.host == "settings" { diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 1f7a87cb67..308fb4b96b 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -3965,6 +3965,7 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation var switchToGifts = false var switchToGroupsInCommon = false var switchToStoryFolder: Int64? + var switchToGiftCollection: Int64? switch mode { case let .nearbyPeer(distance): @@ -3992,10 +3993,12 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation sharedMediaFromForumTopic = (peerId, peer.id.toInt64()) case let .storyAlbum(id): switchToStoryFolder = id + case let .giftCollection(id): + switchToGiftCollection = id default: 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, sharedMediaFromForumTopic: sharedMediaFromForumTopic, switchToGifts: switchToGifts, switchToGroupsInCommon: switchToGroupsInCommon, switchToStoryFolder: switchToStoryFolder) + 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, sharedMediaFromForumTopic: sharedMediaFromForumTopic, switchToGifts: switchToGifts, switchToGroupsInCommon: switchToGroupsInCommon, switchToStoryFolder: switchToStoryFolder, switchToGiftCollection: switchToGiftCollection) } else if peer is TelegramSecretChat { return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: []) } diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index 7123e227f2..1d4c771179 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -82,6 +82,7 @@ public enum ParsedInternalPeerUrlParameter { case profile case referrer(String) case storyFolder(Int64) + case giftCollection(Int64) } public enum ParsedInternalUrl { @@ -603,6 +604,12 @@ public func parseInternalUrl(sharedContext: SharedAccountContext, context: Accou } else { return nil } + } else if pathComponents.count >= 3 && pathComponents[1] == "c" { + if let collectionId = Int64(pathComponents[2]) { + return .peer(.name(pathComponents[0]), .giftCollection(collectionId)) + } else { + return nil + } } else if pathComponents.count == 4 && pathComponents[0] == "c" { if let channelId = Int64(pathComponents[1]), let threadId = Int32(pathComponents[2]), let messageId = Int32(pathComponents[3]), channelId > 0 { var timecode: Double? @@ -946,6 +953,8 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl) return .single(.result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))) case let .storyFolder(folderId): return .single(.result(.storyFolder(peerId: peer.id, id: folderId))) + case let .giftCollection(collectionId): + return .single(.result(.giftCollection(peerId: peer.id, id: collectionId))) } } else { return .single(.result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil))))