Various improvements

This commit is contained in:
Ilya Laktyushin 2025-04-17 16:28:59 +04:00
parent 02711f268d
commit 746239cf69
9 changed files with 94 additions and 29 deletions

View File

@ -2421,7 +2421,15 @@ private final class ResaleGiftsContextImpl {
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers)
return (gifts.compactMap { StarGift(apiStarGift: $0) }, resultAttributes, attributeCount, count, nextOffset)
var mappedGifts: [StarGift] = []
for gift in gifts {
if let mappedGift = StarGift(apiStarGift: gift), case let .unique(uniqueGift) = mappedGift, let resellStars = uniqueGift.resellStars, resellStars > 0 {
mappedGifts.append(mappedGift)
}
}
return (mappedGifts, resultAttributes, attributeCount, count, nextOffset)
}
}
}
@ -2434,9 +2442,7 @@ private final class ResaleGiftsContextImpl {
if initialNextOffset == nil || reload {
self.gifts = gifts
} else {
for gift in gifts {
self.gifts.append(gift)
}
self.gifts.append(contentsOf: gifts)
}
let updatedCount = max(Int32(self.gifts.count), count)

View File

@ -125,7 +125,7 @@ public extension TelegramEngine {
return _internal_transferStarGift(account: self.account, prepaid: prepaid, reference: reference, peerId: peerId)
}
public func buyStarGift(prepaid: Bool, slug: String, peerId: EnginePeer.Id) -> Signal<Never, BuyStarGiftError> {
public func buyStarGift(slug: String, peerId: EnginePeer.Id) -> Signal<Never, BuyStarGiftError> {
return _internal_buyStarGift(account: self.account, slug: slug, peerId: peerId)
}

View File

@ -2726,7 +2726,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
self.additionalPreviewView.isEnabled = false
self.collageView?.isEnabled = false
#if DEBUG
#if targetEnvironment(simulator)
#else
Queue.mainQueue().after(0.3) {

View File

@ -765,10 +765,19 @@ final class GiftStoreScreenComponent: Component {
transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) / 2.0), y: 10.0), size: titleSize))
}
let effectiveCount: Int32
if let count = self.effectiveGifts?.count {
effectiveCount = Int32(count)
} else if let resale = component.gift.availability?.resale {
effectiveCount = Int32(resale)
} else {
effectiveCount = 0
}
let subtitleSize = self.subtitle.update(
transition: transition,
component: AnyComponent(BalancedTextComponent(
text: .plain(NSAttributedString(string: "\(self.effectiveGifts?.count ?? 0) for resale", font: Font.regular(13.0), textColor: theme.rootController.navigationBar.secondaryTextColor)),
text: .plain(NSAttributedString(string: "\(effectiveCount) for resale", font: Font.regular(13.0), textColor: theme.rootController.navigationBar.secondaryTextColor)),
horizontalAlignment: .center,
maximumNumberOfLines: 1
)),
@ -927,7 +936,7 @@ final class GiftStoreScreenComponent: Component {
self.scrollView.contentSize = contentSize
self.nextScrollTransition = nil
}
let scrollInsets = UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: 0.0, right: 0.0)
let scrollInsets = UIEdgeInsets(top: topPanelHeight, left: 0.0, bottom: 0.0, right: 0.0)
if self.scrollView.scrollIndicatorInsets != scrollInsets {
self.scrollView.scrollIndicatorInsets = scrollInsets
}

View File

