Skip to content

Commit bc4b815

Browse files
committed
Various improvements
1 parent 43d6e7e commit bc4b815

File tree

2 files changed

+116
-14
lines changed

2 files changed

+116
-14
lines changed

submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsBalanceComponent.swift

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ final class StarsBalanceComponent: Component {
2626
let action: () -> Void
2727
let secondaryActionTitle: String?
2828
let secondaryActionIcon: UIImage?
29+
let secondaryActionCooldownUntilTimestamp: Int32?
2930
let secondaryAction: (() -> Void)?
3031
let additionalAction: AnyComponent<Empty>?
3132

@@ -43,6 +44,7 @@ final class StarsBalanceComponent: Component {
4344
action: @escaping () -> Void,
4445
secondaryActionTitle: String? = nil,
4546
secondaryActionIcon: UIImage? = nil,
47+
secondaryActionCooldownUntilTimestamp: Int32? = nil,
4648
secondaryAction: (() -> Void)? = nil,
4749
additionalAction: AnyComponent<Empty>? = nil
4850
) {
@@ -58,6 +60,7 @@ final class StarsBalanceComponent: Component {
5860
self.actionIcon = actionIcon
5961
self.action = action
6062
self.secondaryActionTitle = secondaryActionTitle
63+
self.secondaryActionCooldownUntilTimestamp = secondaryActionCooldownUntilTimestamp
6164
self.secondaryActionIcon = secondaryActionIcon
6265
self.secondaryAction = secondaryAction
6366
self.additionalAction = additionalAction
@@ -88,6 +91,9 @@ final class StarsBalanceComponent: Component {
8891
if lhs.secondaryActionTitle != rhs.secondaryActionTitle {
8992
return false
9093
}
94+
if lhs.secondaryActionCooldownUntilTimestamp != rhs.secondaryActionCooldownUntilTimestamp {
95+
return false
96+
}
9197
if lhs.count != rhs.count {
9298
return false
9399
}
@@ -133,7 +139,13 @@ final class StarsBalanceComponent: Component {
133139
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
134140
}
135141

136-
if remainingCooldownSeconds > 0 {
142+
var remainingSecondaryCooldownSeconds: Int32 = 0
143+
if let cooldownUntilTimestamp = component.secondaryActionCooldownUntilTimestamp {
144+
remainingSecondaryCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
145+
remainingSecondaryCooldownSeconds = max(0, remainingSecondaryCooldownSeconds)
146+
}
147+
148+
if remainingCooldownSeconds > 0 || remainingSecondaryCooldownSeconds > 0 {
137149
if self.timer == nil {
138150
self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
139151
guard let self else {
@@ -278,11 +290,30 @@ final class StarsBalanceComponent: Component {
278290
}
279291

280292
if let secondaryActionTitle = component.secondaryActionTitle {
293+
let content: AnyComponentWithIdentity<Empty>
281294
var items: [AnyComponentWithIdentity<Empty>] = []
282295
if let icon = component.secondaryActionIcon {
283296
items.append(AnyComponentWithIdentity(id: "icon", component: AnyComponent(Image(image: icon, tintColor: component.theme.list.itemCheckColors.foregroundColor, size: icon.size))))
284297
}
285-
items.append(AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: secondaryActionTitle, font: Font.semibold(17.0), color: component.theme.list.itemCheckColors.foregroundColor))))
298+
if remainingSecondaryCooldownSeconds > 0 {
299+
items.append(AnyComponentWithIdentity(id: AnyHashable(1 as Int), component: AnyComponent(
300+
VStack([
301+
AnyComponentWithIdentity(id: AnyHashable(1 as Int), component: AnyComponent(Text(text: secondaryActionTitle, font: Font.semibold(17.0), color: component.theme.list.itemCheckColors.foregroundColor))),
302+
AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent(HStack([
303+
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)))),
304+
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))))
305+
], spacing: 3.0)))
306+
], spacing: 1.0)
307+
)))
308+
} else {
309+
items.append(AnyComponentWithIdentity(id: "label", component: AnyComponent(Text(text: secondaryActionTitle, font: Font.semibold(17.0), color: component.theme.list.itemCheckColors.foregroundColor))))
310+
}
311+
content = AnyComponentWithIdentity(
312+
id: AnyHashable(0 as Int),
313+
component: AnyComponent(
314+
HStack(items, spacing: 7.0)
315+
)
316+
)
286317

