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) let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) 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 { if initialNextOffset == nil || reload {
self.gifts = gifts self.gifts = gifts
} else { } else {
for gift in gifts { self.gifts.append(contentsOf: gifts)
self.gifts.append(gift)
}
} }
let updatedCount = max(Int32(self.gifts.count), count) 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) 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) 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.additionalPreviewView.isEnabled = false
self.collageView?.isEnabled = false self.collageView?.isEnabled = false
#if DEBUG #if targetEnvironment(simulator)
#else #else
Queue.mainQueue().after(0.3) { 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)) 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( let subtitleSize = self.subtitle.update(
transition: transition, transition: transition,
component: AnyComponent(BalancedTextComponent( 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, horizontalAlignment: .center,
maximumNumberOfLines: 1 maximumNumberOfLines: 1
)), )),
@ -927,7 +936,7 @@ final class GiftStoreScreenComponent: Component {
self.scrollView.contentSize = contentSize self.scrollView.contentSize = contentSize
self.nextScrollTransition = nil 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 { if self.scrollView.scrollIndicatorInsets != scrollInsets {
self.scrollView.scrollIndicatorInsets = scrollInsets self.scrollView.scrollIndicatorInsets = scrollInsets
} }

View File

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

View File

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

View File

@ -600,6 +600,12 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
return self.profileGifts.upgradeStarGift(formId: formId, reference: reference, keepOriginalInfo: keepOriginalInfo) 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 updateResellStars: { [weak self] price in
guard let self, case let .unique(uniqueGift) = product.gift else { guard let self, case let .unique(uniqueGift) = product.gift else {
return return

View File

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