@ -134,6 +134,7 @@ final class LoadingShimmerNode: ASDisplayNode {
super.init()
self.allowsGroupOpacity = true
self.isUserInteractionEnabled = false
self.addSubnode(self.backgroundColorNode)

View File

@ -57,6 +57,7 @@ private final class GiftViewSheetContent: CombinedComponent {
let openMyGifts: () -> Void
let transferGift: () -> Void
let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)
let buyGift: ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>)
let shareGift: () -> Void
let resellGift: (Bool) -> Void
let showAttributeInfo: (Any, String) -> Void
@ -79,6 +80,7 @@ private final class GiftViewSheetContent: CombinedComponent {
openMyGifts: @escaping () -> Void,
transferGift: @escaping () -> Void,
upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>),
buyGift: @escaping ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>),
shareGift: @escaping () -> Void,
resellGift: @escaping (Bool) -> Void,
showAttributeInfo: @escaping (Any, String) -> Void,
@ -100,6 +102,7 @@ private final class GiftViewSheetContent: CombinedComponent {
self.openMyGifts = openMyGifts
self.transferGift = transferGift
self.upgradeGift = upgradeGift
self.buyGift = buyGift
self.shareGift = shareGift
self.resellGift = resellGift
self.showAttributeInfo = showAttributeInfo
@ -121,7 +124,10 @@ private final class GiftViewSheetContent: CombinedComponent {
final class State: ComponentState {
private let context: AccountContext
private(set) var subject: GiftViewScreen.Subject
private let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)
private let buyGift: ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>)
private let getController: () -> ViewController?
private var disposable: Disposable?
@ -171,11 +177,13 @@ private final class GiftViewSheetContent: CombinedComponent {
context: AccountContext,
subject: GiftViewScreen.Subject,
upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>),
buyGift: @escaping ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>),
getController: @escaping () -> ViewController?
) {
self.context = context
self.subject = subject
self.upgradeGift = upgradeGift
self.buyGift = buyGift
self.getController = getController
super.init()
@ -435,20 +443,8 @@ private final class GiftViewSheetContent: CombinedComponent {
self.inProgress = true
self.updated()
let signal = context.engine.payments.sendStarsPaymentForm(formId: formId, source: .starGiftResale(slug: uniqueGift.slug, toPeerId: recipientPeerId))
|> mapError { _ -> SendBotPaymentFormError in
return .generic
}
|> mapToSignal { result in
if case let .done(_, _, gift) = result, let gift {
return .single(gift)
} else {
return .complete()
}
}
self.buyDisposable = (signal
|> deliverOnMainQueue).start(next: { [weak self, weak starsContext] result in
self.buyDisposable = (self.buyGift(uniqueGift.slug, recipientPeerId)
|> deliverOnMainQueue).start(completed: { [weak self, weak starsContext] in
guard let self, let controller = self.getController() as? GiftViewScreen else {
return
}
@ -677,7 +673,7 @@ private final class GiftViewSheetContent: CombinedComponent {
}
func makeState() -> State {
return State(context: self.context, subject: self.subject, upgradeGift: self.upgradeGift, getController: self.getController)
return State(context: self.context, subject: self.subject, upgradeGift: self.upgradeGift, buyGift: self.buyGift, getController: self.getController)
}
static var body: Body {
@ -690,7 +686,6 @@ private final class GiftViewSheetContent: CombinedComponent {
let transferButton = Child(PlainButtonComponent.self)
let wearButton = Child(PlainButtonComponent.self)
// let shareButton = Child(PlainButtonComponent.self)
let resellButton = Child(PlainButtonComponent.self)
let wearAvatar = Child(AvatarComponent.self)
@ -751,6 +746,7 @@ private final class GiftViewSheetContent: CombinedComponent {
var uniqueGift: StarGift.UniqueGift?
var isSelfGift = false
var isChannelGift = false
var isMyUniqueGift = false
if case let .soldOutGift(gift) = subject {
animationFile = gift.file
@ -798,6 +794,10 @@ private final class GiftViewSheetContent: CombinedComponent {
isSelfGift = arguments.messageId?.peerId == component.context.account.peerId
if case let .peerId(peerId) = uniqueGift?.owner, peerId == component.context.account.peerId || isChannelGift {
isMyUniqueGift = true
}
if isSelfGift {
titleString = strings.Gift_View_Self_Title
} else {
@ -1753,7 +1753,7 @@ private final class GiftViewSheetContent: CombinedComponent {
}
if let uniqueGift {
if case let .peerId(peerId) = uniqueGift.owner, peerId == component.context.account.peerId || isChannelGift {
if isMyUniqueGift, case let .peerId(peerId) = uniqueGift.owner {
var canTransfer = true
if let peer = state.peerMap[peerId], case let .channel(channel) = peer, !channel.flags.contains(.isCreator) {
canTransfer = false
@ -2570,7 +2570,7 @@ private final class GiftViewSheetContent: CombinedComponent {
availableSize: buttonSize,
transition: context.transition
)
} else if !incoming, let resellStars {
} else if !incoming, let resellStars, !isMyUniqueGift {
if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme {
state.cachedStarImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: theme.list.itemCheckColors.foregroundColor)!, theme)
}
@ -2652,6 +2652,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
let openMyGifts: () -> Void
let transferGift: () -> Void
let upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)
let buyGift: ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>)
let shareGift: () -> Void
let resellGift: (Bool) -> Void
let viewUpgraded: (EngineMessage.Id) -> Void
@ -2672,6 +2673,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
openMyGifts: @escaping () -> Void,
transferGift: @escaping () -> Void,
upgradeGift: @escaping ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>),
buyGift: @escaping ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>),
shareGift: @escaping () -> Void,
resellGift: @escaping (Bool) -> Void,
viewUpgraded: @escaping (EngineMessage.Id) -> Void,
@ -2691,6 +2693,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
self.openMyGifts = openMyGifts
self.transferGift = transferGift
self.upgradeGift = upgradeGift
self.buyGift = buyGift
self.shareGift = shareGift
self.resellGift = resellGift
self.viewUpgraded = viewUpgraded
@ -2743,6 +2746,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
openMyGifts: context.component.openMyGifts,
transferGift: context.component.transferGift,
upgradeGift: context.component.upgradeGift,
buyGift: context.component.buyGift,
shareGift: context.component.shareGift,
resellGift: context.component.resellGift,
showAttributeInfo: context.component.showAttributeInfo,
@ -2772,6 +2776,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
if animated {
if let controller = controller() as? GiftViewScreen {
controller.dismissAllTooltips()
controller.dismissBalanceOverlay()
animateOut.invoke(Action { _ in
controller.dismiss(completion: nil)
})
@ -2779,6 +2784,7 @@ private final class GiftViewSheetComponent: CombinedComponent {
} else {
if let controller = controller() as? GiftViewScreen {
controller.dismissAllTooltips()
controller.dismissBalanceOverlay()
controller.dismiss(completion: nil)
}
}
@ -2913,6 +2919,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
convertToStars: (() -> Void)? = nil,
transferGift: ((Bool, EnginePeer.Id) -> Signal<Never, TransferStarGiftError>)? = nil,
upgradeGift: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)? = nil,
buyGift: ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>)? = nil,
updateResellStars: ((Int64?) -> Void)? = nil,
togglePinnedToTop: ((Bool) -> Bool)? = nil,
shareStory: ((StarGift.UniqueGift) -> Void)? = nil
@ -2930,6 +2937,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
var openMyGiftsImpl: (() -> Void)?
var transferGiftImpl: (() -> Void)?
var upgradeGiftImpl: ((Int64?, Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError>)?
var buyGiftImpl: ((String, EnginePeer.Id) -> Signal<Never, BuyStarGiftError>)?
var shareGiftImpl: (() -> Void)?
var resellGiftImpl: ((Bool) -> Void)?
var openMoreImpl: ((ASDisplayNode, ContextGesture?) -> Void)?
@ -2974,6 +2982,9 @@ public class GiftViewScreen: ViewControllerComponentContainer {
upgradeGift: { formId, keepOriginalInfo in
return upgradeGiftImpl?(formId, keepOriginalInfo) ?? .complete()
},
buyGift: { slug, peerId in
return buyGiftImpl?(slug, peerId) ?? .complete()
},
shareGift: {
shareGiftImpl?()
},
@ -3278,6 +3289,11 @@ public class GiftViewScreen: ViewControllerComponentContainer {
}
if let upgradeGift {
return upgradeGift(formId, keepOriginalInfo)
|> afterCompleted {
if formId != nil {
context.starsContext?.load(force: true)
}
}
} else {
return self.context.engine.payments.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo)
|> afterCompleted {
@ -3288,6 +3304,23 @@ public class GiftViewScreen: ViewControllerComponentContainer {
}
}
buyGiftImpl = { [weak self] slug, peerId in
guard let self else {
return .complete()
}
if let buyGift {
return buyGift(slug, peerId)
|> afterCompleted {
context.starsContext?.load(force: true)
}
} else {
return self.context.engine.payments.buyStarGift(slug: slug, peerId: peerId)
|> afterCompleted {
context.starsContext?.load(force: true)
}
}
}
shareGiftImpl = { [weak self] in
guard let self, let arguments = self.subject.arguments, case let .unique(gift) = arguments.gift else {
return
@ -3628,6 +3661,10 @@ public class GiftViewScreen: ViewControllerComponentContainer {
view.dismissAnimated()
}
self.dismissBalanceOverlay()
}
fileprivate func dismissBalanceOverlay() {
if let view = self.balanceOverlay.view, view.superview != nil {
view.layer.animateScale(from: 1.0, to: 0.8, duration: 0.4, removeOnCompletion: false)
view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)

View File

@ -4867,6 +4867,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
return profileGifts.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo)
},
buyGift: { [weak profileGifts] slug, peerId in
guard let profileGifts else {
return .never()
}
return profileGifts.buyStarGift(slug: slug, peerId: peerId)
},
shareStory: { [weak self] uniqueGift in
guard let self, let controller = self.controller else {
return

View File

@ -600,6 +600,12 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
}
return self.profileGifts.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo)
},
buyGift: { [weak self] slug, peerId in
guard let self else {
return .never()
}
return self.profileGifts.buyStarGift(slug: slug, peerId: peerId)
},
updateResellStars: { [weak self] price in
guard let self, case let .unique(uniqueGift) = product.gift else {
return

View File

@ -2987,11 +2987,11 @@ public final class SharedAccountContextImpl: SharedAccountContext {
))
controller.navigationPresentation = .modal
let _ = combineLatest(
let _ = (combineLatest(
queue: Queue.mainQueue(),
controller.result,
options.get()
).startStandalone(next: { [weak controller] result, options in
options.get())
|> take(1)).startStandalone(next: { [weak controller] result, options in
if let (peers, _, _, _, _, _) = result, let contactPeer = peers.first, case let .peer(peer, _, _) = contactPeer, let starsContext = context.starsContext {
if case .starGiftTransfer = source {
presentTransferAlertImpl?(EnginePeer(peer))