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 final class Active {
|
||||||
public let targetPeer: EnginePeer
|
public let targetPeer: EnginePeer
|
||||||
public let link: String
|
public let bot: TelegramConnectedStarRefBotList.Item
|
||||||
public let userCount: Int
|
public let copyLink: (TelegramConnectedStarRefBotList.Item) -> Void
|
||||||
public let copyLink: () -> 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.targetPeer = targetPeer
|
||||||
self.link = link
|
self.bot = bot
|
||||||
self.userCount = userCount
|
|
||||||
self.copyLink = copyLink
|
self.copyLink = copyLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -632,7 +632,6 @@ func _internal_updateStarRefProgram(account: Account, id: EnginePeer.Id, program
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class TelegramConnectedStarRefBotList : Equatable {
|
public final class TelegramConnectedStarRefBotList : Equatable {
|
||||||
|
|
||||||
public final class Item: Equatable {
|
public final class Item: Equatable {
|
||||||
public let peer: EnginePeer
|
public let peer: EnginePeer
|
||||||
public let url: String
|
public let url: String
|
||||||
|
@ -302,6 +302,10 @@ public struct StarsAmount: Equatable, Comparable, Hashable, Codable, CustomStrin
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static func +(lhs: StarsAmount, rhs: StarsAmount) -> StarsAmount {
|
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 totalNanos = Int64(lhs.nanos) + Int64(rhs.nanos)
|
||||||
let overflow = totalNanos / 1_000_000_000
|
let overflow = totalNanos / 1_000_000_000
|
||||||
let remainingNanos = totalNanos % 1_000_000_000
|
let remainingNanos = totalNanos % 1_000_000_000
|
||||||
@ -529,7 +533,7 @@ private final class StarsContextImpl {
|
|||||||
}
|
}
|
||||||
var transactions = state.transactions
|
var transactions = state.transactions
|
||||||
if addTransaction {
|
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))
|
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) {
|
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
|
||||||
switch apiTransaction {
|
switch apiTransaction {
|
||||||
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, subscriptionPeriod, giveawayPostId, starGift, floodskipNumber, starrefCommissionPermille, starrefPeer, starrefAmount):
|
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
|
let parsedPeer: StarsContext.State.Transaction.Peer
|
||||||
var paidMessageId: MessageId?
|
var paidMessageId: MessageId?
|
||||||
var giveawayMessageId: 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 media = extendedMedia.flatMap({ $0.compactMap { textMediaAndExpirationTimerFromApiMedia($0, PeerId(0)).media } }) ?? []
|
||||||
let _ = subscriptionPeriod
|
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 subscriptionPeriod: Int32?
|
||||||
public let starGift: StarGift?
|
public let starGift: StarGift?
|
||||||
public let floodskipNumber: Int32?
|
public let floodskipNumber: Int32?
|
||||||
|
public let starrefCommissionPermille: Int32?
|
||||||
|
public let starrefPeerId: PeerId?
|
||||||
|
public let starrefAmount: StarsAmount?
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
flags: Flags,
|
flags: Flags,
|
||||||
@ -703,7 +706,10 @@ public final class StarsContext {
|
|||||||
media: [Media],
|
media: [Media],
|
||||||
subscriptionPeriod: Int32?,
|
subscriptionPeriod: Int32?,
|
||||||
starGift: StarGift?,
|
starGift: StarGift?,
|
||||||
floodskipNumber: Int32?
|
floodskipNumber: Int32?,
|
||||||
|
starrefCommissionPermille: Int32?,
|
||||||
|
starrefPeerId: PeerId?,
|
||||||
|
starrefAmount: StarsAmount?
|
||||||
) {
|
) {
|
||||||
self.flags = flags
|
self.flags = flags
|
||||||
self.id = id
|
self.id = id
|
||||||
@ -721,6 +727,9 @@ public final class StarsContext {
|
|||||||
self.subscriptionPeriod = subscriptionPeriod
|
self.subscriptionPeriod = subscriptionPeriod
|
||||||
self.starGift = starGift
|
self.starGift = starGift
|
||||||
self.floodskipNumber = floodskipNumber
|
self.floodskipNumber = floodskipNumber
|
||||||
|
self.starrefCommissionPermille = starrefCommissionPermille
|
||||||
|
self.starrefPeerId = starrefPeerId
|
||||||
|
self.starrefAmount = starrefAmount
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func == (lhs: Transaction, rhs: Transaction) -> Bool {
|
public static func == (lhs: Transaction, rhs: Transaction) -> Bool {
|
||||||
@ -772,6 +781,15 @@ public final class StarsContext {
|
|||||||
if lhs.floodskipNumber != rhs.floodskipNumber {
|
if lhs.floodskipNumber != rhs.floodskipNumber {
|
||||||
return false
|
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
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -364,9 +364,8 @@ If you end your affiliate program:
|
|||||||
programDuration: bot.durationMonths,
|
programDuration: bot.durationMonths,
|
||||||
mode: .active(JoinAffiliateProgramScreenMode.Active(
|
mode: .active(JoinAffiliateProgramScreenMode.Active(
|
||||||
targetPeer: targetPeer,
|
targetPeer: targetPeer,
|
||||||
link: bot.url,
|
bot: bot,
|
||||||
userCount: Int(bot.participants),
|
copyLink: { [weak self] bot in
|
||||||
copyLink: { [weak self] in
|
|
||||||
guard let self, let component = self.component else {
|
guard let self, let component = self.component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -119,10 +119,14 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
private var topOffsetDistance: CGFloat?
|
private var topOffsetDistance: CGFloat?
|
||||||
|
|
||||||
private var currentTargetPeer: EnginePeer?
|
private var currentTargetPeer: EnginePeer?
|
||||||
|
private var currentMode: JoinAffiliateProgramScreen.Mode?
|
||||||
|
|
||||||
private var possibleTargetPeers: [EnginePeer] = []
|
private var possibleTargetPeers: [EnginePeer] = []
|
||||||
private var possibleTargetPeersDisposable: Disposable?
|
private var possibleTargetPeersDisposable: Disposable?
|
||||||
|
|
||||||
|
private var changeTargetPeerDisposable: Disposable?
|
||||||
|
private var isChangingTargetPeer: Bool = false
|
||||||
|
|
||||||
private var cachedCloseImage: UIImage?
|
private var cachedCloseImage: UIImage?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
@ -194,6 +198,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.possibleTargetPeersDisposable?.dispose()
|
self.possibleTargetPeersDisposable?.dispose()
|
||||||
|
self.changeTargetPeerDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
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 {
|
guard let component = self.component, let environment = self.environment, let controller = environment.controller() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard case let .join(join) = component.mode else {
|
guard let currentTargetPeer = self.currentTargetPeer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +351,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 })
|
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 })
|
||||||
|
|
||||||
let peers: [EnginePeer] = self.possibleTargetPeers.isEmpty ? [
|
let peers: [EnginePeer] = self.possibleTargetPeers.isEmpty ? [
|
||||||
join.initialTargetPeer
|
currentTargetPeer
|
||||||
] : self.possibleTargetPeers
|
] : self.possibleTargetPeers
|
||||||
|
|
||||||
let avatarSize = CGSize(width: 30.0, height: 30.0)
|
let avatarSize = CGSize(width: 30.0, height: 30.0)
|
||||||
@ -360,14 +365,80 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
peerLabel = "bot"
|
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: {})
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.currentTargetPeer = peer
|
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)
|
self.state?.updated(transition: .immediate)
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
@ -389,7 +460,11 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
|
|
||||||
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
||||||
|
|
||||||
|
let currentMode = self.currentMode ?? component.mode
|
||||||
|
|
||||||
if self.component == nil {
|
if self.component == nil {
|
||||||
|
self.currentMode = component.mode
|
||||||
|
|
||||||
var loadPossibleTargetPeers = false
|
var loadPossibleTargetPeers = false
|
||||||
switch component.mode {
|
switch component.mode {
|
||||||
case let .join(join):
|
case let .join(join):
|
||||||
@ -461,7 +536,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
|
|
||||||
let clippingY: CGFloat
|
let clippingY: CGFloat
|
||||||
|
|
||||||
if let currentTargetPeer = self.currentTargetPeer, case .join = component.mode {
|
if let currentTargetPeer = self.currentTargetPeer, case .join = currentMode {
|
||||||
contentHeight += 34.0
|
contentHeight += 34.0
|
||||||
|
|
||||||
let sourceAvatarSize = self.sourceAvatar.update(
|
let sourceAvatarSize = self.sourceAvatar.update(
|
||||||
@ -592,7 +667,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
transition.setFrame(view: linkIconView, frame: linkIconFrame)
|
transition.setFrame(view: linkIconView, frame: linkIconFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
if active.userCount != 0 {
|
if active.bot.participants != 0 {
|
||||||
let linkIconBadgeSize = self.linkIconBadge.update(
|
let linkIconBadgeSize = self.linkIconBadge.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(BorderedBadgeComponent(
|
component: AnyComponent(BorderedBadgeComponent(
|
||||||
@ -605,7 +680,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
scaleFactor: 1.0
|
scaleFactor: 1.0
|
||||||
))),
|
))),
|
||||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(
|
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)),
|
], spacing: 4.0)),
|
||||||
insets: UIEdgeInsets(top: 4.0, left: 9.0, bottom: 4.0, right: 8.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 titleString: String
|
||||||
let subtitleString: String
|
let subtitleString: String
|
||||||
let termsString: String
|
let termsString: String
|
||||||
switch component.mode {
|
switch currentMode {
|
||||||
case .join:
|
case .join:
|
||||||
titleString = "Affiliate Program"
|
titleString = "Affiliate Program"
|
||||||
subtitleString = "**\(component.sourcePeer.compactDisplayTitle)** will share **\(commissionTitle)** of the revenue from each user you refer to it for **\(durationTitle)**."
|
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."
|
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)."
|
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."
|
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."
|
termsString = "1 user opened \(component.sourcePeer.compactDisplayTitle) through this link."
|
||||||
} else {
|
} 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(
|
let titleSize = self.title.update(
|
||||||
@ -777,8 +852,8 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
contentHeight += 12.0
|
contentHeight += 12.0
|
||||||
|
|
||||||
if case let .active(active) = component.mode {
|
if case let .active(active) = currentMode {
|
||||||
var cleanLink = active.link
|
var cleanLink = active.bot.url
|
||||||
let removePrefixes: [String] = ["http://", "https://"]
|
let removePrefixes: [String] = ["http://", "https://"]
|
||||||
for prefix in removePrefixes {
|
for prefix in removePrefixes {
|
||||||
if cleanLink.hasPrefix(prefix) {
|
if cleanLink.hasPrefix(prefix) {
|
||||||
@ -805,7 +880,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.environment?.controller()?.dismiss()
|
self.environment?.controller()?.dismiss()
|
||||||
active.copyLink()
|
active.copyLink(active.bot)
|
||||||
},
|
},
|
||||||
animateAlpha: true,
|
animateAlpha: true,
|
||||||
animateScale: false,
|
animateScale: false,
|
||||||
@ -826,7 +901,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let actionButtonTitle: String
|
let actionButtonTitle: String
|
||||||
switch component.mode {
|
switch currentMode {
|
||||||
case .join:
|
case .join:
|
||||||
actionButtonTitle = "Join Program"
|
actionButtonTitle = "Join Program"
|
||||||
case .active:
|
case .active:
|
||||||
@ -864,7 +939,7 @@ private final class JoinAffiliateProgramScreenComponent: Component {
|
|||||||
join.completion(currentTargetPeer)
|
join.completion(currentTargetPeer)
|
||||||
}
|
}
|
||||||
case let .active(active):
|
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)
|
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>
|
let toast: ComponentView<Empty>
|
||||||
if let current = self.toast {
|
if let current = self.toast {
|
||||||
toast = current
|
toast = current
|
||||||
|
@ -8620,16 +8620,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
if let result {
|
if let result {
|
||||||
mode = .active(JoinAffiliateProgramScreenMode.Active(
|
mode = .active(JoinAffiliateProgramScreenMode.Active(
|
||||||
targetPeer: accountPeer,
|
targetPeer: accountPeer,
|
||||||
link: result.url,
|
bot: result,
|
||||||
userCount: Int(result.participants),
|
copyLink: { [weak self] result in
|
||||||
copyLink: { [weak self] in
|
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
UIPasteboard.general.string = result.url
|
UIPasteboard.general.string = result.url
|
||||||
let presentationData = self.context.sharedContext.currentPresentationData.with({ $0 })
|
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 {
|
} else {
|
||||||
@ -8654,15 +8653,14 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
programDuration: bot.durationMonths,
|
programDuration: bot.durationMonths,
|
||||||
mode: .active(JoinAffiliateProgramScreenMode.Active(
|
mode: .active(JoinAffiliateProgramScreenMode.Active(
|
||||||
targetPeer: targetPeer,
|
targetPeer: targetPeer,
|
||||||
link: bot.url,
|
bot: bot,
|
||||||
userCount: Int(bot.participants),
|
copyLink: { [weak self] result in
|
||||||
copyLink: { [weak self] in
|
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
UIPasteboard.general.string = bot.url
|
UIPasteboard.general.string = result.url
|
||||||
let presentationData = self.context.sharedContext.currentPresentationData.with({ $0 })
|
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 context: AccountContext
|
||||||
let subject: StarsTransactionScreen.Subject
|
let subject: StarsTransactionScreen.Subject
|
||||||
let cancel: (Bool) -> Void
|
let cancel: (Bool) -> Void
|
||||||
let openPeer: (EnginePeer) -> Void
|
let openPeer: (EnginePeer, Bool) -> Void
|
||||||
let openMessage: (EngineMessage.Id) -> Void
|
let openMessage: (EngineMessage.Id) -> Void
|
||||||
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
|
||||||
@ -44,7 +44,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
subject: StarsTransactionScreen.Subject,
|
subject: StarsTransactionScreen.Subject,
|
||||||
cancel: @escaping (Bool) -> Void,
|
cancel: @escaping (Bool) -> Void,
|
||||||
openPeer: @escaping (EnginePeer) -> Void,
|
openPeer: @escaping (EnginePeer, Bool) -> Void,
|
||||||
openMessage: @escaping (EngineMessage.Id) -> Void,
|
openMessage: @escaping (EngineMessage.Id) -> Void,
|
||||||
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,
|
||||||
@ -95,6 +95,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
if case let .peer(peer) = transaction.peer {
|
if case let .peer(peer) = transaction.peer {
|
||||||
peerIds.append(peer.id)
|
peerIds.append(peer.id)
|
||||||
}
|
}
|
||||||
|
if let starrefPeerId = transaction.starrefPeerId {
|
||||||
|
peerIds.append(starrefPeerId)
|
||||||
|
}
|
||||||
case let .receipt(receipt):
|
case let .receipt(receipt):
|
||||||
peerIds.append(receipt.botPaymentId)
|
peerIds.append(receipt.botPaymentId)
|
||||||
case let .gift(message):
|
case let .gift(message):
|
||||||
@ -232,6 +235,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
var giveawayMessageId: MessageId?
|
var giveawayMessageId: MessageId?
|
||||||
var isBoost = false
|
var isBoost = false
|
||||||
var giftAnimation: TelegramMediaFile?
|
var giftAnimation: TelegramMediaFile?
|
||||||
|
var isRefProgram = false
|
||||||
|
|
||||||
var delayedCloseOnOpenPeer = true
|
var delayedCloseOnOpenPeer = true
|
||||||
switch subject {
|
switch subject {
|
||||||
@ -399,6 +403,23 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
transactionPeer = transaction.peer
|
transactionPeer = transaction.peer
|
||||||
isGift = true
|
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) {
|
} else if transaction.flags.contains(.isReaction) {
|
||||||
titleText = strings.Stars_Transaction_Reaction_Title
|
titleText = strings.Stars_Transaction_Reaction_Title
|
||||||
descriptionText = ""
|
descriptionText = ""
|
||||||
@ -722,7 +743,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
} else if let toPeer {
|
} else if let toPeer, !isRefProgram {
|
||||||
let title: String
|
let title: String
|
||||||
if isSubscription {
|
if isSubscription {
|
||||||
if isBotSubscription {
|
if isBotSubscription {
|
||||||
@ -751,7 +772,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
),
|
),
|
||||||
action: {
|
action: {
|
||||||
if delayedCloseOnOpenPeer {
|
if delayedCloseOnOpenPeer {
|
||||||
component.openPeer(toPeer)
|
component.openPeer(toPeer, false)
|
||||||
Queue.mainQueue().after(1.0, {
|
Queue.mainQueue().after(1.0, {
|
||||||
component.cancel(false)
|
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 {
|
if let transactionId {
|
||||||
tableItems.append(.init(
|
tableItems.append(.init(
|
||||||
id: "transaction",
|
id: "transaction",
|
||||||
@ -1200,7 +1348,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
|
|||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let subject: StarsTransactionScreen.Subject
|
let subject: StarsTransactionScreen.Subject
|
||||||
let openPeer: (EnginePeer) -> Void
|
let openPeer: (EnginePeer, Bool) -> Void
|
||||||
let openMessage: (EngineMessage.Id) -> Void
|
let openMessage: (EngineMessage.Id) -> Void
|
||||||
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
|
||||||
@ -1210,7 +1358,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
|
|||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
subject: StarsTransactionScreen.Subject,
|
subject: StarsTransactionScreen.Subject,
|
||||||
openPeer: @escaping (EnginePeer) -> Void,
|
openPeer: @escaping (EnginePeer, Bool) -> Void,
|
||||||
openMessage: @escaping (EngineMessage.Id) -> Void,
|
openMessage: @escaping (EngineMessage.Id) -> Void,
|
||||||
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,
|
||||||
@ -1363,7 +1511,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
var openPeerImpl: ((EnginePeer) -> Void)?
|
var openPeerImpl: ((EnginePeer, Bool) -> Void)?
|
||||||
var openMessageImpl: ((EngineMessage.Id) -> Void)?
|
var openMessageImpl: ((EngineMessage.Id) -> Void)?
|
||||||
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)?
|
||||||
@ -1375,8 +1523,8 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
component: StarsTransactionSheetComponent(
|
component: StarsTransactionSheetComponent(
|
||||||
context: context,
|
context: context,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
openPeer: { peerId in
|
openPeer: { peerId, isProfile in
|
||||||
openPeerImpl?(peerId)
|
openPeerImpl?(peerId, isProfile)
|
||||||
},
|
},
|
||||||
openMessage: { messageId in
|
openMessage: { messageId in
|
||||||
openMessageImpl?(messageId)
|
openMessageImpl?(messageId)
|
||||||
@ -1402,7 +1550,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
self.navigationPresentation = .flatModal
|
self.navigationPresentation = .flatModal
|
||||||
self.automaticallyControlPresentationContextLayout = false
|
self.automaticallyControlPresentationContextLayout = false
|
||||||
|
|
||||||
openPeerImpl = { [weak self] peer in
|
openPeerImpl = { [weak self] peer, isProfile in
|
||||||
guard let self, let navigationController = self.navigationController as? NavigationController else {
|
guard let self, let navigationController = self.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1415,7 +1563,13 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
|
|||||||
guard let peer else {
|
guard let peer else {
|
||||||
return
|
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))
|
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