mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Various improvements
This commit is contained in:
parent
43d6e7e81c
commit
bc4b8152c3
@ -26,6 +26,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
let action: () -> Void
|
let action: () -> Void
|
||||||
let secondaryActionTitle: String?
|
let secondaryActionTitle: String?
|
||||||
let secondaryActionIcon: UIImage?
|
let secondaryActionIcon: UIImage?
|
||||||
|
let secondaryActionCooldownUntilTimestamp: Int32?
|
||||||
let secondaryAction: (() -> Void)?
|
let secondaryAction: (() -> Void)?
|
||||||
let additionalAction: AnyComponent<Empty>?
|
let additionalAction: AnyComponent<Empty>?
|
||||||
|
|
||||||
@ -43,6 +44,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
action: @escaping () -> Void,
|
action: @escaping () -> Void,
|
||||||
secondaryActionTitle: String? = nil,
|
secondaryActionTitle: String? = nil,
|
||||||
secondaryActionIcon: UIImage? = nil,
|
secondaryActionIcon: UIImage? = nil,
|
||||||
|
secondaryActionCooldownUntilTimestamp: Int32? = nil,
|
||||||
secondaryAction: (() -> Void)? = nil,
|
secondaryAction: (() -> Void)? = nil,
|
||||||
additionalAction: AnyComponent<Empty>? = nil
|
additionalAction: AnyComponent<Empty>? = nil
|
||||||
) {
|
) {
|
||||||
@ -58,6 +60,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
self.actionIcon = actionIcon
|
self.actionIcon = actionIcon
|
||||||
self.action = action
|
self.action = action
|
||||||
self.secondaryActionTitle = secondaryActionTitle
|
self.secondaryActionTitle = secondaryActionTitle
|
||||||
|
self.secondaryActionCooldownUntilTimestamp = secondaryActionCooldownUntilTimestamp
|
||||||
self.secondaryActionIcon = secondaryActionIcon
|
self.secondaryActionIcon = secondaryActionIcon
|
||||||
self.secondaryAction = secondaryAction
|
self.secondaryAction = secondaryAction
|
||||||
self.additionalAction = additionalAction
|
self.additionalAction = additionalAction
|
||||||
@ -88,6 +91,9 @@ final class StarsBalanceComponent: Component {
|
|||||||
if lhs.secondaryActionTitle != rhs.secondaryActionTitle {
|
if lhs.secondaryActionTitle != rhs.secondaryActionTitle {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.secondaryActionCooldownUntilTimestamp != rhs.secondaryActionCooldownUntilTimestamp {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.count != rhs.count {
|
if lhs.count != rhs.count {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -133,7 +139,13 @@ final class StarsBalanceComponent: Component {
|
|||||||
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
|
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
if remainingCooldownSeconds > 0 {
|
var remainingSecondaryCooldownSeconds: Int32 = 0
|
||||||
|
if let cooldownUntilTimestamp = component.secondaryActionCooldownUntilTimestamp {
|
||||||
|
remainingSecondaryCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
||||||
|
remainingSecondaryCooldownSeconds = max(0, remainingSecondaryCooldownSeconds)
|
||||||
|
}
|
||||||
|
|
||||||
|
if remainingCooldownSeconds > 0 || remainingSecondaryCooldownSeconds > 0 {
|
||||||
if self.timer == nil {
|
if self.timer == nil {
|
||||||
self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
|
self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -278,11 +290,30 @@ final class StarsBalanceComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let secondaryActionTitle = component.secondaryActionTitle {
|
if let secondaryActionTitle = component.secondaryActionTitle {
|
||||||
|
let content: AnyComponentWithIdentity<Empty>
|
||||||
var items: [AnyComponentWithIdentity<Empty>] = []
|
var items: [AnyComponentWithIdentity<Empty>] = []
|
||||||
if let icon = component.secondaryActionIcon {
|
if let icon = component.secondaryActionIcon {
|
||||||
items.append(AnyComponentWithIdentity(id: "icon", component: AnyComponent(Image(image: icon, tintColor: component.theme.list.itemCheckColors.foregroundColor, size: icon.size))))
|
items.append(AnyComponentWithIdentity(id: "icon", component: AnyComponent(Image(image: icon, tintColor: component.theme.list.itemCheckColors.foregroundColor, size: icon.size))))
|
||||||
}
|
}
|
||||||
items.append(AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: secondaryActionTitle, font: Font.semibold(17.0), color: component.theme.list.itemCheckColors.foregroundColor))))
|
if remainingSecondaryCooldownSeconds > 0 {
|
||||||
|
items.append(AnyComponentWithIdentity(id: AnyHashable(1 as Int), component: AnyComponent(
|
||||||
|
VStack([
|
||||||
|
AnyComponentWithIdentity(id: AnyHashable(1 as Int), component: AnyComponent(Text(text: secondaryActionTitle, font: Font.semibold(17.0), color: component.theme.list.itemCheckColors.foregroundColor))),
|
||||||
|
AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(HStack([
|
||||||
|
AnyComponentWithIdentity(id: 1, component: AnyComponent(BundleIconComponent(name: "Chat List/StatusLockIcon", tintColor: component.theme.list.itemCheckColors.fillColor.mixedWith(component.theme.list.itemCheckColors.foregroundColor, alpha: 0.7)))),
|
||||||
|
AnyComponentWithIdentity(id: 0, component: AnyComponent(Text(text: stringForRemainingTime(remainingSecondaryCooldownSeconds), font: Font.with(size: 11.0, weight: .medium, traits: [.monospacedNumbers]), color: component.theme.list.itemCheckColors.fillColor.mixedWith(component.theme.list.itemCheckColors.foregroundColor, alpha: 0.7))))
|
||||||
|
], spacing: 3.0)))
|
||||||
|
], spacing: 1.0)
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
items.append(AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: secondaryActionTitle, font: Font.semibold(17.0), color: component.theme.list.itemCheckColors.foregroundColor))))
|
||||||
|
}
|
||||||
|
content = AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable(0 as Int),
|
||||||
|
component: AnyComponent(
|
||||||
|
HStack(items, spacing: 7.0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
let buttonSize = self.secondaryButton.update(
|
let buttonSize = self.secondaryButton.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
@ -292,12 +323,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
foreground: component.theme.list.itemCheckColors.foregroundColor,
|
foreground: component.theme.list.itemCheckColors.foregroundColor,
|
||||||
pressedColor: component.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
|
pressedColor: component.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
|
||||||
),
|
),
|
||||||
content: AnyComponentWithIdentity(
|
content: content,
|
||||||
id: AnyHashable(0 as Int),
|
|
||||||
component: AnyComponent(
|
|
||||||
HStack(items, spacing: 7.0)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
isEnabled: component.actionIsEnabled,
|
isEnabled: component.actionIsEnabled,
|
||||||
allowActionWhenDisabled: false,
|
allowActionWhenDisabled: false,
|
||||||
displaysProgress: false,
|
displaysProgress: false,
|
||||||
|
|||||||
@ -38,6 +38,7 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
let openSubscription: (StarsContext.State.Subscription) -> Void
|
let openSubscription: (StarsContext.State.Subscription) -> Void
|
||||||
let buy: () -> Void
|
let buy: () -> Void
|
||||||
let withdraw: () -> Void
|
let withdraw: () -> Void
|
||||||
|
let showTimeoutTooltip: (Int32) -> Void
|
||||||
let gift: () -> Void
|
let gift: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@ -49,6 +50,7 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
openSubscription: @escaping (StarsContext.State.Subscription) -> Void,
|
openSubscription: @escaping (StarsContext.State.Subscription) -> Void,
|
||||||
buy: @escaping () -> Void,
|
buy: @escaping () -> Void,
|
||||||
withdraw: @escaping () -> Void,
|
withdraw: @escaping () -> Void,
|
||||||
|
showTimeoutTooltip: @escaping (Int32) -> Void,
|
||||||
gift: @escaping () -> Void
|
gift: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -59,6 +61,7 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
self.openSubscription = openSubscription
|
self.openSubscription = openSubscription
|
||||||
self.buy = buy
|
self.buy = buy
|
||||||
self.withdraw = withdraw
|
self.withdraw = withdraw
|
||||||
|
self.showTimeoutTooltip = showTimeoutTooltip
|
||||||
self.gift = gift
|
self.gift = gift
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +141,7 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
private var starsState: StarsContext.State?
|
private var starsState: StarsContext.State?
|
||||||
|
|
||||||
private var revenueStateDisposable: Disposable?
|
private var revenueStateDisposable: Disposable?
|
||||||
private var revenueState: StarsRevenueStatsContextState?
|
private var revenueState: StarsRevenueStats?
|
||||||
|
|
||||||
private var previousBalance: StarsAmount?
|
private var previousBalance: StarsAmount?
|
||||||
|
|
||||||
@ -389,7 +392,7 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.revenueState = state
|
self.revenueState = state.stats
|
||||||
|
|
||||||
if !self.isUpdating {
|
if !self.isUpdating {
|
||||||
self.state?.updated()
|
self.state?.updated()
|
||||||
@ -627,7 +630,7 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
contentHeight += descriptionSize.height
|
contentHeight += descriptionSize.height
|
||||||
contentHeight += 29.0
|
contentHeight += 29.0
|
||||||
|
|
||||||
let withdrawAvailable = self.revenueState?.stats?.balances.withdrawEnabled ?? false
|
let withdrawAvailable = self.revenueState?.balances.withdrawEnabled ?? false
|
||||||
|
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||||
let balanceSize = self.balanceView.update(
|
let balanceSize = self.balanceView.update(
|
||||||
@ -655,11 +658,24 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
},
|
},
|
||||||
secondaryActionTitle: withdrawAvailable ? environment.strings.Stars_Intro_Withdraw : nil,
|
secondaryActionTitle: withdrawAvailable ? environment.strings.Stars_Intro_Withdraw : nil,
|
||||||
secondaryActionIcon: withdrawAvailable ? PresentationResourcesItemList.itemListRoundWithdrawIcon(environment.theme) : nil,
|
secondaryActionIcon: withdrawAvailable ? PresentationResourcesItemList.itemListRoundWithdrawIcon(environment.theme) : nil,
|
||||||
|
secondaryActionCooldownUntilTimestamp: self.revenueState?.balances.nextWithdrawalTimestamp,
|
||||||
secondaryAction: withdrawAvailable ? { [weak self] in
|
secondaryAction: withdrawAvailable ? { [weak self] in
|
||||||
guard let self, let component = self.component else {
|
guard let self, let component = self.component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
component.withdraw()
|
var remainingCooldownSeconds: Int32 = 0
|
||||||
|
if let cooldownUntilTimestamp = self.revenueState?.balances.nextWithdrawalTimestamp {
|
||||||
|
remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
||||||
|
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
|
||||||
|
|
||||||
|
if remainingCooldownSeconds > 0 {
|
||||||
|
component.showTimeoutTooltip(cooldownUntilTimestamp)
|
||||||
|
} else {
|
||||||
|
component.withdraw()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
component.withdraw()
|
||||||
|
}
|
||||||
} : nil,
|
} : nil,
|
||||||
additionalAction: (premiumConfiguration.starsGiftsPurchaseAvailable && !premiumConfiguration.isPremiumDisabled) ? AnyComponent(
|
additionalAction: (premiumConfiguration.starsGiftsPurchaseAvailable && !premiumConfiguration.isPremiumDisabled) ? AnyComponent(
|
||||||
Button(
|
Button(
|
||||||
@ -1085,6 +1101,9 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
|||||||
|
|
||||||
private let navigateDisposable = MetaDisposable()
|
private let navigateDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
private weak var tooltipScreen: UndoOverlayController?
|
||||||
|
private var timer: Foundation.Timer?
|
||||||
|
|
||||||
public init(context: AccountContext, starsContext: StarsContext, forceDark: Bool = false) {
|
public init(context: AccountContext, starsContext: StarsContext, forceDark: Bool = false) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.starsContext = starsContext
|
self.starsContext = starsContext
|
||||||
@ -1094,6 +1113,7 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
|||||||
|
|
||||||
var buyImpl: (() -> Void)?
|
var buyImpl: (() -> Void)?
|
||||||
var withdrawImpl: (() -> Void)?
|
var withdrawImpl: (() -> Void)?
|
||||||
|
var showTimeoutTooltipImpl: ((Int32) -> Void)?
|
||||||
var giftImpl: (() -> Void)?
|
var giftImpl: (() -> Void)?
|
||||||
var openTransactionImpl: ((StarsContext.State.Transaction) -> Void)?
|
var openTransactionImpl: ((StarsContext.State.Transaction) -> Void)?
|
||||||
var openSubscriptionImpl: ((StarsContext.State.Subscription) -> Void)?
|
var openSubscriptionImpl: ((StarsContext.State.Subscription) -> Void)?
|
||||||
@ -1114,6 +1134,9 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
|||||||
withdraw: {
|
withdraw: {
|
||||||
withdrawImpl?()
|
withdrawImpl?()
|
||||||
},
|
},
|
||||||
|
showTimeoutTooltip: { timestamp in
|
||||||
|
showTimeoutTooltipImpl?(timestamp)
|
||||||
|
},
|
||||||
gift: {
|
gift: {
|
||||||
giftImpl?()
|
giftImpl?()
|
||||||
}
|
}
|
||||||
@ -1234,12 +1257,12 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
|||||||
}
|
}
|
||||||
let controller = confirmStarsRevenueWithdrawalController(context: context, peerId: context.account.peerId, amount: amount, present: { [weak self] c, a in
|
let controller = confirmStarsRevenueWithdrawalController(context: context, peerId: context.account.peerId, amount: amount, present: { [weak self] c, a in
|
||||||
self?.present(c, in: .window(.root))
|
self?.present(c, in: .window(.root))
|
||||||
}, completion: { url in
|
}, completion: { [weak self] url in
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
|
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
|
||||||
|
|
||||||
Queue.mainQueue().after(2.0) {
|
Queue.mainQueue().after(2.0) {
|
||||||
context.starsContext?.load(force: true)
|
self?.starsRevenueStatsContext.reload()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
self.present(controller, in: .window(.root))
|
self.present(controller, in: .window(.root))
|
||||||
@ -1257,6 +1280,59 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showTimeoutTooltipImpl = { [weak self] cooldownUntilTimestamp in
|
||||||
|
guard let self, self.tooltipScreen == nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
||||||
|
|
||||||
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
let content: UndoOverlayContent = .universal(
|
||||||
|
animation: "anim_clock",
|
||||||
|
scale: 0.058,
|
||||||
|
colors: [:],
|
||||||
|
title: nil,
|
||||||
|
text: presentationData.strings.Stars_Withdraw_Withdraw_ErrorTimeout(stringForRemainingTime(remainingCooldownSeconds)).string,
|
||||||
|
customUndoText: nil,
|
||||||
|
timeout: nil
|
||||||
|
)
|
||||||
|
let controller = UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
self.tooltipScreen = controller
|
||||||
|
self.present(controller, in: .window(.root))
|
||||||
|
|
||||||
|
if remainingCooldownSeconds < 3600 {
|
||||||
|
if self.timer == nil {
|
||||||
|
self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let tooltipScreen = self.tooltipScreen {
|
||||||
|
let remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
||||||
|
let content: UndoOverlayContent = .universal(
|
||||||
|
animation: "anim_clock",
|
||||||
|
scale: 0.058,
|
||||||
|
colors: [:],
|
||||||
|
title: nil,
|
||||||
|
text: presentationData.strings.Stars_Withdraw_Withdraw_ErrorTimeout(stringForRemainingTime(remainingCooldownSeconds)).string,
|
||||||
|
customUndoText: nil,
|
||||||
|
timeout: nil
|
||||||
|
)
|
||||||
|
tooltipScreen.content = content
|
||||||
|
} else {
|
||||||
|
if let timer = self.timer {
|
||||||
|
self.timer = nil
|
||||||
|
timer.invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
giftImpl = { [weak self] in
|
giftImpl = { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user