mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Stars ref
This commit is contained in:
parent
ef652c0e30
commit
005887b8a8
@ -896,14 +896,12 @@ public enum JoinAffiliateProgramScreenMode {
|
||||
|
||||
public final class Active {
|
||||
public let targetPeer: EnginePeer
|
||||
public let link: String
|
||||
public let userCount: Int
|
||||
public let copyLink: () -> Void
|
||||
public let bot: TelegramConnectedStarRefBotList.Item
|
||||
public let copyLink: (TelegramConnectedStarRefBotList.Item) -> Void
|
||||
|
||||
public init(targetPeer: EnginePeer, link: String, userCount: Int, copyLink: @escaping () -> Void) {
|
||||
public init(targetPeer: EnginePeer, bot: TelegramConnectedStarRefBotList.Item, copyLink: @escaping (TelegramConnectedStarRefBotList.Item) -> Void) {
|
||||
self.targetPeer = targetPeer
|
||||
self.link = link
|
||||
self.userCount = userCount
|
||||
self.bot = bot
|
||||
self.copyLink = copyLink
|
||||
}
|
||||
}
|
||||
|
@ -632,7 +632,6 @@ func _internal_updateStarRefProgram(account: Account, id: EnginePeer.Id, program
|
||||
}
|
||||
|
||||
public final class TelegramConnectedStarRefBotList : Equatable {
|
||||
|
||||
public final class Item: Equatable {
|
||||
public let peer: EnginePeer
|
||||
public let url: String
|
||||
|
@ -302,6 +302,10 @@ public struct StarsAmount: Equatable, Comparable, Hashable, Codable, CustomStrin
|
||||
}
|
||||
|
||||
public static func +(lhs: StarsAmount, rhs: StarsAmount) -> StarsAmount {
|
||||
if rhs.value < 0 || rhs.nanos < 0 {
|
||||
return lhs - StarsAmount(value: abs(rhs.value), nanos: abs(rhs.nanos))
|
||||
}
|
||||
|
||||
let totalNanos = Int64(lhs.nanos) + Int64(rhs.nanos)
|
||||
let overflow = totalNanos / 1_000_000_000
|
||||
let remainingNanos = totalNanos % 1_000_000_000
|
||||
@ -529,7 +533,7 @@ private final class StarsContextImpl {
|
||||
}
|
||||
var transactions = state.transactions
|
||||
if addTransaction {
|
||||
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil, starGift: nil, floodskipNumber: nil), at: 0)
|
||||
transactions.insert(.init(flags: [.isLocal], id: "\(arc4random())", count: balance, date: Int32(Date().timeIntervalSince1970), peer: .appStore, title: nil, description: nil, photo: nil, transactionDate: nil, transactionUrl: nil, paidMessageId: nil, giveawayMessageId: nil, media: [], subscriptionPeriod: nil, starGift: nil, floodskipNumber: nil, starrefCommissionPermille: nil, starrefPeerId: nil, starrefAmount: nil), at: 0)
|
||||
}
|
||||
|
||||
self.updateState(StarsContext.State(flags: [.isPendingBalance], balance: max(StarsAmount(value: 0, nanos: 0), state.balance + balance), subscriptions: state.subscriptions, canLoadMoreSubscriptions: state.canLoadMoreSubscriptions, transactions: transactions, canLoadMoreTransactions: state.canLoadMoreTransactions, isLoading: state.isLoading))
|
||||
@ -552,10 +556,6 @@ private extension StarsContext.State.Transaction {
|
||||
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
|
||||
switch apiTransaction {
|
||||
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId, starGift, floodskipNumber, starrefCommissionPermille, starrefPeer, starrefAmount):
|
||||
let _ = starrefCommissionPermille
|
||||
let _ = starrefPeer
|
||||
let _ = starrefAmount
|
||||
|
||||
let parsedPeer: StarsContext.State.Transaction.Peer
|
||||
var paidMessageId: MessageId?
|
||||
var giveawayMessageId: MessageId?
|
||||
@ -611,7 +611,7 @@ private extension StarsContext.State.Transaction {
|
||||
|
||||
let media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
|
||||
let _ = subscriptionPeriod
|
||||
self.init(flags: flags, id: id, count: StarsAmount(apiAmount: stars), date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod, starGift: starGift.flatMap { StarGift(apiStarGift: $0) }, floodskipNumber: floodskipNumber)
|
||||
self.init(flags: flags, id: id, count: StarsAmount(apiAmount: stars), date: date, peer: parsedPeer, title: title, description: description, photo: photo.flatMap(TelegramMediaWebFile.init), transactionDate: transactionDate, transactionUrl: transactionUrl, paidMessageId: paidMessageId, giveawayMessageId: giveawayMessageId, media: media, subscriptionPeriod: subscriptionPeriod, starGift: starGift.flatMap { StarGift(apiStarGift: $0) }, floodskipNumber: floodskipNumber, starrefCommissionPermille: starrefCommissionPermille, starrefPeerId: starrefPeer.flatMap(\.peerId), starrefAmount: starrefAmount.flatMap(StarsAmount.init(apiAmount:)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -686,6 +686,9 @@ public final class StarsContext {
|
||||
public let subscriptionPeriod: Int32?
|
||||
public let starGift: StarGift?
|
||||
public let floodskipNumber: Int32?
|
||||
public let starrefCommissionPermille: Int32?
|
||||
public let starrefPeerId: PeerId?
|
||||
public let starrefAmount: StarsAmount?
|
||||
|
||||
public init(
|
||||
flags: Flags,
|
||||
@ -703,7 +706,10 @@ public final class StarsContext {
|
||||
media: [Media],
|
||||
subscriptionPeriod: Int32?,
|
||||
starGift: StarGift?,
|
||||
floodskipNumber: Int32?
|
||||
floodskipNumber: Int32?,
|
||||
starrefCommissionPermille: Int32?,
|
||||
starrefPeerId: PeerId?,
|
||||
starrefAmount: StarsAmount?
|
||||
) {
|
||||
self.flags = flags
|
||||
self.id = id
|
||||
@ -721,6 +727,9 @@ public final class StarsContext {
|
||||
self.subscriptionPeriod = subscriptionPeriod
|
||||
self.starGift = starGift
|
||||
self.floodskipNumber = floodskipNumber
|
||||
self.starrefCommissionPermille = starrefCommissionPermille
|
||||
self.starrefPeerId = starrefPeerId
|
||||
self.starrefAmount = starrefAmount
|
||||
}
|
||||
|
||||
public static func == (lhs: Transaction, rhs: Transaction) -> Bool {
|
||||
@ -772,6 +781,15 @@ public final class StarsContext {
|
||||
if lhs.floodskipNumber != rhs.floodskipNumber {
|
||||
return false
|
||||
}
|
||||
if lhs.starrefCommissionPermille != rhs.starrefCommissionPermille {
|
||||
return false
|
||||
}
|
||||
if lhs.starrefPeerId != rhs.starrefPeerId {
|
||||
return false
|
||||
}
|
||||
if lhs.starrefAmount != rhs.starrefAmount {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -364,9 +364,8 @@ If you end your affiliate program:
|
||||
programDuration: bot.durationMonths,
|
||||
mode: .active(JoinAffiliateProgramScreenMode.Active(
|
||||
targetPeer: targetPeer,
|
||||
link: bot.url,
|
||||
userCount: Int(bot.participants),
|
||||
copyLink: { [weak self] in
|
||||
bot: bot,
|
||||
copyLink: { [weak self] bot in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
|
@ -119,10 +119,14 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
private var topOffsetDistance: CGFloat?
|
||||
|
||||
private var currentTargetPeer: EnginePeer?
|
||||
private var currentMode: JoinAffiliateProgramScreen.Mode?
|
||||
|
||||
private var possibleTargetPeers: [EnginePeer] = []
|
||||
private var possibleTargetPeersDisposable: Disposable?
|
||||
|
||||
private var changeTargetPeerDisposable: Disposable?
|
||||
private var isChangingTargetPeer: Bool = false
|
||||
|
||||
private var cachedCloseImage: UIImage?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
@ -194,6 +198,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
|
||||
deinit {
|
||||
self.possibleTargetPeersDisposable?.dispose()
|
||||
self.changeTargetPeerDisposable?.dispose()
|
||||
}
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
@ -337,7 +342,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
guard let component = self.component, let environment = self.environment, let controller = environment.controller() else {
|
||||
return
|
||||
}
|
||||
guard case let .join(join) = component.mode else {
|
||||
guard let currentTargetPeer = self.currentTargetPeer else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -346,7 +351,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 })
|
||||
|
||||
let peers: [EnginePeer] = self.possibleTargetPeers.isEmpty ? [
|
||||
join.initialTargetPeer
|
||||
currentTargetPeer
|
||||
] : self.possibleTargetPeers
|
||||
|
||||
let avatarSize = CGSize(width: 30.0, height: 30.0)
|
||||
@ -360,14 +365,80 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
} else {
|
||||
peerLabel = "bot"
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder), textLayout: .secondLineWithValue(peerLabel), icon: { _ in nil }, iconSource: ContextMenuActionItemIconSource(size: avatarSize, signal: peerAvatarCompleteImage(account: component.context.account, peer: peer, size: avatarSize)), action: { [weak self] c, _ in
|
||||
let isSelected = peer.id == self.currentTargetPeer?.id
|
||||
let accentColor = environment.theme.list.itemAccentColor
|
||||
let avatarSignal = peerAvatarCompleteImage(account: component.context.account, peer: peer, size: avatarSize)
|
||||
|> map { image in
|
||||
let context = DrawingContext(size: avatarSize, scale: 0.0, clear: true)
|
||||
context?.withContext { c in
|
||||
UIGraphicsPushContext(c)
|
||||
defer {
|
||||
UIGraphicsPopContext()
|
||||
}
|
||||
if isSelected {
|
||||
|
||||
}
|
||||
c.saveGState()
|
||||
let scaleFactor = (avatarSize.width - 3.0 * 2.0) / avatarSize.width
|
||||
if isSelected {
|
||||
c.translateBy(x: avatarSize.width * 0.5, y: avatarSize.height * 0.5)
|
||||
c.scaleBy(x: scaleFactor, y: scaleFactor)
|
||||
c.translateBy(x: -avatarSize.width * 0.5, y: -avatarSize.height * 0.5)
|
||||
}
|
||||
if let image {
|
||||
image.draw(in: CGRect(origin: CGPoint(), size: avatarSize))
|
||||
}
|
||||
c.restoreGState()
|
||||
|
||||
if isSelected {
|
||||
c.setStrokeColor(accentColor.cgColor)
|
||||
let lineWidth: CGFloat = 1.0 + UIScreenPixel
|
||||
c.setLineWidth(lineWidth)
|
||||
c.strokeEllipse(in: CGRect(origin: CGPoint(), size: avatarSize).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5))
|
||||
}
|
||||
}
|
||||
return context?.generateImage()
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: peer.displayTitle(strings: environment.strings, displayOrder: presentationData.nameDisplayOrder), textLayout: .secondLineWithValue(peerLabel), icon: { _ in nil }, iconSource: ContextMenuActionItemIconSource(size: avatarSize, signal: avatarSignal), action: { [weak self] c, _ in
|
||||
c?.dismiss(completion: {})
|
||||
|
||||
guard let self else {
|
||||
guard let self, let currentMode = self.currentMode, let component = self.component else {
|
||||
return
|
||||
}
|
||||
if self.currentTargetPeer?.id == peer.id {
|
||||
return
|
||||
}
|
||||
|
||||
self.currentTargetPeer = peer
|
||||
|
||||
switch currentMode {
|
||||
case .join:
|
||||
self.currentTargetPeer = peer
|
||||
case let .active(active):
|
||||
self.isChangingTargetPeer = true
|
||||
self.changeTargetPeerDisposable?.dispose()
|
||||
self.changeTargetPeerDisposable = (component.context.engine.peers.connectStarRefBot(id: peer.id, botId: component.sourcePeer.id)
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.isChangingTargetPeer = false
|
||||
|
||||
self.currentMode = .active(JoinAffiliateProgramScreen.Mode.Active(
|
||||
targetPeer: peer,
|
||||
bot: result,
|
||||
copyLink: active.copyLink
|
||||
))
|
||||
self.state?.updated(transition: .immediate)
|
||||
}, error: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.isChangingTargetPeer = false
|
||||
self.state?.updated(transition: .immediate)
|
||||
})
|
||||
}
|
||||
|
||||
self.state?.updated(transition: .immediate)
|
||||
})))
|
||||
}
|
||||
@ -389,7 +460,11 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
|
||||
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
||||
|
||||
let currentMode = self.currentMode ?? component.mode
|
||||
|
||||
if self.component == nil {
|
||||
self.currentMode = component.mode
|
||||
|
||||
var loadPossibleTargetPeers = false
|
||||
switch component.mode {
|
||||
case let .join(join):
|
||||
@ -461,7 +536,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
|
||||
let clippingY: CGFloat
|
||||
|
||||
if let currentTargetPeer = self.currentTargetPeer, case .join = component.mode {
|
||||
if let currentTargetPeer = self.currentTargetPeer, case .join = currentMode {
|
||||
contentHeight += 34.0
|
||||
|
||||
let sourceAvatarSize = self.sourceAvatar.update(
|
||||
@ -592,7 +667,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
transition.setFrame(view: linkIconView, frame: linkIconFrame)
|
||||
}
|
||||
|
||||
if active.userCount != 0 {
|
||||
if active.bot.participants != 0 {
|
||||
let linkIconBadgeSize = self.linkIconBadge.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(BorderedBadgeComponent(
|
||||
@ -605,7 +680,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
scaleFactor: 1.0
|
||||
))),
|
||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: "\(active.userCount)", font: Font.bold(14.0), textColor: .white))
|
||||
text: .plain(NSAttributedString(string: "\(active.bot.participants)", font: Font.bold(14.0), textColor: .white))
|
||||
)))
|
||||
], spacing: 4.0)),
|
||||
insets: UIEdgeInsets(top: 4.0, left: 9.0, bottom: 4.0, right: 8.0),
|
||||
@ -637,7 +712,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
let titleString: String
|
||||
let subtitleString: String
|
||||
let termsString: String
|
||||
switch component.mode {
|
||||
switch currentMode {
|
||||
case .join:
|
||||
titleString = "Affiliate Program"
|
||||
subtitleString = "**\(component.sourcePeer.compactDisplayTitle)** will share **\(commissionTitle)** of the revenue from each user you refer to it for **\(durationTitle)**."
|
||||
@ -651,12 +726,12 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
timeString = "for **\(durationTitle)** after they follow your link."
|
||||
}
|
||||
subtitleString = "Share this link with your users to earn a **\(commissionTitle)** commission on their spending in **\(component.sourcePeer.compactDisplayTitle)** \(timeString)."
|
||||
if active.userCount == 0 {
|
||||
if active.bot.participants == 0 {
|
||||
termsString = "No one opened \(component.sourcePeer.compactDisplayTitle) through this link yet."
|
||||
} else if active.userCount == 1 {
|
||||
} else if active.bot.participants == 1 {
|
||||
termsString = "1 user opened \(component.sourcePeer.compactDisplayTitle) through this link."
|
||||
} else {
|
||||
termsString = "\(active.userCount) users opened \(component.sourcePeer.compactDisplayTitle) through this link."
|
||||
termsString = "\(active.bot.participants) users opened \(component.sourcePeer.compactDisplayTitle) through this link."
|
||||
}
|
||||
}
|
||||
let titleSize = self.title.update(
|
||||
@ -777,8 +852,8 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
}
|
||||
contentHeight += 12.0
|
||||
|
||||
if case let .active(active) = component.mode {
|
||||
var cleanLink = active.link
|
||||
if case let .active(active) = currentMode {
|
||||
var cleanLink = active.bot.url
|
||||
let removePrefixes: [String] = ["http://", "https://"]
|
||||
for prefix in removePrefixes {
|
||||
if cleanLink.hasPrefix(prefix) {
|
||||
@ -805,7 +880,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
self.environment?.controller()?.dismiss()
|
||||
active.copyLink()
|
||||
active.copyLink(active.bot)
|
||||
},
|
||||
animateAlpha: true,
|
||||
animateScale: false,
|
||||
@ -826,7 +901,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
}
|
||||
|
||||
let actionButtonTitle: String
|
||||
switch component.mode {
|
||||
switch currentMode {
|
||||
case .join:
|
||||
actionButtonTitle = "Join Program"
|
||||
case .active:
|
||||
@ -864,7 +939,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
join.completion(currentTargetPeer)
|
||||
}
|
||||
case let .active(active):
|
||||
active.copyLink()
|
||||
active.copyLink(active.bot)
|
||||
}
|
||||
}
|
||||
)),
|
||||
@ -928,7 +1003,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
||||
|
||||
self.itemLayout = ItemLayout(containerSize: availableSize, containerInset: containerInset, bottomInset: environment.safeInsets.bottom, topInset: topInset)
|
||||
|
||||
if case .active = component.mode {
|
||||
if case .active = currentMode {
|
||||
let toast: ComponentView<Empty>
|
||||
if let current = self.toast {
|
||||
toast = current
|
||||
|
@ -8620,16 +8620,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
if let result {
|
||||
mode = .active(JoinAffiliateProgramScreenMode.Active(
|
||||
targetPeer: accountPeer,
|
||||
link: result.url,
|
||||
userCount: Int(result.participants),
|
||||
copyLink: { [weak self] in
|
||||
bot: result,
|
||||
copyLink: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
//TODO:localize
|
||||
UIPasteboard.general.string = result.url
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with({ $0 })
|
||||
self.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(title: "Link copied to clipboard", text: "Share this link and earn **\(result.commissionPermille / 10)%** of what people who use it spend in **\(EnginePeer.user(peer).compactDisplayTitle)**!"), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
self.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(title: "Link copied to clipboard", text: "Share this link and earn **\(result.commissionPermille / 10)%** of what people who use it spend in **\(result.peer.compactDisplayTitle)**!"), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
}
|
||||
))
|
||||
} else {
|
||||
@ -8654,15 +8653,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
programDuration: bot.durationMonths,
|
||||
mode: .active(JoinAffiliateProgramScreenMode.Active(
|
||||
targetPeer: targetPeer,
|
||||
link: bot.url,
|
||||
userCount: Int(bot.participants),
|
||||
copyLink: { [weak self] in
|
||||
bot: bot,
|
||||
copyLink: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
UIPasteboard.general.string = bot.url
|
||||
UIPasteboard.general.string = result.url
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with({ $0 })
|
||||
self.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(title: "Link copied to clipboard", text: "Share this link and earn **\(bot.commissionPermille / 10)%** of what people who use it spend in **\(bot.peer.compactDisplayTitle)**!"), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
self.controller?.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(title: "Link copied to clipboard", text: "Share this link and earn **\(result.commissionPermille / 10)%** of what people who use it spend in **\(result.peer.compactDisplayTitle)**!"), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
}
|
||||
))
|
||||
))
|
||||
|
@ -33,7 +33,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
let context: AccountContext
|
||||
let subject: StarsTransactionScreen.Subject
|
||||
let cancel: (Bool) -> Void
|
||||
let openPeer: (EnginePeer) -> Void
|
||||
let openPeer: (EnginePeer, Bool) -> Void
|
||||
let openMessage: (EngineMessage.Id) -> Void
|
||||
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
|
||||
let openAppExamples: () -> Void
|
||||
@ -44,7 +44,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
context: AccountContext,
|
||||
subject: StarsTransactionScreen.Subject,
|
||||
cancel: @escaping (Bool) -> Void,
|
||||
openPeer: @escaping (EnginePeer) -> Void,
|
||||
openPeer: @escaping (EnginePeer, Bool) -> Void,
|
||||
openMessage: @escaping (EngineMessage.Id) -> Void,
|
||||
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
|
||||
openAppExamples: @escaping () -> Void,
|
||||
@ -95,6 +95,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
if case let .peer(peer) = transaction.peer {
|
||||
peerIds.append(peer.id)
|
||||
}
|
||||
if let starrefPeerId = transaction.starrefPeerId {
|
||||
peerIds.append(starrefPeerId)
|
||||
}
|
||||
case let .receipt(receipt):
|
||||
peerIds.append(receipt.botPaymentId)
|
||||
case let .gift(message):
|
||||
@ -232,6 +235,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
var giveawayMessageId: MessageId?
|
||||
var isBoost = false
|
||||
var giftAnimation: TelegramMediaFile?
|
||||
var isRefProgram = false
|
||||
|
||||
var delayedCloseOnOpenPeer = true
|
||||
switch subject {
|
||||
@ -399,6 +403,23 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
}
|
||||
transactionPeer = transaction.peer
|
||||
isGift = true
|
||||
} else if let starrefCommissionPermille = transaction.starrefCommissionPermille {
|
||||
//TODO:localize
|
||||
isRefProgram = true
|
||||
if transaction.starrefPeerId == nil {
|
||||
titleText = "\(starrefCommissionPermille / 10)% Commission"
|
||||
} else {
|
||||
titleText = transaction.title ?? "Product"
|
||||
}
|
||||
descriptionText = ""
|
||||
count = transaction.count
|
||||
countOnTop = false
|
||||
transactionId = transaction.id
|
||||
date = transaction.date
|
||||
transactionPeer = transaction.peer
|
||||
if case let .peer(peer) = transaction.peer {
|
||||
toPeer = peer
|
||||
}
|
||||
} else if transaction.flags.contains(.isReaction) {
|
||||
titleText = strings.Stars_Transaction_Reaction_Title
|
||||
descriptionText = ""
|
||||
@ -722,7 +743,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
)
|
||||
)
|
||||
))
|
||||
} else if let toPeer {
|
||||
} else if let toPeer, !isRefProgram {
|
||||
let title: String
|
||||
if isSubscription {
|
||||
if isBotSubscription {
|
||||
@ -751,7 +772,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
),
|
||||
action: {
|
||||
if delayedCloseOnOpenPeer {
|
||||
component.openPeer(toPeer)
|
||||
component.openPeer(toPeer, false)
|
||||
Queue.mainQueue().after(1.0, {
|
||||
component.cancel(false)
|
||||
})
|
||||
@ -846,6 +867,133 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
||||
))
|
||||
}
|
||||
|
||||
if case let .transaction(transaction, _) = subject {
|
||||
//TODO:localize
|
||||
if transaction.starrefCommissionPermille != nil {
|
||||
if transaction.starrefPeerId == nil {
|
||||
tableItems.append(.init(
|
||||
id: "reason",
|
||||
title: "Reason",
|
||||
component: AnyComponent(
|
||||
Button(
|
||||
content: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Affiliate Program", font: tableFont, textColor: tableLinkColor))
|
||||
)),
|
||||
action: {
|
||||
if let toPeer {
|
||||
component.openPeer(toPeer, true)
|
||||
Queue.mainQueue().after(1.0, {
|
||||
component.cancel(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
),
|
||||
insets: UIEdgeInsets(top: 0.0, left: 12.0, bottom: 0.0, right: 5.0)
|
||||
))
|
||||
}
|
||||
if let toPeer, transaction.starrefPeerId == nil {
|
||||
tableItems.append(.init(
|
||||
id: "miniapp",
|
||||
title: "Mini App",
|
||||
component: AnyComponent(
|
||||
Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
peer: toPeer
|
||||
)
|
||||
),
|
||||
action: {
|
||||
if delayedCloseOnOpenPeer {
|
||||
component.openPeer(toPeer, false)
|
||||
Queue.mainQueue().after(1.0, {
|
||||
component.cancel(false)
|
||||
})
|
||||
} else {
|
||||
if let controller = controller() as? StarsTransactionScreen, let navigationController = controller.navigationController, let chatController = navigationController.viewControllers.first(where: { $0 is ChatController }) as? ChatController {
|
||||
chatController.playShakeAnimation()
|
||||
}
|
||||
component.cancel(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
if let starRefPeerId = transaction.starrefPeerId, let starRefPeer = state.peerMap[starRefPeerId] {
|
||||
//TODO:localize
|
||||
tableItems.append(.init(
|
||||
id: "to",
|
||||
title: "Affiliate",
|
||||
component: AnyComponent(
|
||||
Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
peer: starRefPeer
|
||||
)
|
||||
),
|
||||
action: {
|
||||
if delayedCloseOnOpenPeer {
|
||||
component.openPeer(starRefPeer, false)
|
||||
Queue.mainQueue().after(1.0, {
|
||||
component.cancel(false)
|
||||
})
|
||||
} else {
|
||||
if let controller = controller() as? StarsTransactionScreen, let navigationController = controller.navigationController, let chatController = navigationController.viewControllers.first(where: { $0 is ChatController }) as? ChatController {
|
||||
chatController.playShakeAnimation()
|
||||
}
|
||||
component.cancel(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
))
|
||||
if let toPeer {
|
||||
tableItems.append(.init(
|
||||
id: "referred",
|
||||
title: "Referred User",
|
||||
component: AnyComponent(
|
||||
Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
peer: toPeer
|
||||
)
|
||||
),
|
||||
action: {
|
||||
if delayedCloseOnOpenPeer {
|
||||
component.openPeer(toPeer, true)
|
||||
Queue.mainQueue().after(1.0, {
|
||||
component.cancel(false)
|
||||
})
|
||||
} else {
|
||||
if let controller = controller() as? StarsTransactionScreen, let navigationController = controller.navigationController, let chatController = navigationController.viewControllers.first(where: { $0 is ChatController }) as? ChatController {
|
||||
chatController.playShakeAnimation()
|
||||
}
|
||||
component.cancel(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
))
|
||||
}
|
||||
}
|
||||
if let starrefCommissionPermille = transaction.starrefCommissionPermille, transaction.starrefPeerId != nil {
|
||||
tableItems.append(.init(
|
||||
id: "commission",
|
||||
title: "Commission",
|
||||
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "\(starrefCommissionPermille / 10)%", font: tableFont, textColor: tableTextColor))
|
||||
)),
|
||||
insets: UIEdgeInsets(top: 0.0, left: 12.0, bottom: 0.0, right: 5.0)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
if let transactionId {
|
||||
tableItems.append(.init(
|
||||
id: "transaction",
|
||||
@ -1200,7 +1348,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
|
||||
|
||||
let context: AccountContext
|
||||
let subject: StarsTransactionScreen.Subject
|
||||
let openPeer: (EnginePeer) -> Void
|
||||
let openPeer: (EnginePeer, Bool) -> Void
|
||||
let openMessage: (EngineMessage.Id) -> Void
|
||||
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
|
||||
let openAppExamples: () -> Void
|
||||
@ -1210,7 +1358,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
|
||||
init(
|
||||
context: AccountContext,
|
||||
subject: StarsTransactionScreen.Subject,
|
||||
openPeer: @escaping (EnginePeer) -> Void,
|
||||
openPeer: @escaping (EnginePeer, Bool) -> Void,
|
||||
openMessage: @escaping (EngineMessage.Id) -> Void,
|
||||
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
|
||||
openAppExamples: @escaping () -> Void,
|
||||
@ -1363,7 +1511,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
||||
) {
|
||||
self.context = context
|
||||
|
||||
var openPeerImpl: ((EnginePeer) -> Void)?
|
||||
var openPeerImpl: ((EnginePeer, Bool) -> Void)?
|
||||
var openMessageImpl: ((EngineMessage.Id) -> Void)?
|
||||
var openMediaImpl: (([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)?
|
||||
var openAppExamplesImpl: (() -> Void)?
|
||||
@ -1375,8 +1523,8 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
||||
component: StarsTransactionSheetComponent(
|
||||
context: context,
|
||||
subject: subject,
|
||||
openPeer: { peerId in
|
||||
openPeerImpl?(peerId)
|
||||
openPeer: { peerId, isProfile in
|
||||
openPeerImpl?(peerId, isProfile)
|
||||
},
|
||||
openMessage: { messageId in
|
||||
openMessageImpl?(messageId)
|
||||
@ -1402,7 +1550,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
||||
self.navigationPresentation = .flatModal
|
||||
self.automaticallyControlPresentationContextLayout = false
|
||||
|
||||
openPeerImpl = { [weak self] peer in
|
||||
openPeerImpl = { [weak self] peer, isProfile in
|
||||
guard let self, let navigationController = self.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
@ -1415,7 +1563,13 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
||||
guard let peer else {
|
||||
return
|
||||
}
|
||||
if isProfile {
|
||||
if let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
|
||||
navigationController.pushViewController(controller)
|
||||
}
|
||||
} else {
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, chatController: nil, context: context, chatLocation: .peer(peer), subject: nil, botStart: nil, updateTextInputState: nil, keepStack: .always, useExisting: true, purposefulAction: nil, scrollToEndIfExists: false, activateMessageSearch: nil, animated: true))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user