mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
d17391ad9b
commit
2bf11a6279
@ -12344,6 +12344,7 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.Transfer.Purchased.Stars_any" = "%@ Stars";
|
"Stars.Transfer.Purchased.Stars_any" = "%@ Stars";
|
||||||
"Stars.Transfer.UnlockedText" = "You unlocked media for **%1$@**.";
|
"Stars.Transfer.UnlockedText" = "You unlocked media for **%1$@**.";
|
||||||
"Stars.Transfer.UnlockInfo" = "Do you want to unlock %1$@ in **%2$@** for **%3$@**?";
|
"Stars.Transfer.UnlockInfo" = "Do you want to unlock %1$@ in **%2$@** for **%3$@**?";
|
||||||
|
"Stars.Transfer.UnlockBotInfo" = "Do you want to unlock %1$@ from **%2$@** for **%3$@**?";
|
||||||
|
|
||||||
"Stars.Transfer.Balance" = "Balance";
|
"Stars.Transfer.Balance" = "Balance";
|
||||||
|
|
||||||
@ -12695,6 +12696,9 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.Transaction.Subscription.Cancelled" = "You have cancelled your subscription.";
|
"Stars.Transaction.Subscription.Cancelled" = "You have cancelled your subscription.";
|
||||||
"Stars.Transaction.Subscription.Renew" = "Renew Subscription";
|
"Stars.Transaction.Subscription.Renew" = "Renew Subscription";
|
||||||
"Stars.Transaction.Subscription.Cancel" = "Cancel Subscription";
|
"Stars.Transaction.Subscription.Cancel" = "Cancel Subscription";
|
||||||
|
"Stars.Transaction.Subscription.JoinChannel" = "Join Channel";
|
||||||
|
"Stars.Transaction.Subscription.JoinAgainChannel" = "Join Channel";
|
||||||
|
"Stars.Transaction.Subscription.LeftChannel" = "You left channel but you can still get back until %@";
|
||||||
"Stars.Transaction.Subscription.PerMonth" = "%@ / month";
|
"Stars.Transaction.Subscription.PerMonth" = "%@ / month";
|
||||||
"Stars.Transaction.Subscription.PerMonthUsd" = "appx. %@ per month";
|
"Stars.Transaction.Subscription.PerMonthUsd" = "appx. %@ per month";
|
||||||
"Stars.Transaction.Subscription.Subscription" = "Subscription";
|
"Stars.Transaction.Subscription.Subscription" = "Subscription";
|
||||||
@ -12721,3 +12725,14 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Stars.Intro.Transaction.SubscriptionFee.Title" = "Monthly Subscription Fee";
|
"Stars.Intro.Transaction.SubscriptionFee.Title" = "Monthly Subscription Fee";
|
||||||
"Stars.Intro.Transaction.Reaction.Title" = "Star Reaction";
|
"Stars.Intro.Transaction.Reaction.Title" = "Star Reaction";
|
||||||
|
|
||||||
|
"Stars.Purchase.GenericPurchasePurpose" = "Buy Stars to unlock content and services on Telegram.";
|
||||||
|
"Stars.Purchase.PurchasePurpose.subs" = "Buy Stars to keep all your subscriptions.";
|
||||||
|
|
||||||
|
"Stars.Transfer.Subscribe.Channel.Title" = "Subscribe";
|
||||||
|
"Stars.Transfer.SubscribeInfo" = "Do you want to subscribe to **%1$@** for **%2$@** per month?";
|
||||||
|
"Stars.Transfer.Subscribe" = "Subscribe";
|
||||||
|
"Stars.Transfer.Subscribe.Successful.Title" = "Subscription successful!";
|
||||||
|
"Stars.Transfer.Subscribe.Successful.Text" = "%1$@ transferred to %2$@.";
|
||||||
|
|
||||||
|
"Gallery.Ad" = "Ad";
|
||||||
|
@ -305,7 +305,7 @@ public enum ResolvedUrl {
|
|||||||
case startAttach(peerId: PeerId, payload: String?, choose: ResolvedBotChoosePeerTypes?)
|
case startAttach(peerId: PeerId, payload: String?, choose: ResolvedBotChoosePeerTypes?)
|
||||||
case invoice(slug: String, invoice: TelegramMediaInvoice?)
|
case invoice(slug: String, invoice: TelegramMediaInvoice?)
|
||||||
case premiumOffer(reference: String?)
|
case premiumOffer(reference: String?)
|
||||||
case starsTopup(amount: Int64?)
|
case starsTopup(amount: Int64, purpose: String?)
|
||||||
case chatFolder(slug: String)
|
case chatFolder(slug: String)
|
||||||
case story(peerId: PeerId, id: Int32)
|
case story(peerId: PeerId, id: Int32)
|
||||||
case boost(peerId: PeerId?, status: ChannelBoostStatus?, myBoostStatus: MyBoostStatus?)
|
case boost(peerId: PeerId?, status: ChannelBoostStatus?, myBoostStatus: MyBoostStatus?)
|
||||||
@ -917,7 +917,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeProxySettingsController(context: AccountContext) -> ViewController
|
func makeProxySettingsController(context: AccountContext) -> ViewController
|
||||||
func makeLocalizationListController(context: AccountContext) -> ViewController
|
func makeLocalizationListController(context: AccountContext) -> ViewController
|
||||||
func makeCreateGroupController(context: AccountContext, peerIds: [PeerId], initialTitle: String?, mode: CreateGroupMode, completion: ((PeerId, @escaping () -> Void) -> Void)?) -> ViewController
|
func makeCreateGroupController(context: AccountContext, peerIds: [PeerId], initialTitle: String?, mode: CreateGroupMode, completion: ((PeerId, @escaping () -> Void) -> Void)?) -> ViewController
|
||||||
func makeChatRecentActionsController(context: AccountContext, peer: Peer, adminPeerId: PeerId?) -> ViewController
|
func makeChatRecentActionsController(context: AccountContext, peer: Peer, adminPeerId: PeerId?, starsState: StarsRevenueStats?) -> ViewController
|
||||||
func makePrivacyAndSecurityController(context: AccountContext) -> ViewController
|
func makePrivacyAndSecurityController(context: AccountContext) -> ViewController
|
||||||
func makeBioPrivacyController(context: AccountContext, settings: Promise<AccountPrivacySettings?>, present: @escaping (ViewController) -> Void)
|
func makeBioPrivacyController(context: AccountContext, settings: Promise<AccountPrivacySettings?>, present: @escaping (ViewController) -> Void)
|
||||||
func makeBirthdayPrivacyController(context: AccountContext, settings: Promise<AccountPrivacySettings?>, openedFromBirthdayScreen: Bool, present: @escaping (ViewController) -> Void)
|
func makeBirthdayPrivacyController(context: AccountContext, settings: Promise<AccountPrivacySettings?>, openedFromBirthdayScreen: Bool, present: @escaping (ViewController) -> Void)
|
||||||
|
@ -123,7 +123,8 @@ public enum BoostSubject: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum StarsPurchasePurpose: Equatable {
|
public enum StarsPurchasePurpose: Equatable {
|
||||||
case generic(requiredStars: Int64?)
|
case generic
|
||||||
|
case topUp(requiredStars: Int64, purpose: String?)
|
||||||
case transfer(peerId: EnginePeer.Id, requiredStars: Int64)
|
case transfer(peerId: EnginePeer.Id, requiredStars: Int64)
|
||||||
case subscription(peerId: EnginePeer.Id, requiredStars: Int64, renew: Bool)
|
case subscription(peerId: EnginePeer.Id, requiredStars: Int64, renew: Bool)
|
||||||
case gift(peerId: EnginePeer.Id)
|
case gift(peerId: EnginePeer.Id)
|
||||||
|
@ -256,7 +256,13 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if message.containsSecretMedia {
|
if let adAttribute = message.adAttribute, adAttribute.hasContentMedia {
|
||||||
|
let gallery = GalleryController(context: context, source: .standaloneMessage(message, mediaIndex), invertItemOrder: reverseMessageGalleryOrder, streamSingleVideo: stream, fromPlayingVideo: autoplayingVideo, landscape: landscape, timecode: nil, playbackRate: 1.0, synchronousLoad: synchronousLoad, replaceRootController: { [weak navigationController] controller, ready in
|
||||||
|
navigationController?.replaceTopController(controller, animated: false, ready: ready)
|
||||||
|
}, baseNavigationController: navigationController, actionInteraction: actionInteraction)
|
||||||
|
gallery.temporaryDoNotWaitForReady = autoplayingVideo
|
||||||
|
return .gallery(.single(gallery))
|
||||||
|
} else if message.containsSecretMedia {
|
||||||
let gallery = SecretMediaPreviewController(context: context, messageId: message.id)
|
let gallery = SecretMediaPreviewController(context: context, messageId: message.id)
|
||||||
return .secretGallery(gallery)
|
return .secretGallery(gallery)
|
||||||
} else {
|
} else {
|
||||||
|
@ -770,10 +770,18 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(origin: GalleryItemOriginData?, caption: NSAttributedString) {
|
func setup(origin: GalleryItemOriginData?, caption: NSAttributedString, isAd: Bool = false) {
|
||||||
let titleText = origin?.title
|
var titleText = origin?.title
|
||||||
let dateText = origin?.timestamp.flatMap { humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: $0).string }
|
let dateText = origin?.timestamp.flatMap { humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: $0).string }
|
||||||
|
|
||||||
|
let caption = caption.mutableCopy() as! NSMutableAttributedString
|
||||||
|
if isAd {
|
||||||
|
if let titleText, !titleText.isEmpty {
|
||||||
|
caption.insert(NSAttributedString(string: titleText + "\n", font: Font.semibold(17.0), textColor: .white), at: 0)
|
||||||
|
}
|
||||||
|
titleText = nil
|
||||||
|
}
|
||||||
|
|
||||||
if self.currentMessageText != caption || self.currentAuthorNameText != titleText || self.currentDateText != dateText {
|
if self.currentMessageText != caption || self.currentAuthorNameText != titleText || self.currentDateText != dateText {
|
||||||
self.currentMessageText = caption
|
self.currentMessageText = caption
|
||||||
self.currentAuthorNameText = titleText
|
self.currentAuthorNameText = titleText
|
||||||
@ -820,9 +828,12 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||||||
if Namespaces.Message.allNonRegular.contains(message.id.namespace) || message.timestamp == 0 {
|
if Namespaces.Message.allNonRegular.contains(message.id.namespace) || message.timestamp == 0 {
|
||||||
displayInfo = false
|
displayInfo = false
|
||||||
}
|
}
|
||||||
|
if let _ = message.adAttribute {
|
||||||
|
displayInfo = false
|
||||||
|
}
|
||||||
|
|
||||||
var canDelete: Bool
|
var canDelete: Bool
|
||||||
var canShare = !message.containsSecretMedia && !Namespaces.Message.allNonRegular.contains(message.id.namespace)
|
var canShare = !message.containsSecretMedia && !Namespaces.Message.allNonRegular.contains(message.id.namespace) && message.adAttribute == nil
|
||||||
|
|
||||||
var canFullscreen = false
|
var canFullscreen = false
|
||||||
|
|
||||||
@ -922,13 +933,8 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||||||
}
|
}
|
||||||
|
|
||||||
var dateText = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: message.timestamp).string
|
var dateText = humanReadableStringForTimestamp(strings: self.strings, dateTimeFormat: self.dateTimeFormat, timestamp: message.timestamp).string
|
||||||
if !displayInfo {
|
|
||||||
authorNameText = ""
|
|
||||||
dateText = ""
|
|
||||||
canEdit = false
|
|
||||||
}
|
|
||||||
|
|
||||||
var messageText = NSAttributedString(string: "")
|
var messageText = NSMutableAttributedString(string: "")
|
||||||
var hasCaption = false
|
var hasCaption = false
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if media is TelegramMediaPaidContent {
|
if media is TelegramMediaPaidContent {
|
||||||
@ -991,7 +997,14 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, ASScroll
|
|||||||
codeHighlightState.disposable.dispose()
|
codeHighlightState.disposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
messageText = galleryCaptionStringWithAppliedEntities(context: self.context, text: text, entities: entities, message: message, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight)
|
messageText = galleryCaptionStringWithAppliedEntities(context: self.context, text: text, entities: entities, message: message, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight).mutableCopy() as! NSMutableAttributedString
|
||||||
|
messageText.insert(NSAttributedString(string: (authorNameText ?? "") + "\n", font: Font.semibold(17.0), textColor: .white), at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !displayInfo {
|
||||||
|
authorNameText = ""
|
||||||
|
dateText = ""
|
||||||
|
canEdit = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canFullscreen != !self.fullscreenButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText {
|
if self.currentMessageText != messageText || canDelete != !self.deleteButton.isHidden || canFullscreen != !self.fullscreenButton.isHidden || canShare != !self.actionButton.isHidden || canEdit != !self.editButton.isHidden || self.currentAuthorNameText != authorNameText || self.currentDateText != dateText {
|
||||||
|
@ -168,7 +168,9 @@ class ChatImageGalleryItem: GalleryItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let location = self.location {
|
if let _ = message.adAttribute {
|
||||||
|
node._title.set(.single(self.presentationData.strings.Gallery_Ad))
|
||||||
|
} else if let location = self.location {
|
||||||
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
node._title.set(.single(self.presentationData.strings.Items_NOfM("\(location.index + 1)", "\(location.count)").string))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1528,15 +1528,17 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
|
|
||||||
self.playbackRatePromise.set(self.playbackRate ?? 1.0)
|
self.playbackRatePromise.set(self.playbackRate ?? 1.0)
|
||||||
|
|
||||||
|
var isAd = false
|
||||||
if let contentInfo = item.contentInfo {
|
if let contentInfo = item.contentInfo {
|
||||||
switch contentInfo {
|
switch contentInfo {
|
||||||
case let .message(message, _):
|
case let .message(message, _):
|
||||||
|
isAd = message.adAttribute != nil
|
||||||
self.footerContentNode.setMessage(message, displayInfo: !item.displayInfoOnTop, peerIsCopyProtected: item.peerIsCopyProtected)
|
self.footerContentNode.setMessage(message, displayInfo: !item.displayInfoOnTop, peerIsCopyProtected: item.peerIsCopyProtected)
|
||||||
case let .webPage(webPage, media, _):
|
case let .webPage(webPage, media, _):
|
||||||
self.footerContentNode.setWebPage(webPage, media: media)
|
self.footerContentNode.setWebPage(webPage, media: media)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.footerContentNode.setup(origin: item.originData, caption: item.caption)
|
self.footerContentNode.setup(origin: item.originData, caption: item.caption, isAd: isAd)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func controlsVisibilityUpdated(isVisible: Bool) {
|
override func controlsVisibilityUpdated(isVisible: Bool) {
|
||||||
|
@ -857,18 +857,20 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
|
|||||||
|
|
||||||
private struct StarsSubscriptionConfiguration {
|
private struct StarsSubscriptionConfiguration {
|
||||||
static var defaultValue: StarsSubscriptionConfiguration {
|
static var defaultValue: StarsSubscriptionConfiguration {
|
||||||
return StarsSubscriptionConfiguration(maxFee: 2500)
|
return StarsSubscriptionConfiguration(maxFee: 2500, usdSellRate: 2000)
|
||||||
}
|
}
|
||||||
|
|
||||||
let maxFee: Int64?
|
let maxFee: Int64?
|
||||||
|
let usdSellRate: Int64?
|
||||||
|
|
||||||
fileprivate init(maxFee: Int64?) {
|
fileprivate init(maxFee: Int64?, usdSellRate: Int64?) {
|
||||||
self.maxFee = maxFee
|
self.maxFee = maxFee
|
||||||
|
self.usdSellRate = usdSellRate
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func with(appConfiguration: AppConfiguration) -> StarsSubscriptionConfiguration {
|
public static func with(appConfiguration: AppConfiguration) -> StarsSubscriptionConfiguration {
|
||||||
if let data = appConfiguration.data, let value = data["stars_subscription_amount_max"] as? Double {
|
if let data = appConfiguration.data, let value = data["stars_subscription_amount_max"] as? Double, let usdRate = data["stars_usd_sell_rate_x1000"] as? Double {
|
||||||
return StarsSubscriptionConfiguration(maxFee: Int64(value))
|
return StarsSubscriptionConfiguration(maxFee: Int64(value), usdSellRate: Int64(usdRate))
|
||||||
} else {
|
} else {
|
||||||
return .defaultValue
|
return .defaultValue
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,7 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
private var absoluteLocation: (CGRect, CGSize)?
|
private var absoluteLocation: (CGRect, CGSize)?
|
||||||
|
|
||||||
private var currentColor: ItemBackgroundColor?
|
private var currentColor: ItemBackgroundColor?
|
||||||
|
private var currentIsPaid: Bool?
|
||||||
private var layoutParams: (ItemListInviteLinkItem, ListViewItemLayoutParams, ItemListNeighbors, Bool, Bool)?
|
private var layoutParams: (ItemListInviteLinkItem, ListViewItemLayoutParams, ItemListNeighbors, Bool, Bool)?
|
||||||
|
|
||||||
public var tag: ItemListItemTag?
|
public var tag: ItemListItemTag?
|
||||||
@ -548,8 +549,12 @@ public class ItemListInviteLinkItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
if let _ = item.invite?.pricing {
|
let isPaid = item.invite?.pricing != nil
|
||||||
|
if updatedTheme != nil || strongSelf.currentIsPaid != isPaid {
|
||||||
|
strongSelf.currentIsPaid = isPaid
|
||||||
|
if isPaid {
|
||||||
strongSelf.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/SubscriptionLink"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
strongSelf.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/SubscriptionLink"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||||
} else {
|
} else {
|
||||||
strongSelf.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/InviteLink"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
strongSelf.iconNode.image = generateTintedImage(image: UIImage(bundleImageName: "Item List/InviteLink"), color: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||||
|
@ -1358,6 +1358,8 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||||||
let _ = statusApply()
|
let _ = statusApply()
|
||||||
if case let .account(context) = item.context {
|
if case let .account(context) = item.context {
|
||||||
let _ = labelApply(TextNodeWithEntities.Arguments(context: context, cache: item.context.animationCache, renderer: item.context.animationRenderer, placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, attemptSynchronous: false))
|
let _ = labelApply(TextNodeWithEntities.Arguments(context: context, cache: item.context.animationCache, renderer: item.context.animationRenderer, placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, attemptSynchronous: false))
|
||||||
|
} else {
|
||||||
|
let _ = labelApply(nil)
|
||||||
}
|
}
|
||||||
strongSelf.labelNode.textNode.isHidden = labelAttributedString == nil
|
strongSelf.labelNode.textNode.isHidden = labelAttributedString == nil
|
||||||
|
|
||||||
|
@ -709,7 +709,7 @@ public func channelAdminsController(context: AccountContext, updatedPresentation
|
|||||||
}
|
}
|
||||||
if case .legacyGroup = peer {
|
if case .legacyGroup = peer {
|
||||||
} else {
|
} else {
|
||||||
pushControllerImpl?(context.sharedContext.makeChatRecentActionsController(context: context, peer: peer._asPeer(), adminPeerId: nil))
|
pushControllerImpl?(context.sharedContext.makeChatRecentActionsController(context: context, peer: peer._asPeer(), adminPeerId: nil, starsState: nil))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -890,7 +890,7 @@ public func groupStatsController(context: AccountContext, updatedPresentationDat
|
|||||||
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
let _ = (context.account.postbox.loadedPeerWithId(peerId)
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
let controller = context.sharedContext.makeChatRecentActionsController(context: context, peer: peer, adminPeerId: participantPeerId)
|
let controller = context.sharedContext.makeChatRecentActionsController(context: context, peer: peer, adminPeerId: participantPeerId, starsState: nil)
|
||||||
navigationController.pushViewController(controller)
|
navigationController.pushViewController(controller)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -881,7 +881,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
dict[-651419003] = { return Api.SendMessageAction.parse_speakingInGroupCallAction($0) }
|
||||||
dict[-1239335713] = { return Api.ShippingOption.parse_shippingOption($0) }
|
dict[-1239335713] = { return Api.ShippingOption.parse_shippingOption($0) }
|
||||||
dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) }
|
dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) }
|
||||||
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
dict[1301522832] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
|
||||||
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
|
||||||
dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) }
|
dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) }
|
||||||
dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) }
|
dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) }
|
||||||
|
@ -441,14 +441,14 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum SponsoredMessage: TypeConstructorDescription {
|
indirect enum SponsoredMessage: TypeConstructorDescription {
|
||||||
case sponsoredMessage(flags: Int32, randomId: Buffer, url: String, title: String, message: String, entities: [Api.MessageEntity]?, photo: Api.Photo?, color: Api.PeerColor?, buttonText: String, sponsorInfo: String?, additionalInfo: String?)
|
case sponsoredMessage(flags: Int32, randomId: Buffer, url: String, title: String, message: String, entities: [Api.MessageEntity]?, photo: Api.Photo?, media: Api.MessageMedia?, color: Api.PeerColor?, buttonText: String, sponsorInfo: String?, additionalInfo: String?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .sponsoredMessage(let flags, let randomId, let url, let title, let message, let entities, let photo, let color, let buttonText, let sponsorInfo, let additionalInfo):
|
case .sponsoredMessage(let flags, let randomId, let url, let title, let message, let entities, let photo, let media, let color, let buttonText, let sponsorInfo, let additionalInfo):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-1108478618)
|
buffer.appendInt32(1301522832)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeBytes(randomId, buffer: buffer, boxed: false)
|
serializeBytes(randomId, buffer: buffer, boxed: false)
|
||||||
@ -461,6 +461,7 @@ public extension Api {
|
|||||||
item.serialize(buffer, true)
|
item.serialize(buffer, true)
|
||||||
}}
|
}}
|
||||||
if Int(flags) & Int(1 << 6) != 0 {photo!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 6) != 0 {photo!.serialize(buffer, true)}
|
||||||
|
if Int(flags) & Int(1 << 14) != 0 {media!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 13) != 0 {color!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 13) != 0 {color!.serialize(buffer, true)}
|
||||||
serializeString(buttonText, buffer: buffer, boxed: false)
|
serializeString(buttonText, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 7) != 0 {serializeString(sponsorInfo!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 7) != 0 {serializeString(sponsorInfo!, buffer: buffer, boxed: false)}
|
||||||
@ -471,8 +472,8 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .sponsoredMessage(let flags, let randomId, let url, let title, let message, let entities, let photo, let color, let buttonText, let sponsorInfo, let additionalInfo):
|
case .sponsoredMessage(let flags, let randomId, let url, let title, let message, let entities, let photo, let media, let color, let buttonText, let sponsorInfo, let additionalInfo):
|
||||||
return ("sponsoredMessage", [("flags", flags as Any), ("randomId", randomId as Any), ("url", url as Any), ("title", title as Any), ("message", message as Any), ("entities", entities as Any), ("photo", photo as Any), ("color", color as Any), ("buttonText", buttonText as Any), ("sponsorInfo", sponsorInfo as Any), ("additionalInfo", additionalInfo as Any)])
|
return ("sponsoredMessage", [("flags", flags as Any), ("randomId", randomId as Any), ("url", url as Any), ("title", title as Any), ("message", message as Any), ("entities", entities as Any), ("photo", photo as Any), ("media", media as Any), ("color", color as Any), ("buttonText", buttonText as Any), ("sponsorInfo", sponsorInfo as Any), ("additionalInfo", additionalInfo as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,16 +496,20 @@ public extension Api {
|
|||||||
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
|
||||||
_7 = Api.parse(reader, signature: signature) as? Api.Photo
|
_7 = Api.parse(reader, signature: signature) as? Api.Photo
|
||||||
} }
|
} }
|
||||||
var _8: Api.PeerColor?
|
var _8: Api.MessageMedia?
|
||||||
if Int(_1!) & Int(1 << 13) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 14) != 0 {if let signature = reader.readInt32() {
|
||||||
_8 = Api.parse(reader, signature: signature) as? Api.PeerColor
|
_8 = Api.parse(reader, signature: signature) as? Api.MessageMedia
|
||||||
|
} }
|
||||||
|
var _9: Api.PeerColor?
|
||||||
|
if Int(_1!) & Int(1 << 13) != 0 {if let signature = reader.readInt32() {
|
||||||
|
_9 = Api.parse(reader, signature: signature) as? Api.PeerColor
|
||||||
} }
|
} }
|
||||||
var _9: String?
|
|
||||||
_9 = parseString(reader)
|
|
||||||
var _10: String?
|
var _10: String?
|
||||||
if Int(_1!) & Int(1 << 7) != 0 {_10 = parseString(reader) }
|
_10 = parseString(reader)
|
||||||
var _11: String?
|
var _11: String?
|
||||||
if Int(_1!) & Int(1 << 8) != 0 {_11 = parseString(reader) }
|
if Int(_1!) & Int(1 << 7) != 0 {_11 = parseString(reader) }
|
||||||
|
var _12: String?
|
||||||
|
if Int(_1!) & Int(1 << 8) != 0 {_12 = parseString(reader) }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = _3 != nil
|
let _c3 = _3 != nil
|
||||||
@ -512,12 +517,13 @@ public extension Api {
|
|||||||
let _c5 = _5 != nil
|
let _c5 = _5 != nil
|
||||||
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
|
||||||
let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil
|
let _c7 = (Int(_1!) & Int(1 << 6) == 0) || _7 != nil
|
||||||
let _c8 = (Int(_1!) & Int(1 << 13) == 0) || _8 != nil
|
let _c8 = (Int(_1!) & Int(1 << 14) == 0) || _8 != nil
|
||||||
let _c9 = _9 != nil
|
let _c9 = (Int(_1!) & Int(1 << 13) == 0) || _9 != nil
|
||||||
let _c10 = (Int(_1!) & Int(1 << 7) == 0) || _10 != nil
|
let _c10 = _10 != nil
|
||||||
let _c11 = (Int(_1!) & Int(1 << 8) == 0) || _11 != nil
|
let _c11 = (Int(_1!) & Int(1 << 7) == 0) || _11 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
|
let _c12 = (Int(_1!) & Int(1 << 8) == 0) || _12 != nil
|
||||||
return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, url: _3!, title: _4!, message: _5!, entities: _6, photo: _7, color: _8, buttonText: _9!, sponsorInfo: _10, additionalInfo: _11)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 {
|
||||||
|
return Api.SponsoredMessage.sponsoredMessage(flags: _1!, randomId: _2!, url: _3!, title: _4!, message: _5!, entities: _6, photo: _7, media: _8, color: _9, buttonText: _10!, sponsorInfo: _11, additionalInfo: _12)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -14,8 +14,9 @@ public final class AdMessageAttribute: MessageAttribute {
|
|||||||
public let sponsorInfo: String?
|
public let sponsorInfo: String?
|
||||||
public let additionalInfo: String?
|
public let additionalInfo: String?
|
||||||
public let canReport: Bool
|
public let canReport: Bool
|
||||||
|
public let hasContentMedia: Bool
|
||||||
|
|
||||||
public init(opaqueId: Data, messageType: MessageType, url: String, buttonText: String, sponsorInfo: String?, additionalInfo: String?, canReport: Bool) {
|
public init(opaqueId: Data, messageType: MessageType, url: String, buttonText: String, sponsorInfo: String?, additionalInfo: String?, canReport: Bool, hasContentMedia: Bool) {
|
||||||
self.opaqueId = opaqueId
|
self.opaqueId = opaqueId
|
||||||
self.messageType = messageType
|
self.messageType = messageType
|
||||||
self.url = url
|
self.url = url
|
||||||
@ -23,6 +24,7 @@ public final class AdMessageAttribute: MessageAttribute {
|
|||||||
self.sponsorInfo = sponsorInfo
|
self.sponsorInfo = sponsorInfo
|
||||||
self.additionalInfo = additionalInfo
|
self.additionalInfo = additionalInfo
|
||||||
self.canReport = canReport
|
self.canReport = canReport
|
||||||
|
self.hasContentMedia = hasContentMedia
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
|
@ -12,6 +12,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
case text
|
case text
|
||||||
case textEntities
|
case textEntities
|
||||||
case media
|
case media
|
||||||
|
case contentMedia
|
||||||
case color
|
case color
|
||||||
case backgroundEmojiId
|
case backgroundEmojiId
|
||||||
case url
|
case url
|
||||||
@ -32,6 +33,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
public let text: String
|
public let text: String
|
||||||
public let textEntities: [MessageTextEntity]
|
public let textEntities: [MessageTextEntity]
|
||||||
public let media: [Media]
|
public let media: [Media]
|
||||||
|
public let contentMedia: [Media]
|
||||||
public let color: PeerNameColor?
|
public let color: PeerNameColor?
|
||||||
public let backgroundEmojiId: Int64?
|
public let backgroundEmojiId: Int64?
|
||||||
public let url: String
|
public let url: String
|
||||||
@ -47,6 +49,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
text: String,
|
text: String,
|
||||||
textEntities: [MessageTextEntity],
|
textEntities: [MessageTextEntity],
|
||||||
media: [Media],
|
media: [Media],
|
||||||
|
contentMedia: [Media],
|
||||||
color: PeerNameColor?,
|
color: PeerNameColor?,
|
||||||
backgroundEmojiId: Int64?,
|
backgroundEmojiId: Int64?,
|
||||||
url: String,
|
url: String,
|
||||||
@ -61,6 +64,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
self.text = text
|
self.text = text
|
||||||
self.textEntities = textEntities
|
self.textEntities = textEntities
|
||||||
self.media = media
|
self.media = media
|
||||||
|
self.contentMedia = contentMedia
|
||||||
self.color = color
|
self.color = color
|
||||||
self.backgroundEmojiId = backgroundEmojiId
|
self.backgroundEmojiId = backgroundEmojiId
|
||||||
self.url = url
|
self.url = url
|
||||||
@ -89,6 +93,12 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
self.media = mediaData.compactMap { data -> Media? in
|
self.media = mediaData.compactMap { data -> Media? in
|
||||||
return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Media
|
return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Media
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let contentMediaData = try container.decode([Data].self, forKey: .contentMedia)
|
||||||
|
self.contentMedia = contentMediaData.compactMap { data -> Media? in
|
||||||
|
return PostboxDecoder(buffer: MemoryBuffer(data: data)).decodeRootObject() as? Media
|
||||||
|
}
|
||||||
|
|
||||||
self.color = try container.decodeIfPresent(Int32.self, forKey: .color).flatMap { PeerNameColor(rawValue: $0) }
|
self.color = try container.decodeIfPresent(Int32.self, forKey: .color).flatMap { PeerNameColor(rawValue: $0) }
|
||||||
self.backgroundEmojiId = try container.decodeIfPresent(Int64.self, forKey: .backgroundEmojiId)
|
self.backgroundEmojiId = try container.decodeIfPresent(Int64.self, forKey: .backgroundEmojiId)
|
||||||
|
|
||||||
@ -117,6 +127,13 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
try container.encode(mediaData, forKey: .media)
|
try container.encode(mediaData, forKey: .media)
|
||||||
|
|
||||||
|
let contentMediaData = self.contentMedia.map { media -> Data in
|
||||||
|
let encoder = PostboxEncoder()
|
||||||
|
encoder.encodeRootObject(media)
|
||||||
|
return encoder.makeData()
|
||||||
|
}
|
||||||
|
try container.encode(contentMediaData, forKey: .contentMedia)
|
||||||
|
|
||||||
try container.encodeIfPresent(self.color?.rawValue, forKey: .color)
|
try container.encodeIfPresent(self.color?.rawValue, forKey: .color)
|
||||||
try container.encodeIfPresent(self.backgroundEmojiId, forKey: .backgroundEmojiId)
|
try container.encodeIfPresent(self.backgroundEmojiId, forKey: .backgroundEmojiId)
|
||||||
|
|
||||||
@ -153,6 +170,14 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if lhs.contentMedia.count != rhs.contentMedia.count {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i in 0 ..< lhs.contentMedia.count {
|
||||||
|
if !lhs.contentMedia[i].isEqual(to: rhs.contentMedia[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
if lhs.url != rhs.url {
|
if lhs.url != rhs.url {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -181,7 +206,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
case .recommended:
|
case .recommended:
|
||||||
mappedMessageType = .recommended
|
mappedMessageType = .recommended
|
||||||
}
|
}
|
||||||
attributes.append(AdMessageAttribute(opaqueId: self.opaqueId, messageType: mappedMessageType, url: self.url, buttonText: self.buttonText, sponsorInfo: self.sponsorInfo, additionalInfo: self.additionalInfo, canReport: self.canReport))
|
attributes.append(AdMessageAttribute(opaqueId: self.opaqueId, messageType: mappedMessageType, url: self.url, buttonText: self.buttonText, sponsorInfo: self.sponsorInfo, additionalInfo: self.additionalInfo, canReport: self.canReport, hasContentMedia: !self.contentMedia.isEmpty))
|
||||||
if !self.textEntities.isEmpty {
|
if !self.textEntities.isEmpty {
|
||||||
let attribute = TextEntitiesMessageAttribute(entities: self.textEntities)
|
let attribute = TextEntitiesMessageAttribute(entities: self.textEntities)
|
||||||
attributes.append(attribute)
|
attributes.append(attribute)
|
||||||
@ -241,7 +266,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
author: author,
|
author: author,
|
||||||
text: self.text,
|
text: self.text,
|
||||||
attributes: attributes,
|
attributes: attributes,
|
||||||
media: self.media,
|
media: !self.contentMedia.isEmpty ? self.contentMedia : self.media,
|
||||||
peers: messagePeers,
|
peers: messagePeers,
|
||||||
associatedMessages: SimpleDictionary<MessageId, Message>(),
|
associatedMessages: SimpleDictionary<MessageId, Message>(),
|
||||||
associatedMessageIds: [],
|
associatedMessageIds: [],
|
||||||
@ -422,7 +447,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
|
|
||||||
for message in messages {
|
for message in messages {
|
||||||
switch message {
|
switch message {
|
||||||
case let .sponsoredMessage(flags, randomId, url, title, message, entities, photo, color, buttonText, sponsorInfo, additionalInfo):
|
case let .sponsoredMessage(flags, randomId, url, title, message, entities, photo, media, color, buttonText, sponsorInfo, additionalInfo):
|
||||||
var parsedEntities: [MessageTextEntity] = []
|
var parsedEntities: [MessageTextEntity] = []
|
||||||
if let entities = entities {
|
if let entities = entities {
|
||||||
parsedEntities = messageTextEntitiesFromApiEntities(entities)
|
parsedEntities = messageTextEntitiesFromApiEntities(entities)
|
||||||
@ -442,6 +467,8 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let photo = photo.flatMap { telegramMediaImageFromApiPhoto($0) }
|
let photo = photo.flatMap { telegramMediaImageFromApiPhoto($0) }
|
||||||
|
let (contentMedia, _, _, _, _) = textMediaAndExpirationTimerFromApiMedia(media, peerId)
|
||||||
|
|
||||||
parsedMessages.append(CachedMessage(
|
parsedMessages.append(CachedMessage(
|
||||||
opaqueId: randomId.makeData(),
|
opaqueId: randomId.makeData(),
|
||||||
messageType: isRecommended ? .recommended : .sponsored,
|
messageType: isRecommended ? .recommended : .sponsored,
|
||||||
@ -449,6 +476,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
text: message,
|
text: message,
|
||||||
textEntities: parsedEntities,
|
textEntities: parsedEntities,
|
||||||
media: photo.flatMap { [$0] } ?? [],
|
media: photo.flatMap { [$0] } ?? [],
|
||||||
|
contentMedia: contentMedia.flatMap { [$0] } ?? [],
|
||||||
color: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) },
|
color: nameColorIndex.flatMap { PeerNameColor(rawValue: $0) },
|
||||||
backgroundEmojiId: backgroundEmojiId,
|
backgroundEmojiId: backgroundEmojiId,
|
||||||
url: url,
|
url: url,
|
||||||
|
@ -686,7 +686,7 @@ public final class StarsContext {
|
|||||||
return peerId!
|
return peerId!
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentState: StarsContext.State? {
|
public var currentState: StarsContext.State? {
|
||||||
var state: StarsContext.State?
|
var state: StarsContext.State?
|
||||||
self.impl.syncWith { impl in
|
self.impl.syncWith { impl in
|
||||||
state = impl._state
|
state = impl._state
|
||||||
|
@ -637,6 +637,14 @@ public struct PeerInvitationImportersState: Equatable {
|
|||||||
public var about: String?
|
public var about: String?
|
||||||
public var approvedBy: PeerId?
|
public var approvedBy: PeerId?
|
||||||
public var joinedViaFolderLink: Bool
|
public var joinedViaFolderLink: Bool
|
||||||
|
|
||||||
|
public init(peer: RenderedPeer, date: Int32, about: String? = nil, approvedBy: PeerId? = nil, joinedViaFolderLink: Bool) {
|
||||||
|
self.peer = peer
|
||||||
|
self.date = date
|
||||||
|
self.about = about
|
||||||
|
self.approvedBy = approvedBy
|
||||||
|
self.joinedViaFolderLink = joinedViaFolderLink
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public var importers: [Importer]
|
public var importers: [Importer]
|
||||||
public var isLoadingMore: Bool
|
public var isLoadingMore: Bool
|
||||||
|
@ -318,6 +318,12 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
flags.remove(.preferMediaInline)
|
flags.remove(.preferMediaInline)
|
||||||
mediaAndFlags = (mediaAndFlagsValue.0, flags)
|
mediaAndFlags = (mediaAndFlagsValue.0, flags)
|
||||||
}
|
}
|
||||||
|
if let adAttribute = message.adAttribute, adAttribute.hasContentMedia {
|
||||||
|
var flags = mediaAndFlagsValue.1
|
||||||
|
flags.remove(.preferMediaInline)
|
||||||
|
flags.insert(.preferMediaBeforeText)
|
||||||
|
mediaAndFlags = (mediaAndFlagsValue.0, flags)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentMediaAspectFilled = false
|
var contentMediaAspectFilled = false
|
||||||
|
@ -82,7 +82,7 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let openChatMessageMode: ChatControllerInteractionOpenMessageMode
|
var openChatMessageMode: ChatControllerInteractionOpenMessageMode
|
||||||
switch mode {
|
switch mode {
|
||||||
case .default:
|
case .default:
|
||||||
openChatMessageMode = .default
|
openChatMessageMode = .default
|
||||||
@ -91,6 +91,9 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
case .automaticPlayback:
|
case .automaticPlayback:
|
||||||
openChatMessageMode = .automaticPlayback
|
openChatMessageMode = .automaticPlayback
|
||||||
}
|
}
|
||||||
|
if let adAttribute = item.message.adAttribute, adAttribute.hasContentMedia {
|
||||||
|
openChatMessageMode = .automaticPlayback
|
||||||
|
}
|
||||||
if !item.controllerInteraction.openMessage(item.message, OpenMessageParams(mode: openChatMessageMode)) {
|
if !item.controllerInteraction.openMessage(item.message, OpenMessageParams(mode: openChatMessageMode)) {
|
||||||
if let webPage = strongSelf.webPage, case let .Loaded(content) = webPage.content {
|
if let webPage = strongSelf.webPage, case let .Loaded(content) = webPage.content {
|
||||||
var isConcealed = true
|
var isConcealed = true
|
||||||
|
@ -22,6 +22,8 @@ public final class ChatRecentActionsController: TelegramBaseController {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let peer: Peer
|
private let peer: Peer
|
||||||
private let initialAdminPeerId: PeerId?
|
private let initialAdminPeerId: PeerId?
|
||||||
|
let starsState: StarsRevenueStats?
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
private var presentationData: PresentationData
|
||||||
private var presentationDataPromise = Promise<PresentationData>()
|
private var presentationDataPromise = Promise<PresentationData>()
|
||||||
override public var updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) {
|
override public var updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>) {
|
||||||
@ -37,10 +39,11 @@ public final class ChatRecentActionsController: TelegramBaseController {
|
|||||||
|
|
||||||
private var adminsDisposable: Disposable?
|
private var adminsDisposable: Disposable?
|
||||||
|
|
||||||
public init(context: AccountContext, peer: Peer, adminPeerId: PeerId?) {
|
public init(context: AccountContext, peer: Peer, adminPeerId: PeerId?, starsState: StarsRevenueStats?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.initialAdminPeerId = adminPeerId
|
self.initialAdminPeerId = adminPeerId
|
||||||
|
self.starsState = starsState
|
||||||
|
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
|
@ -210,10 +210,16 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
])])
|
])])
|
||||||
strongSelf.presentController(actionSheet, .window(.root), nil)
|
strongSelf.presentController(actionSheet, .window(.root), nil)
|
||||||
} else {
|
} else {
|
||||||
let controller = inviteLinkEditController(context: strongSelf.context, updatedPresentationData: strongSelf.controller?.updatedPresentationData, peerId: peer.id, invite: invite, completion: { [weak self] _ in
|
let controller = InviteLinkViewController(
|
||||||
self?.eventLogContext.reload()
|
context: strongSelf.context,
|
||||||
})
|
updatedPresentationData: strongSelf.controller?.updatedPresentationData,
|
||||||
controller.navigationPresentation = .modal
|
peerId: peer.id,
|
||||||
|
invite: invite,
|
||||||
|
invitationsContext: nil,
|
||||||
|
revokedInvitationsContext: nil,
|
||||||
|
importersContext: nil,
|
||||||
|
starsState: strongSelf.controller?.starsState
|
||||||
|
)
|
||||||
strongSelf.pushController(controller)
|
strongSelf.pushController(controller)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -8584,7 +8584,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
guard let peer = self.data?.peer else {
|
guard let peer = self.data?.peer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let controller = self.context.sharedContext.makeChatRecentActionsController(context: self.context, peer: peer, adminPeerId: nil)
|
let controller = self.context.sharedContext.makeChatRecentActionsController(context: self.context, peer: peer, adminPeerId: nil, starsState: self.data?.starsRevenueStatsState)
|
||||||
self.controller?.push(controller)
|
self.controller?.push(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,9 +208,24 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
|
|||||||
|
|
||||||
let textString: String
|
let textString: String
|
||||||
switch context.component.purpose {
|
switch context.component.purpose {
|
||||||
case let .generic(requiredStars):
|
case .generic:
|
||||||
let _ = requiredStars
|
|
||||||
textString = strings.Stars_Purchase_GetStarsInfo
|
textString = strings.Stars_Purchase_GetStarsInfo
|
||||||
|
case let .topUp(_, purpose):
|
||||||
|
var text = strings.Stars_Purchase_GenericPurchasePurpose
|
||||||
|
if let purpose, !purpose.isEmpty {
|
||||||
|
switch purpose {
|
||||||
|
case "subs":
|
||||||
|
text = strings.Stars_Purchase_PurchasePurpose_subs
|
||||||
|
default:
|
||||||
|
let key = "Stars.Purchase.PurchasePurpose.\(purpose)"
|
||||||
|
if let string = strings.primaryComponent.dict[key] {
|
||||||
|
text = string
|
||||||
|
} else if let string = strings.secondaryComponent?.dict[key] {
|
||||||
|
text = string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textString = text
|
||||||
case .gift:
|
case .gift:
|
||||||
textString = strings.Stars_Purchase_GiftInfo(component.peers.first?.value.compactDisplayTitle ?? "").string
|
textString = strings.Stars_Purchase_GiftInfo(component.peers.first?.value.compactDisplayTitle ?? "").string
|
||||||
case .transfer:
|
case .transfer:
|
||||||
@ -816,12 +831,10 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
|
|||||||
|
|
||||||
let titleText: String
|
let titleText: String
|
||||||
switch context.component.purpose {
|
switch context.component.purpose {
|
||||||
case let .generic(requiredStars):
|
case .generic:
|
||||||
if let requiredStars {
|
|
||||||
titleText = strings.Stars_Purchase_StarsNeeded(Int32(requiredStars))
|
|
||||||
} else {
|
|
||||||
titleText = strings.Stars_Purchase_GetStars
|
titleText = strings.Stars_Purchase_GetStars
|
||||||
}
|
case let .topUp(requiredStars, _):
|
||||||
|
titleText = strings.Stars_Purchase_StarsNeeded(Int32(requiredStars))
|
||||||
case .gift:
|
case .gift:
|
||||||
titleText = strings.Stars_Purchase_GiftStars
|
titleText = strings.Stars_Purchase_GiftStars
|
||||||
case let .transfer(_, requiredStars), let .subscription(_, requiredStars, _), let .unlockMedia(requiredStars):
|
case let .transfer(_, requiredStars), let .subscription(_, requiredStars, _), let .unlockMedia(requiredStars):
|
||||||
@ -1226,7 +1239,7 @@ private extension StarsPurchasePurpose {
|
|||||||
|
|
||||||
var requiredStars: Int64? {
|
var requiredStars: Int64? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .generic(requiredStars):
|
case let .topUp(requiredStars, _):
|
||||||
return requiredStars
|
return requiredStars
|
||||||
case let .transfer(_, requiredStars):
|
case let .transfer(_, requiredStars):
|
||||||
return requiredStars
|
return requiredStars
|
||||||
|
@ -36,7 +36,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
|
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
|
||||||
let openAppExamples: () -> Void
|
let openAppExamples: () -> Void
|
||||||
let copyTransactionId: (String) -> Void
|
let copyTransactionId: (String) -> Void
|
||||||
let updateSubscription: (StarsTransactionScreen.SubscriptionAction) -> Void
|
let updateSubscription: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
@ -47,7 +47,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
|
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
|
||||||
openAppExamples: @escaping () -> Void,
|
openAppExamples: @escaping () -> Void,
|
||||||
copyTransactionId: @escaping (String) -> Void,
|
copyTransactionId: @escaping (String) -> Void,
|
||||||
updateSubscription: @escaping (StarsTransactionScreen.SubscriptionAction) -> Void
|
updateSubscription: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.subject = subject
|
self.subject = subject
|
||||||
@ -199,6 +199,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
var countOnTop = false
|
var countOnTop = false
|
||||||
var transactionId: String?
|
var transactionId: String?
|
||||||
let date: Int32
|
let date: Int32
|
||||||
|
var additionalDate: Int32?
|
||||||
var via: String?
|
var via: String?
|
||||||
var messageId: EngineMessage.Id?
|
var messageId: EngineMessage.Id?
|
||||||
var toPeer: EnginePeer?
|
var toPeer: EnginePeer?
|
||||||
@ -230,14 +231,41 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
count = subscription.pricing.amount
|
count = subscription.pricing.amount
|
||||||
date = subscription.untilDate
|
date = subscription.untilDate
|
||||||
|
if let creationDate = (subscription.peer._asPeer() as? TelegramChannel)?.creationDate, creationDate > 0 {
|
||||||
|
additionalDate = creationDate
|
||||||
|
} else {
|
||||||
|
additionalDate = nil
|
||||||
|
}
|
||||||
toPeer = subscription.peer
|
toPeer = subscription.peer
|
||||||
transactionPeer = .peer(subscription.peer)
|
transactionPeer = .peer(subscription.peer)
|
||||||
isSubscription = true
|
isSubscription = true
|
||||||
|
|
||||||
|
var hasLeft = false
|
||||||
|
if let toPeer, case let .channel(channel) = toPeer, channel.participationStatus == .left {
|
||||||
|
hasLeft = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasLeft {
|
||||||
if subscription.flags.contains(.isCancelled) {
|
if subscription.flags.contains(.isCancelled) {
|
||||||
statusText = strings.Stars_Transaction_Subscription_Cancelled
|
statusText = strings.Stars_Transaction_Subscription_Cancelled
|
||||||
statusIsDestructive = true
|
statusIsDestructive = true
|
||||||
|
if date > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
||||||
buttonText = strings.Stars_Transaction_Subscription_Renew
|
buttonText = strings.Stars_Transaction_Subscription_Renew
|
||||||
|
} else {
|
||||||
|
if let _ = subscription.inviteHash {
|
||||||
|
buttonText = strings.Stars_Transaction_Subscription_JoinAgainChannel
|
||||||
|
} else {
|
||||||
|
buttonText = strings.Common_OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if date < Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
||||||
|
buttonText = strings.Stars_Transaction_Subscription_Renew
|
||||||
|
} else {
|
||||||
|
statusText = strings.Stars_Transaction_Subscription_LeftChannel(stringForMediumDate(timestamp: subscription.untilDate, strings: strings, dateTimeFormat: dateTimeFormat, withTime: false)).string
|
||||||
|
buttonText = strings.Stars_Transaction_Subscription_JoinChannel
|
||||||
|
}
|
||||||
|
}
|
||||||
isCancelled = true
|
isCancelled = true
|
||||||
} else {
|
} else {
|
||||||
statusText = strings.Stars_Transaction_Subscription_Active(stringForMediumDate(timestamp: subscription.untilDate, strings: strings, dateTimeFormat: dateTimeFormat, withTime: false)).string
|
statusText = strings.Stars_Transaction_Subscription_Active(stringForMediumDate(timestamp: subscription.untilDate, strings: strings, dateTimeFormat: dateTimeFormat, withTime: false)).string
|
||||||
@ -628,16 +656,26 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isSubscription, let additionalDate {
|
||||||
|
tableItems.append(.init(
|
||||||
|
id: "additionalDate",
|
||||||
|
title: strings.Stars_Transaction_Subscription_Status_Subscribed,
|
||||||
|
component: AnyComponent(
|
||||||
|
MultilineTextComponent(text: .plain(NSAttributedString(string: stringForMediumDate(timestamp: additionalDate, strings: strings, dateTimeFormat: dateTimeFormat), font: tableFont, textColor: tableTextColor)))
|
||||||
|
)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
let dateTitle: String
|
let dateTitle: String
|
||||||
if isSubscription {
|
if isSubscription {
|
||||||
if isCancelled {
|
|
||||||
if date > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
if date > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
||||||
|
if isCancelled {
|
||||||
dateTitle = strings.Stars_Transaction_Subscription_Status_Expires
|
dateTitle = strings.Stars_Transaction_Subscription_Status_Expires
|
||||||
} else {
|
} else {
|
||||||
dateTitle = strings.Stars_Transaction_Subscription_Status_Expired
|
dateTitle = strings.Stars_Transaction_Subscription_Status_Renews
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dateTitle = strings.Stars_Transaction_Subscription_Status_Renews
|
dateTitle = strings.Stars_Transaction_Subscription_Status_Expired
|
||||||
}
|
}
|
||||||
} else if isSubscriber {
|
} else if isSubscriber {
|
||||||
dateTitle = strings.Stars_Transaction_Subscription_Status_Subscribed
|
dateTitle = strings.Stars_Transaction_Subscription_Status_Subscribed
|
||||||
@ -652,6 +690,16 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if isSubscriber, let additionalDate {
|
||||||
|
tableItems.append(.init(
|
||||||
|
id: "additionalDate",
|
||||||
|
title: strings.Stars_Transaction_Subscription_Status_Renews,
|
||||||
|
component: AnyComponent(
|
||||||
|
MultilineTextComponent(text: .plain(NSAttributedString(string: stringForMediumDate(timestamp: additionalDate, strings: strings, dateTimeFormat: dateTimeFormat), font: tableFont, textColor: tableTextColor)))
|
||||||
|
)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
let table = table.update(
|
let table = table.update(
|
||||||
component: TableComponent(
|
component: TableComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
@ -857,13 +905,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
isLoading: state.inProgress,
|
isLoading: state.inProgress,
|
||||||
action: {
|
action: {
|
||||||
component.cancel(true)
|
component.cancel(true)
|
||||||
|
|
||||||
if isSubscription {
|
if isSubscription {
|
||||||
if buttonIsDestructive {
|
component.updateSubscription()
|
||||||
component.updateSubscription(.cancel)
|
|
||||||
} else {
|
|
||||||
component.updateSubscription(.renew)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@ -899,7 +942,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
|
|||||||
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
|
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
|
||||||
let openAppExamples: () -> Void
|
let openAppExamples: () -> Void
|
||||||
let copyTransactionId: (String) -> Void
|
let copyTransactionId: (String) -> Void
|
||||||
let updateSubscription: (StarsTransactionScreen.SubscriptionAction) -> Void
|
let updateSubscription: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
@ -909,7 +952,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
|
|||||||
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
|
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
|
||||||
openAppExamples: @escaping () -> Void,
|
openAppExamples: @escaping () -> Void,
|
||||||
copyTransactionId: @escaping (String) -> Void,
|
copyTransactionId: @escaping (String) -> Void,
|
||||||
updateSubscription: @escaping (StarsTransactionScreen.SubscriptionAction) -> Void
|
updateSubscription: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.subject = subject
|
self.subject = subject
|
||||||
@ -1061,7 +1104,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
var openMediaImpl: (([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)?
|
var openMediaImpl: (([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)?
|
||||||
var openAppExamplesImpl: (() -> Void)?
|
var openAppExamplesImpl: (() -> Void)?
|
||||||
var copyTransactionIdImpl: ((String) -> Void)?
|
var copyTransactionIdImpl: ((String) -> Void)?
|
||||||
var updateSubscriptionImpl: ((StarsTransactionScreen.SubscriptionAction) -> Void)?
|
var updateSubscriptionImpl: (() -> Void)?
|
||||||
|
|
||||||
super.init(
|
super.init(
|
||||||
context: context,
|
context: context,
|
||||||
@ -1083,8 +1126,8 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
copyTransactionId: { transactionId in
|
copyTransactionId: { transactionId in
|
||||||
copyTransactionIdImpl?(transactionId)
|
copyTransactionIdImpl?(transactionId)
|
||||||
},
|
},
|
||||||
updateSubscription: { action in
|
updateSubscription: {
|
||||||
updateSubscriptionImpl?(action)
|
updateSubscriptionImpl?()
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
navigationBarAppearance: .none,
|
navigationBarAppearance: .none,
|
||||||
@ -1197,30 +1240,40 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
HapticFeedback().tap()
|
HapticFeedback().tap()
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSubscriptionImpl = { [weak self] action in
|
updateSubscriptionImpl = { [weak self] in
|
||||||
guard let self, case let .subscription(subscription) = subject, let navigationController = self.navigationController as? NavigationController else {
|
guard let self, case let .subscription(subscription) = subject, let navigationController = self.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
updateSubscription(action == .cancel)
|
var titleAndText: (String, String)?
|
||||||
|
if subscription.flags.contains(.isCancelled) {
|
||||||
let title: String
|
updateSubscription(false)
|
||||||
let text: String
|
if subscription.untilDate > Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
||||||
switch action {
|
titleAndText = (
|
||||||
case .cancel:
|
presentationData.strings.Stars_Transaction_Subscription_Renewed_Title,
|
||||||
title = presentationData.strings.Stars_Transaction_Subscription_Cancelled_Title
|
presentationData.strings.Stars_Transaction_Subscription_Renewed_Text(subscription.peer.compactDisplayTitle).string
|
||||||
text = presentationData.strings.Stars_Transaction_Subscription_Cancelled_Text(subscription.peer.compactDisplayTitle, stringForMediumDate(timestamp: subscription.untilDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)).string
|
)
|
||||||
case .renew:
|
}
|
||||||
title = presentationData.strings.Stars_Transaction_Subscription_Renewed_Title
|
} else {
|
||||||
text = presentationData.strings.Stars_Transaction_Subscription_Renewed_Text(subscription.peer.compactDisplayTitle).string
|
if subscription.untilDate < Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) {
|
||||||
|
updateSubscription(false)
|
||||||
|
} else {
|
||||||
|
updateSubscription(true)
|
||||||
|
titleAndText = (
|
||||||
|
presentationData.strings.Stars_Transaction_Subscription_Cancelled_Title,
|
||||||
|
presentationData.strings.Stars_Transaction_Subscription_Cancelled_Text(subscription.peer.compactDisplayTitle, stringForMediumDate(timestamp: subscription.untilDate, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat)).string
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let (title, text) = titleAndText {
|
||||||
let controller = UndoOverlayController(presentationData: presentationData, content: .invitedToVoiceChat(context: context, peer: subscription.peer, title: title, text: text, action: nil, duration: 3.0), elevatedLayout: false, position: .bottom, action: { _ in return true })
|
let controller = UndoOverlayController(presentationData: presentationData, content: .invitedToVoiceChat(context: context, peer: subscription.peer, title: title, text: text, action: nil, duration: 3.0), elevatedLayout: false, position: .bottom, action: { _ in return true })
|
||||||
Queue.mainQueue().after(0.6) {
|
Queue.mainQueue().after(0.6) {
|
||||||
navigationController.presentOverlay(controller: controller)
|
navigationController.presentOverlay(controller: controller)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
@ -972,7 +972,7 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let controller = context.sharedContext.makeStarsPurchaseScreen(context: context, starsContext: starsContext, options: options, purpose: .generic(requiredStars: nil), completion: { [weak self] stars in
|
let controller = context.sharedContext.makeStarsPurchaseScreen(context: context, starsContext: starsContext, options: options, purpose: .generic, completion: { [weak self] stars in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -348,8 +348,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let titleString: String
|
let titleString: String
|
||||||
if isSubscription {
|
if isSubscription {
|
||||||
//TODO:localize
|
titleString = strings.Stars_Transfer_Subscribe_Channel_Title
|
||||||
titleString = "Subscribe to the Channel"
|
|
||||||
} else {
|
} else {
|
||||||
titleString = strings.Stars_Transfer_Title
|
titleString = strings.Stars_Transfer_Title
|
||||||
}
|
}
|
||||||
@ -376,7 +375,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
let amount = component.invoice.totalAmount
|
let amount = component.invoice.totalAmount
|
||||||
let infoText: String
|
let infoText: String
|
||||||
if case .starsChatSubscription = context.component.source {
|
if case .starsChatSubscription = context.component.source {
|
||||||
infoText = "Do you want to subscribe to **\(state.botPeer?.compactDisplayTitle ?? "")** for **\(strings.Stars_Transfer_Info_Stars(Int32(amount)))** per month?"
|
infoText = strings.Stars_Transfer_SubscribeInfo(state.botPeer?.compactDisplayTitle ?? "", strings.Stars_Transfer_Info_Stars(Int32(amount))).string
|
||||||
} else if !component.extendedMedia.isEmpty {
|
} else if !component.extendedMedia.isEmpty {
|
||||||
var description: String = ""
|
var description: String = ""
|
||||||
var photoCount: Int32 = 0
|
var photoCount: Int32 = 0
|
||||||
@ -403,11 +402,20 @@ private final class SheetContent: CombinedComponent {
|
|||||||
description += "**\(strings.Stars_Transfer_SingleVideo)**"
|
description += "**\(strings.Stars_Transfer_SingleVideo)**"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let botPeerName = state.botPeer?.compactDisplayTitle {
|
||||||
|
infoText = strings.Stars_Transfer_UnlockBotInfo(
|
||||||
|
description,
|
||||||
|
botPeerName,
|
||||||
|
strings.Stars_Transfer_Info_Stars(Int32(amount))
|
||||||
|
).string
|
||||||
|
} else {
|
||||||
infoText = strings.Stars_Transfer_UnlockInfo(
|
infoText = strings.Stars_Transfer_UnlockInfo(
|
||||||
description,
|
description,
|
||||||
state.chatPeer?.compactDisplayTitle ?? "",
|
state.chatPeer?.compactDisplayTitle ?? "",
|
||||||
strings.Stars_Transfer_Info_Stars(Int32(amount))
|
strings.Stars_Transfer_Info_Stars(Int32(amount))
|
||||||
).string
|
).string
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
infoText = strings.Stars_Transfer_Info(
|
infoText = strings.Stars_Transfer_Info(
|
||||||
component.invoice.title,
|
component.invoice.title,
|
||||||
@ -483,7 +491,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
let amountString = presentationStringsFormattedNumber(Int32(amount), presentationData.dateTimeFormat.groupingSeparator)
|
let amountString = presentationStringsFormattedNumber(Int32(amount), presentationData.dateTimeFormat.groupingSeparator)
|
||||||
let buttonAttributedString: NSMutableAttributedString
|
let buttonAttributedString: NSMutableAttributedString
|
||||||
if case .starsChatSubscription = component.source {
|
if case .starsChatSubscription = component.source {
|
||||||
buttonAttributedString = NSMutableAttributedString(string: "Subscribe", font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
buttonAttributedString = NSMutableAttributedString(string: strings.Stars_Transfer_Subscribe, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
||||||
} else {
|
} else {
|
||||||
buttonAttributedString = NSMutableAttributedString(string: "\(strings.Stars_Transfer_Pay) # \(amountString)", font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
buttonAttributedString = NSMutableAttributedString(string: "\(strings.Stars_Transfer_Pay) # \(amountString)", font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
||||||
}
|
}
|
||||||
@ -524,7 +532,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
} else if let peerId = state?.botPeer?.id {
|
} else if let peerId = state?.botPeer?.id {
|
||||||
purpose = .transfer(peerId: peerId, requiredStars: invoice.totalAmount)
|
purpose = .transfer(peerId: peerId, requiredStars: invoice.totalAmount)
|
||||||
} else {
|
} else {
|
||||||
purpose = .generic(requiredStars: nil)
|
purpose = .generic
|
||||||
}
|
}
|
||||||
let purchaseController = accountContext.sharedContext.makeStarsPurchaseScreen(
|
let purchaseController = accountContext.sharedContext.makeStarsPurchaseScreen(
|
||||||
context: accountContext,
|
context: accountContext,
|
||||||
@ -549,9 +557,8 @@ private final class SheetContent: CombinedComponent {
|
|||||||
var title = presentationData.strings.Stars_Transfer_PurchasedTitle
|
var title = presentationData.strings.Stars_Transfer_PurchasedTitle
|
||||||
let text: String
|
let text: String
|
||||||
if isSubscription {
|
if isSubscription {
|
||||||
//TODO:localize
|
title = presentationData.strings.Stars_Transfer_Subscribe_Successful_Title
|
||||||
title = "Subscription successful!"
|
text = presentationData.strings.Stars_Transfer_Subscribe_Successful_Text(presentationData.strings.Stars_Transfer_Purchased_Stars(Int32(invoice.totalAmount)), botTitle).string
|
||||||
text = "\(presentationData.strings.Stars_Transfer_Purchased_Stars(Int32(invoice.totalAmount))) transferred to \(botTitle)."
|
|
||||||
} else if let _ = component.invoice.extendedMedia {
|
} else if let _ = component.invoice.extendedMedia {
|
||||||
text = presentationData.strings.Stars_Transfer_UnlockedText( presentationData.strings.Stars_Transfer_Purchased_Stars(Int32(invoice.totalAmount))).string
|
text = presentationData.strings.Stars_Transfer_UnlockedText( presentationData.strings.Stars_Transfer_Purchased_Stars(Int32(invoice.totalAmount))).string
|
||||||
} else {
|
} else {
|
||||||
|
@ -706,14 +706,40 @@ func openResolvedUrlImpl(
|
|||||||
if let navigationController = navigationController {
|
if let navigationController = navigationController {
|
||||||
navigationController.pushViewController(controller, animated: true)
|
navigationController.pushViewController(controller, animated: true)
|
||||||
}
|
}
|
||||||
case let .starsTopup(amount):
|
case let .starsTopup(amount, purpose):
|
||||||
dismissInput()
|
dismissInput()
|
||||||
if let starsContext = context.starsContext {
|
if let starsContext = context.starsContext {
|
||||||
let controller = context.sharedContext.makeStarsPurchaseScreen(context: context, starsContext: starsContext, options: [], purpose: .generic(requiredStars: amount), completion: { _ in })
|
let proceed = {
|
||||||
|
let controller = context.sharedContext.makeStarsPurchaseScreen(context: context, starsContext: starsContext, options: [], purpose: .topUp(requiredStars: amount, purpose: purpose), completion: { _ in })
|
||||||
if let navigationController = navigationController {
|
if let navigationController = navigationController {
|
||||||
navigationController.pushViewController(controller, animated: true)
|
navigationController.pushViewController(controller, animated: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let currentState = starsContext.currentState, currentState.balance >= amount {
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
let controller = UndoOverlayController(
|
||||||
|
presentationData: presentationData,
|
||||||
|
content: .universal(
|
||||||
|
animation: "StarsBuy",
|
||||||
|
scale: 0.066,
|
||||||
|
colors: [:],
|
||||||
|
title: nil,
|
||||||
|
text: "You have enough stars at the moment.",
|
||||||
|
customUndoText: "Buy Anyway",
|
||||||
|
timeout: nil
|
||||||
|
),
|
||||||
|
elevatedLayout: true,
|
||||||
|
action: { action in
|
||||||
|
if case .undo = action {
|
||||||
|
proceed()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
present(controller, nil)
|
||||||
|
} else {
|
||||||
|
proceed()
|
||||||
|
}
|
||||||
|
}
|
||||||
case let .joinVoiceChat(peerId, invite):
|
case let .joinVoiceChat(peerId, invite):
|
||||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|
||||||
|> deliverOnMainQueue).start(next: { peer in
|
|> deliverOnMainQueue).start(next: { peer in
|
||||||
|
@ -920,18 +920,23 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
|
|||||||
handleResolvedUrl(.premiumMultiGift(reference: reference))
|
handleResolvedUrl(.premiumMultiGift(reference: reference))
|
||||||
} else if parsedUrl.host == "stars_topup" {
|
} else if parsedUrl.host == "stars_topup" {
|
||||||
var amount: Int64?
|
var amount: Int64?
|
||||||
|
var purpose: String?
|
||||||
if let components = URLComponents(string: "/?" + query) {
|
if let components = URLComponents(string: "/?" + query) {
|
||||||
if let queryItems = components.queryItems {
|
if let queryItems = components.queryItems {
|
||||||
for queryItem in queryItems {
|
for queryItem in queryItems {
|
||||||
if let value = queryItem.value {
|
if let value = queryItem.value {
|
||||||
if queryItem.name == "amount" {
|
if queryItem.name == "balance" {
|
||||||
amount = Int64(value)
|
amount = Int64(value)
|
||||||
|
} else if queryItem.name == "purpose" {
|
||||||
|
purpose = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleResolvedUrl(.starsTopup(amount: amount))
|
if let amount {
|
||||||
|
handleResolvedUrl(.starsTopup(amount: amount, purpose: purpose))
|
||||||
|
}
|
||||||
} else if parsedUrl.host == "addlist" {
|
} else if parsedUrl.host == "addlist" {
|
||||||
if let components = URLComponents(string: "/?" + query) {
|
if let components = URLComponents(string: "/?" + query) {
|
||||||
var slug: String?
|
var slug: String?
|
||||||
|
@ -1650,8 +1650,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeChatRecentActionsController(context: AccountContext, peer: Peer, adminPeerId: PeerId?) -> ViewController {
|
public func makeChatRecentActionsController(context: AccountContext, peer: Peer, adminPeerId: PeerId?, starsState: StarsRevenueStats?) -> ViewController {
|
||||||
return ChatRecentActionsController(context: context, peer: peer, adminPeerId: adminPeerId)
|
return ChatRecentActionsController(context: context, peer: peer, adminPeerId: adminPeerId, starsState: starsState)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void) {
|
public func presentContactsWarningSuppression(context: AccountContext, present: (ViewController, Any?) -> Void) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "10.15",
|
"app": "11.0",
|
||||||
"xcode": "15.2",
|
"xcode": "15.2",
|
||||||
"bazel": "7.1.1",
|
"bazel": "7.1.1",
|
||||||
"macos": "13.0"
|
"macos": "13.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user