diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/BotWebView.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/BotWebView.swift index 91403e5290..ed675dcccd 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/BotWebView.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/BotWebView.swift @@ -752,7 +752,7 @@ func _internal_requestConnectedStarRefBots(account: Account, id: EnginePeer.Id, public final class TelegramSuggestedStarRefBotList: Equatable { public enum SortMode { case date - case commission + case profitability case revenue } @@ -805,7 +805,7 @@ func _internal_requestSuggestedStarRefBots(account: Account, id: EnginePeer.Id, flags |= 1 << 0 case .date: flags |= 1 << 1 - case .commission: + case .profitability: break } return account.network.request(Api.functions.payments.getSuggestedStarRefBots( @@ -1008,3 +1008,48 @@ func _internal_getStarRefBotConnection(account: Account, id: EnginePeer.Id, targ } } } + +func _internal_getPossibleStarRefBotTargets(account: Account) -> Signal<[EnginePeer], NoError> { + return combineLatest( + account.network.request(Api.functions.bots.getAdminedBots()) + |> `catch` { _ -> Signal<[Api.User], NoError> in + return .single([]) + }, + account.network.request(Api.functions.channels.getAdminedPublicChannels(flags: 0)) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + ) + |> mapToSignal { apiBots, apiChannels -> Signal<[EnginePeer], NoError> in + return account.postbox.transaction { transaction -> [EnginePeer] in + var result: [EnginePeer] = [] + + if let peer = transaction.getPeer(account.peerId) { + result.append(EnginePeer(peer)) + } + + updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(users: apiBots)) + for bot in apiBots { + if let peer = transaction.getPeer(bot.peerId) { + result.append(EnginePeer(peer)) + } + } + + if let apiChannels { + switch apiChannels { + case let .chats(chats), let .chatsSlice(_, chats): + updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: AccumulatedPeers(chats: chats, users: [])) + + for chat in chats { + if let peer = transaction.getPeer(chat.peerId) { + result.append(EnginePeer(peer)) + } + } + } + } + + return result + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 09238b232f..b5f66d6f2b 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -1656,6 +1656,10 @@ public extension TelegramEngine { public func getStarRefBotConnection(id: EnginePeer.Id, targetId: EnginePeer.Id) -> Signal { return _internal_getStarRefBotConnection(account: self.account, id: id, targetId: targetId) } + + public func getPossibleStarRefBotTargets() -> Signal<[EnginePeer], NoError> { + return _internal_getPossibleStarRefBotTargets(account: self.account) + } } } diff --git a/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift b/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift index bc06084a21..3580b86fde 100644 --- a/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/AffiliateProgramSetupScreen.swift @@ -413,7 +413,7 @@ If you end your affiliate program: let availableModes: [(TelegramSuggestedStarRefBotList.SortMode, String)] = [ (.date, "Date"), (.revenue, "Revenue"), - (.commission, "Commission") + (.profitability, "Profitability") ] for (mode, title) in availableModes { let isSelected = mode == self.suggestedSortMode diff --git a/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/JoinAffiliateProgramScreen.swift b/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/JoinAffiliateProgramScreen.swift index 60f2336070..a16b6c5df0 100644 --- a/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/JoinAffiliateProgramScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/AffiliateProgramSetupScreen/Sources/JoinAffiliateProgramScreen.swift @@ -120,6 +120,9 @@ private final class JoinAffiliateProgramScreenComponent: Component { private var currentTargetPeer: EnginePeer? + private var possibleTargetPeers: [EnginePeer] = [] + private var possibleTargetPeersDisposable: Disposable? + private var cachedCloseImage: UIImage? override init(frame: CGRect) { @@ -189,6 +192,10 @@ private final class JoinAffiliateProgramScreenComponent: Component { fatalError("init(coder:) has not been implemented") } + deinit { + self.possibleTargetPeersDisposable?.dispose() + } + func scrollViewDidScroll(_ scrollView: UIScrollView) { if !self.ignoreScrolling { self.updateScrolling(transition: .immediate) @@ -338,9 +345,9 @@ private final class JoinAffiliateProgramScreenComponent: Component { let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }) - let peers: [EnginePeer] = [ + let peers: [EnginePeer] = self.possibleTargetPeers.isEmpty ? [ join.initialTargetPeer - ] + ] : self.possibleTargetPeers let avatarSize = CGSize(width: 30.0, height: 30.0) @@ -383,11 +390,24 @@ private final class JoinAffiliateProgramScreenComponent: Component { let sideInset: CGFloat = 16.0 + environment.safeInsets.left if self.component == nil { + var loadPossibleTargetPeers = false switch component.mode { case let .join(join): self.currentTargetPeer = join.initialTargetPeer + loadPossibleTargetPeers = join.canSelectTargetPeer case let .active(active): self.currentTargetPeer = active.targetPeer + loadPossibleTargetPeers = true + } + + if loadPossibleTargetPeers { + self.possibleTargetPeersDisposable = (component.context.engine.peers.getPossibleStarRefBotTargets() + |> deliverOnMainQueue).startStrict(next: { [weak self] result in + guard let self else { + return + } + self.possibleTargetPeers = result + }) } } @@ -701,6 +721,7 @@ private final class JoinAffiliateProgramScreenComponent: Component { isTargetPeerSelectable = join.canSelectTargetPeer case .active: displayTargetPeer = true + isTargetPeerSelectable = true } if displayTargetPeer { @@ -1154,7 +1175,7 @@ private final class PeerBadgeComponent: Component { if let current = self.avatarNode { avatarNode = current } else { - avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 15.0)) + avatarNode = AvatarNode(font: avatarPlaceholderFont(size: floor(avatarDiameter * 0.5))) avatarNode.isUserInteractionEnabled = false avatarNode.displaysAsynchronously = false self.avatarNode = avatarNode @@ -1252,18 +1273,13 @@ private final class AvatarComponent: Component { } final class View: UIView { - private let avatarNode: AvatarNode + private var avatarNode: AvatarNode? private var component: AvatarComponent? private weak var state: EmptyComponentState? override init(frame: CGRect) { - self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 18.0)) - self.avatarNode.displaysAsynchronously = false - super.init(frame: frame) - - self.addSubnode(self.avatarNode) } required init?(coder: NSCoder) { @@ -1276,14 +1292,24 @@ private final class AvatarComponent: Component { let size = component.size ?? availableSize - self.avatarNode.frame = CGRect(origin: CGPoint(), size: size) - self.avatarNode.setPeer( + let avatarNode: AvatarNode + if let current = self.avatarNode { + avatarNode = current + } else { + avatarNode = AvatarNode(font: avatarPlaceholderFont(size: floor(size.width * 0.5))) + avatarNode.displaysAsynchronously = false + self.avatarNode = avatarNode + self.addSubview(avatarNode.view) + } + avatarNode.frame = CGRect(origin: CGPoint(), size: size) + avatarNode.setPeer( context: component.context, theme: component.context.sharedContext.currentPresentationData.with({ $0 }).theme, peer: component.peer, synchronousLoad: true, displayDimensions: size ) + avatarNode.updateSize(size: size) return size } @@ -1634,8 +1660,8 @@ final class BotSectionSortButtonComponent: Component { switch component.sortMode { case .date: sortByString = "SORT BY [DATE]()" - case .commission: - sortByString = "SORT BY [COMMISSION]()" + case .profitability: + sortByString = "SORT BY [PROFITABILITY]()" case .revenue: sortByString = "SORT BY [REVENUE]()" } @@ -1732,7 +1758,7 @@ final class PeerBadgeAvatarComponent: Component { } final class View: UIView { - private let avatarNode: AvatarNode + private var avatarNode: AvatarNode? private let badgeBackground = UIImageView() private let badgeIcon = UIImageView() @@ -1744,12 +1770,7 @@ final class PeerBadgeAvatarComponent: Component { private static let badgeIconImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Link"), color: .white)?.withRenderingMode(.alwaysTemplate) override init(frame: CGRect) { - self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 15.0)) - self.avatarNode.displaysAsynchronously = false - super.init(frame: frame) - - self.addSubnode(self.avatarNode) } required init?(coder: NSCoder) { @@ -1765,8 +1786,18 @@ final class PeerBadgeAvatarComponent: Component { let badgeFrame = CGRect(origin: CGPoint(x: size.width - badgeSize, y: size.height - badgeSize), size: CGSize(width: badgeSize, height: badgeSize)) - self.avatarNode.frame = CGRect(origin: CGPoint(), size: size) - self.avatarNode.setPeer( + let avatarNode: AvatarNode + if let current = self.avatarNode { + avatarNode = current + } else { + avatarNode = AvatarNode(font: avatarPlaceholderFont(size: floor(size.width * 0.5))) + avatarNode.displaysAsynchronously = false + self.avatarNode = avatarNode + self.addSubview(avatarNode.view) + } + + avatarNode.frame = CGRect(origin: CGPoint(), size: size) + avatarNode.setPeer( context: component.context, theme: component.context.sharedContext.currentPresentationData.with({ $0 }).theme, peer: component.peer,