287318
let buttonSize = self.secondaryButton.update(
288319
transition: transition,
@@ -292,12 +323,7 @@ final class StarsBalanceComponent: Component {
292323
foreground: component.theme.list.itemCheckColors.foregroundColor,
293324
pressedColor: component.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
294325
),
295-
content: AnyComponentWithIdentity(
296-
id: AnyHashable(0 as Int),
297-
component: AnyComponent(
298-
HStack(items, spacing: 7.0)
299-
)
300-
),
326+
content: content,
301327
isEnabled: component.actionIsEnabled,
302328
allowActionWhenDisabled: false,
303329
displaysProgress: false,

submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ final class StarsTransactionsScreenComponent: Component {
3838
let openSubscription: (StarsContext.State.Subscription) -> Void
3939
let buy: () -> Void
4040
let withdraw: () -> Void
41+
let showTimeoutTooltip: (Int32) -> Void
4142
let gift: () -> Void
4243

4344
init(
@@ -49,6 +50,7 @@ final class StarsTransactionsScreenComponent: Component {
4950
openSubscription: @escaping (StarsContext.State.Subscription) -> Void,
5051
buy: @escaping () -> Void,
5152
withdraw: @escaping () -> Void,
53+
showTimeoutTooltip: @escaping (Int32) -> Void,
5254
gift: @escaping () -> Void
5355
) {
5456
self.context = context
@@ -59,6 +61,7 @@ final class StarsTransactionsScreenComponent: Component {
5961
self.openSubscription = openSubscription
6062
self.buy = buy
6163
self.withdraw = withdraw
64+
self.showTimeoutTooltip = showTimeoutTooltip
6265
self.gift = gift
6366
}
6467

@@ -138,7 +141,7 @@ final class StarsTransactionsScreenComponent: Component {
138141
private var starsState: StarsContext.State?
139142

140143
private var revenueStateDisposable: Disposable?
141-
private var revenueState: StarsRevenueStatsContextState?
144+
private var revenueState: StarsRevenueStats?
142145

143146
private var previousBalance: StarsAmount?
144147

@@ -389,7 +392,7 @@ final class StarsTransactionsScreenComponent: Component {
389392
guard let self else {
390393
return
391394
}
392-
self.revenueState = state
395+
self.revenueState = state.stats
393396

394397
if !self.isUpdating {
395398
self.state?.updated()
@@ -627,7 +630,7 @@ final class StarsTransactionsScreenComponent: Component {
627630
contentHeight += descriptionSize.height
628631
contentHeight += 29.0
629632

630-
let withdrawAvailable = self.revenueState?.stats?.balances.withdrawEnabled ?? false
633+
let withdrawAvailable = self.revenueState?.balances.withdrawEnabled ?? false
631634

632635
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
633636
let balanceSize = self.balanceView.update(
@@ -655,11 +658,24 @@ final class StarsTransactionsScreenComponent: Component {
655658
},
656659
secondaryActionTitle: withdrawAvailable ? environment.strings.Stars_Intro_Withdraw : nil,
657660
secondaryActionIcon: withdrawAvailable ? PresentationResourcesItemList.itemListRoundWithdrawIcon(environment.theme) : nil,
661+
secondaryActionCooldownUntilTimestamp: self.revenueState?.balances.nextWithdrawalTimestamp,
658662
secondaryAction: withdrawAvailable ? { [weak self] in
659663
guard let self, let component = self.component else {
660664
return
661665
}
662-
component.withdraw()
666+
var remainingCooldownSeconds: Int32 = 0
667+
if let cooldownUntilTimestamp = self.revenueState?.balances.nextWithdrawalTimestamp {
668+
remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
669+
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
670+
671+
if remainingCooldownSeconds > 0 {
672+
component.showTimeoutTooltip(cooldownUntilTimestamp)
673+
} else {
674+
component.withdraw()
675+
}
676+
} else {
677+
component.withdraw()
678+
}
663679
} : nil,
664680
additionalAction: (premiumConfiguration.starsGiftsPurchaseAvailable && !premiumConfiguration.isPremiumDisabled) ? AnyComponent(
665681
Button(
@@ -1085,6 +1101,9 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
10851101

10861102
private let navigateDisposable = MetaDisposable()
10871103

1104+
private weak var tooltipScreen: UndoOverlayController?
1105+
private var timer: Foundation.Timer?
1106+
10881107
public init(context: AccountContext, starsContext: StarsContext, forceDark: Bool = false) {
10891108
self.context = context
10901109
self.starsContext = starsContext
@@ -1094,6 +1113,7 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
10941113

10951114
var buyImpl: (() -> Void)?
10961115
var withdrawImpl: (() -> Void)?
1116+
var showTimeoutTooltipImpl: ((Int32) -> Void)?
10971117
var giftImpl: (() -> Void)?
10981118
var openTransactionImpl: ((StarsContext.State.Transaction) -> Void)?
10991119
var openSubscriptionImpl: ((StarsContext.State.Subscription) -> Void)?
@@ -1114,6 +1134,9 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
11141134
withdraw: {
11151135
withdrawImpl?()
11161136
},
1137+
showTimeoutTooltip: { timestamp in
1138+
showTimeoutTooltipImpl?(timestamp)
1139+
},
11171140
gift: {
11181141
giftImpl?()
11191142
}
@@ -1234,12 +1257,12 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
12341257
}
12351258
let controller = confirmStarsRevenueWithdrawalController(context: context, peerId: context.account.peerId, amount: amount, present: { [weak self] c, a in
12361259
self?.present(c, in: .window(.root))
1237-
}, completion: { url in
1260+
}, completion: { [weak self] url in
12381261
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
12391262
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: true, presentationData: presentationData, navigationController: nil, dismissInput: {})
12401263

12411264
Queue.mainQueue().after(2.0) {
1242-
context.starsContext?.load(force: true)
1265+
self?.starsRevenueStatsContext.reload()
12431266
}
12441267
})
12451268
self.present(controller, in: .window(.root))
@@ -1257,6 +1280,59 @@ public final class StarsTransactionsScreen: ViewControllerComponentContainer {
12571280
})
12581281
}
12591282

1283+
showTimeoutTooltipImpl = { [weak self] cooldownUntilTimestamp in
1284+
guard let self, self.tooltipScreen == nil else {
1285+
return
1286+
}
1287+
1288+
let remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
1289+
1290+
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
1291+
let content: UndoOverlayContent = .universal(
1292+
animation: "anim_clock",
1293+
scale: 0.058,
1294+
colors: [:],
1295+
title: nil,
1296+
text: presentationData.strings.Stars_Withdraw_Withdraw_ErrorTimeout(stringForRemainingTime(remainingCooldownSeconds)).string,
1297+
customUndoText: nil,
1298+
timeout: nil
1299+
)
1300+
let controller = UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in
1301+
return true
1302+
})
1303+
self.tooltipScreen = controller
1304+
self.present(controller, in: .window(.root))
1305+
1306+
if remainingCooldownSeconds < 3600 {
1307+
if self.timer == nil {
1308+
self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
1309+
guard let self else {
1310+
return
1311+
}
1312+
1313+
if let tooltipScreen = self.tooltipScreen {
1314+
let remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
1315+
let content: UndoOverlayContent = .universal(
1316+
animation: "anim_clock",
1317+
scale: 0.058,
1318+
colors: [:],
1319+
title: nil,
1320+
text: presentationData.strings.Stars_Withdraw_Withdraw_ErrorTimeout(stringForRemainingTime(remainingCooldownSeconds)).string,
1321+
customUndoText: nil,
1322+
timeout: nil
1323+
)
1324+
tooltipScreen.content = content
1325+
} else {
1326+
if let timer = self.timer {
1327+
self.timer = nil
1328+
timer.invalidate()
1329+
}
1330+
}
1331+
})
1332+
}
1333+
}
1334+
}
1335+
12601336
giftImpl = { [weak self] in
12611337
guard let self else {
12621338
return

0 commit comments

Comments
 (0)