diff --git a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift index 1d2a35b0c5..3d6ce5ecdc 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkEditController.swift @@ -479,7 +479,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry { } } -private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: InviteLinkEditControllerState, isGroup: Bool, isPublic: Bool, presentationData: PresentationData, starsState: StarsRevenueStats?, configuration: StarsSubscriptionConfiguration) -> [InviteLinksEditEntry] { +private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: InviteLinkEditControllerState, isGroup: Bool, isPublic: Bool, presentationData: PresentationData, configuration: StarsSubscriptionConfiguration) -> [InviteLinksEditEntry] { var entries: [InviteLinksEditEntry] = [] entries.append(.titleHeader(presentationData.theme, presentationData.strings.InviteLink_Create_LinkNameTitle.uppercased())) @@ -492,8 +492,12 @@ private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: entries.append(.subscriptionFeeToggle(presentationData.theme, presentationData.strings.InviteLink_Create_Fee, state.subscriptionEnabled, isEditingEnabled)) if state.subscriptionEnabled { var label: String = "" - if let subscriptionFee = state.subscriptionFee, subscriptionFee > 0, let starsState { - label = presentationData.strings.InviteLink_Create_FeePerMonth("≈\(formatTonUsdValue(subscriptionFee, divide: false, rate: starsState.usdRate, dateTimeFormat: presentationData.dateTimeFormat))").string + if let subscriptionFee = state.subscriptionFee, subscriptionFee > 0 { + var usdRate = 0.012 + if let usdWithdrawRate = configuration.usdWithdrawRate { + usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0 + } + label = presentationData.strings.InviteLink_Create_FeePerMonth("≈\(formatTonUsdValue(subscriptionFee, divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))").string } entries.append(.subscriptionFee(presentationData.theme, presentationData.strings.InviteLink_Create_FeePlaceholder, isEditingEnabled, state.subscriptionFee, label, configuration.maxFee)) } @@ -569,7 +573,7 @@ private struct InviteLinkEditControllerState: Equatable { var updating = false } -public func inviteLinkEditController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, invite: ExportedInvitation?, starsState: StarsRevenueStats? = nil, completion: ((ExportedInvitation?) -> Void)? = nil) -> ViewController { +public func inviteLinkEditController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, invite: ExportedInvitation?, completion: ((ExportedInvitation?) -> Void)? = nil) -> ViewController { var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? let actionsDisposable = DisposableSet() @@ -791,7 +795,7 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(invite == nil ? presentationData.strings.InviteLink_Create_Title : presentationData.strings.InviteLink_Create_EditTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkEditControllerEntries(invite: invite, state: state, isGroup: isGroup, isPublic: isPublic, presentationData: presentationData, starsState: starsState, configuration: configuration), style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkEditControllerEntries(invite: invite, state: state, isGroup: isGroup, isPublic: isPublic, presentationData: presentationData, configuration: configuration), style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges) return (controllerState, (listState, arguments)) } @@ -854,22 +858,22 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio return controller } -private struct StarsSubscriptionConfiguration { +struct StarsSubscriptionConfiguration { static var defaultValue: StarsSubscriptionConfiguration { - return StarsSubscriptionConfiguration(maxFee: 2500, usdSellRate: 2000) + return StarsSubscriptionConfiguration(maxFee: 2500, usdWithdrawRate: 1200) } let maxFee: Int64? - let usdSellRate: Int64? + let usdWithdrawRate: Int64? - fileprivate init(maxFee: Int64?, usdSellRate: Int64?) { + fileprivate init(maxFee: Int64?, usdWithdrawRate: Int64?) { self.maxFee = maxFee - self.usdSellRate = usdSellRate + self.usdWithdrawRate = usdWithdrawRate } public static func with(appConfiguration: AppConfiguration) -> StarsSubscriptionConfiguration { - 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), usdSellRate: Int64(usdRate)) + if let data = appConfiguration.data, let value = data["stars_subscription_amount_max"] as? Double, let usdRate = data["stars_usd_withdraw_rate_x1000"] as? Double { + return StarsSubscriptionConfiguration(maxFee: Int64(value), usdWithdrawRate: Int64(usdRate)) } else { return .defaultValue } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift index 2473129fac..ff177a97be 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift @@ -268,7 +268,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry { } } -private func inviteLinkListControllerEntries(presentationData: PresentationData, exportedInvitation: EngineExportedPeerInvitation?, peer: EnginePeer?, invites: [ExportedInvitation]?, revokedInvites: [ExportedInvitation]?, importers: PeerInvitationImportersState?, creators: [ExportedInvitationCreator], admin: ExportedInvitationCreator?, tick: Int32, starsState: StarsRevenueStats?) -> [InviteLinksListEntry] { +private func inviteLinkListControllerEntries(presentationData: PresentationData, exportedInvitation: EngineExportedPeerInvitation?, peer: EnginePeer?, invites: [ExportedInvitation]?, revokedInvites: [ExportedInvitation]?, importers: PeerInvitationImportersState?, creators: [ExportedInvitationCreator], admin: ExportedInvitationCreator?, tick: Int32) -> [InviteLinksListEntry] { var entries: [InviteLinksListEntry] = [] if admin == nil { @@ -393,7 +393,7 @@ private struct InviteLinkListControllerState: Equatable { var revokingPrivateLink: Bool } -public func inviteLinkListController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, admin: ExportedInvitationCreator?, starsRevenueContext: StarsRevenueStatsContext? = nil) -> ViewController { +public func inviteLinkListController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, admin: ExportedInvitationCreator?) -> ViewController { var pushControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? var presentInGlobalOverlayImpl: ((ViewController) -> Void)? @@ -408,10 +408,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio let updateState: ((InviteLinkListControllerState) -> InviteLinkListControllerState) -> Void = { f in statePromise.set(stateValue.modify { f($0) }) } - - let starsContext: StarsRevenueStatsContext = starsRevenueContext ?? context.engine.payments.peerStarsRevenueContext(peerId: peerId) - let starsStats = Atomic(value: nil) - + let revokeLinkDisposable = MetaDisposable() actionsDisposable.add(revokeLinkDisposable) @@ -490,7 +487,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio } presentControllerImpl?(shareController, nil) }, openMainLink: { invite in - let controller = InviteLinkViewController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: invite, invitationsContext: nil, revokedInvitationsContext: revokedInvitesContext, importersContext: nil, starsState: starsStats.with { $0 }) + let controller = InviteLinkViewController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: invite, invitationsContext: nil, revokedInvitationsContext: revokedInvitesContext, importersContext: nil) pushControllerImpl?(controller) }, copyLink: { invite in UIPasteboard.general.string = invite.link @@ -607,7 +604,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio let contextController = ContextController(presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture) presentInGlobalOverlayImpl?(contextController) }, createLink: { - let controller = inviteLinkEditController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: nil, starsState: starsStats.with( { $0 }), completion: { invite in + let controller = inviteLinkEditController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: nil, completion: { invite in if let invite = invite { invitesContext.add(invite) } @@ -616,7 +613,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio pushControllerImpl?(controller) }, openLink: { invite in if let invite = invite { - let controller = InviteLinkViewController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: invite, invitationsContext: invitesContext, revokedInvitationsContext: revokedInvitesContext, importersContext: nil, starsState: starsStats.with { $0 }) + let controller = InviteLinkViewController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: invite, invitationsContext: invitesContext, revokedInvitationsContext: revokedInvitesContext, importersContext: nil) pushControllerImpl?(controller) } }, linkContextAction: { invite, canEdit, node, gesture in @@ -733,7 +730,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio }, action: { _, f in f(.default) - let controller = inviteLinkEditController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: invite, starsState: starsStats.with( { $0 }), completion: { invite in + let controller = inviteLinkEditController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: invite, completion: { invite in if let invite = invite { if invite.isRevoked { invitesContext.remove(invite) @@ -900,14 +897,12 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio invitesContext.state, revokedInvitesContext.state, creators, - timerPromise.get(), - starsContext.state + timerPromise.get() ) - |> map { presentationData, exportedInvitation, peer, importersContext, importers, invites, revokedInvites, creators, tick, starsState -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, exportedInvitation, peer, importersContext, importers, invites, revokedInvites, creators, tick -> (ItemListControllerState, (ItemListNodeState, Any)) in let previousInvites = previousInvites.swap(invites) let previousRevokedInvites = previousRevokedInvites.swap(revokedInvites) let previousCreators = previousCreators.swap(creators) - let _ = starsStats.swap(starsState.stats) var crossfade = false if (previousInvites?.hasLoadedOnce ?? false) != (invites.hasLoadedOnce) { @@ -933,7 +928,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: title, leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkListControllerEntries(presentationData: presentationData, exportedInvitation: exportedInvitation, peer: peer, invites: invites.hasLoadedOnce ? invites.invitations : nil, revokedInvites: revokedInvites.hasLoadedOnce ? revokedInvites.invitations : nil, importers: importers, creators: creators, admin: admin, tick: tick, starsState: starsState.stats), style: .blocks, emptyStateItem: nil, crossfadeState: crossfade, animateChanges: animateChanges) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkListControllerEntries(presentationData: presentationData, exportedInvitation: exportedInvitation, peer: peer, invites: invites.hasLoadedOnce ? invites.invitations : nil, revokedInvites: revokedInvites.hasLoadedOnce ? revokedInvites.invitations : nil, importers: importers, creators: creators, admin: admin, tick: tick), style: .blocks, emptyStateItem: nil, crossfadeState: crossfade, animateChanges: animateChanges) return (controllerState, (listState, arguments)) } diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index fac7a302e2..442350e641 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -380,20 +380,18 @@ public final class InviteLinkViewController: ViewController { private let invitationsContext: PeerExportedInvitationsContext? private let revokedInvitationsContext: PeerExportedInvitationsContext? private let importersContext: PeerInvitationImportersContext? - private let starsState: StarsRevenueStats? private var presentationData: PresentationData private var presentationDataDisposable: Disposable? fileprivate var presentationDataPromise = Promise() - public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, invite: ExportedInvitation, invitationsContext: PeerExportedInvitationsContext?, revokedInvitationsContext: PeerExportedInvitationsContext?, importersContext: PeerInvitationImportersContext?, starsState: StarsRevenueStats? = nil) { + public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, peerId: EnginePeer.Id, invite: ExportedInvitation, invitationsContext: PeerExportedInvitationsContext?, revokedInvitationsContext: PeerExportedInvitationsContext?, importersContext: PeerInvitationImportersContext?) { self.context = context self.peerId = peerId self.invite = invite self.invitationsContext = invitationsContext self.revokedInvitationsContext = revokedInvitationsContext self.importersContext = importersContext - self.starsState = starsState self.presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } @@ -522,6 +520,8 @@ public final class InviteLinkViewController: ViewController { self.presentationDataPromise = Promise(self.presentationData) self.controller = controller + let configuration = StarsSubscriptionConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + self.importersContext = importersContext ?? context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: false)) if case let .link(_, _, _, requestApproval, _, _, _, _, _, _, _, _, _) = invite, requestApproval { self.requestsContext = context.engine.peers.peerInvitationImporters(peerId: peerId, subject: .invite(invite: invite, requested: true)) @@ -589,15 +589,16 @@ public final class InviteLinkViewController: ViewController { } }) }, openSubscription: { [weak self] pricing, importer in - guard let controller = self?.controller else { - return - } let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) - |> deliverOnMainQueue).start(next: { peer in + |> deliverOnMainQueue).start(next: { [weak self] peer in guard let peer else { return } - let subscriptionController = context.sharedContext.makeStarsSubscriptionScreen(context: context, peer: peer, pricing: pricing, importer: importer, usdRate: controller.starsState?.usdRate ?? 0.0) + var usdRate = 0.012 + if let usdWithdrawRate = configuration.usdWithdrawRate { + usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0 + } + let subscriptionController = context.sharedContext.makeStarsSubscriptionScreen(context: context, peer: peer, pricing: pricing, importer: importer, usdRate: usdRate) self?.controller?.push(subscriptionController) }) }, copyLink: { [weak self] invite in @@ -824,7 +825,7 @@ public final class InviteLinkViewController: ViewController { } else { requestsState = .single(PeerInvitationImportersState.Empty) } - + if case let .link(_, _, _, _, _, adminId, date, _, _, usageLimit, _, _, _) = invite { self.disposable = (combineLatest( self.presentationDataPromise.get(), @@ -833,8 +834,11 @@ public final class InviteLinkViewController: ViewController { context.account.postbox.loadedPeerWithId(adminId) ) |> deliverOnMainQueue).start(next: { [weak self] presentationData, state, requestsState, creatorPeer in if let strongSelf = self { - let usdRate = strongSelf.controller?.starsState?.usdRate - + var usdRate = 0.012 + if let usdWithdrawRate = configuration.usdWithdrawRate { + usdRate = Double(usdWithdrawRate) / 1000.0 / 100.0 + } + var entries: [InviteLinkViewEntry] = [] entries.append(.link(presentationData.theme, invite)) @@ -845,12 +849,8 @@ public final class InviteLinkViewController: ViewController { var subtitle = presentationData.strings.InviteLink_SubscriptionFee_NoOneJoined if state.count > 0 { title += " x \(state.count)" - if let usdRate { - let usdValue = formatTonUsdValue(pricing.amount * Int64(state.count), divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat) - subtitle = presentationData.strings.InviteLink_SubscriptionFee_ApproximateIncome(usdValue).string - } else { - subtitle = "" - } + let usdValue = formatTonUsdValue(pricing.amount * Int64(state.count), divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat) + subtitle = presentationData.strings.InviteLink_SubscriptionFee_ApproximateIncome(usdValue).string } entries.append(.subscriptionPricing(presentationData.theme, title, subtitle)) } @@ -1001,7 +1001,7 @@ public final class InviteLinkViewController: ViewController { let revokedInvitationsContext = parentController.revokedInvitationsContext if let navigationController = navigationController { let updatedPresentationData = (self.presentationData, parentController.presentationDataPromise.get()) - let controller = inviteLinkEditController(context: self.context, updatedPresentationData: updatedPresentationData, peerId: self.peerId, invite: self.invite, starsState: self.controller?.starsState, completion: { [weak self] invite in + let controller = inviteLinkEditController(context: self.context, updatedPresentationData: updatedPresentationData, peerId: self.peerId, invite: self.invite, completion: { [weak self] invite in if let invite = invite { if invite.isRevoked { invitationsContext?.remove(invite) diff --git a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift index e272dca7a2..335f76f486 100644 --- a/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsControllerNode.swift @@ -217,8 +217,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { invite: invite, invitationsContext: nil, revokedInvitationsContext: nil, - importersContext: nil, - starsState: strongSelf.controller?.starsState + importersContext: nil ) strongSelf.pushController(controller) } diff --git a/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift b/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift index 0ea22e1777..7554de748b 100644 --- a/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsPurchaseScreen/Sources/StarsPurchaseScreen.swift @@ -467,7 +467,7 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent { } }, tapAction: { attributes, _ in - component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: strings.Stars_Purchase_Terms_URL, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {}) + component.context.sharedContext.openExternalUrl(context: component.context, urlContext: .generic, url: strings.Stars_Purchase_Terms_URL, forceExternal: false, presentationData: presentationData, navigationController: nil, dismissInput: {}) } ), environment: {},