mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Update API
This commit is contained in:
parent
1be0aaef7c
commit
e680691988
15 changed files with 592 additions and 95 deletions
|
|
@ -1423,8 +1423,8 @@ public protocol SharedAccountContext: AnyObject {
|
|||
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: ((StarGift.UniqueGift) -> Void)?, openChatTheme: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
|
||||
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift.UniqueGift) -> ViewController
|
||||
func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController
|
||||
func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
||||
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController
|
||||
func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, auctionContext: GiftAuctionContext) -> ViewController
|
||||
func makeGiftAuctionViewScreen(context: AccountContext, toPeerId: EnginePeer.Id, auctionContext: GiftAuctionContext) -> ViewController
|
||||
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
|
||||
|
||||
func makeStorySharingScreen(context: AccountContext, subject: StorySharingSubject, parentController: ViewController) -> ViewController
|
||||
|
|
|
|||
|
|
@ -397,8 +397,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-625298705] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftStars($0) }
|
||||
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
|
||||
dict[-396206446] = { return Api.InputInvoice.parse_inputInvoiceStarGift($0) }
|
||||
dict[2010287526] = { return Api.InputInvoice.parse_inputInvoiceStarGiftAuctionBid($0) }
|
||||
dict[-2061017960] = { return Api.InputInvoice.parse_inputInvoiceStarGiftAuctionUpdateBid($0) }
|
||||
dict[516618768] = { return Api.InputInvoice.parse_inputInvoiceStarGiftAuctionBid($0) }
|
||||
dict[153344209] = { return Api.InputInvoice.parse_inputInvoiceStarGiftDropOriginalDetails($0) }
|
||||
dict[-1710536520] = { return Api.InputInvoice.parse_inputInvoiceStarGiftPrepaidUpgrade($0) }
|
||||
dict[-1012968668] = { return Api.InputInvoice.parse_inputInvoiceStarGiftResale($0) }
|
||||
|
|
|
|||
|
|
@ -566,8 +566,7 @@ public extension Api {
|
|||
case inputInvoicePremiumGiftStars(flags: Int32, userId: Api.InputUser, months: Int32, message: Api.TextWithEntities?)
|
||||
case inputInvoiceSlug(slug: String)
|
||||
case inputInvoiceStarGift(flags: Int32, peer: Api.InputPeer, giftId: Int64, message: Api.TextWithEntities?)
|
||||
case inputInvoiceStarGiftAuctionBid(flags: Int32, peer: Api.InputPeer, giftId: Int64, bidAmount: Int64, message: Api.TextWithEntities?)
|
||||
case inputInvoiceStarGiftAuctionUpdateBid(giftId: Int64, bidAmount: Int64)
|
||||
case inputInvoiceStarGiftAuctionBid(flags: Int32, peer: Api.InputPeer?, giftId: Int64, bidAmount: Int64, message: Api.TextWithEntities?)
|
||||
case inputInvoiceStarGiftDropOriginalDetails(stargift: Api.InputSavedStarGift)
|
||||
case inputInvoiceStarGiftPrepaidUpgrade(peer: Api.InputPeer, hash: String)
|
||||
case inputInvoiceStarGiftResale(flags: Int32, slug: String, toId: Api.InputPeer)
|
||||
|
|
@ -636,21 +635,14 @@ public extension Api {
|
|||
break
|
||||
case .inputInvoiceStarGiftAuctionBid(let flags, let peer, let giftId, let bidAmount, let message):
|
||||
if boxed {
|
||||
buffer.appendInt32(2010287526)
|
||||
buffer.appendInt32(516618768)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 3) != 0 {peer!.serialize(buffer, true)}
|
||||
serializeInt64(giftId, buffer: buffer, boxed: false)
|
||||
serializeInt64(bidAmount, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
|
||||
break
|
||||
case .inputInvoiceStarGiftAuctionUpdateBid(let giftId, let bidAmount):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2061017960)
|
||||
}
|
||||
serializeInt64(giftId, buffer: buffer, boxed: false)
|
||||
serializeInt64(bidAmount, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .inputInvoiceStarGiftDropOriginalDetails(let stargift):
|
||||
if boxed {
|
||||
buffer.appendInt32(153344209)
|
||||
|
|
@ -715,8 +707,6 @@ public extension Api {
|
|||
return ("inputInvoiceStarGift", [("flags", flags as Any), ("peer", peer as Any), ("giftId", giftId as Any), ("message", message as Any)])
|
||||
case .inputInvoiceStarGiftAuctionBid(let flags, let peer, let giftId, let bidAmount, let message):
|
||||
return ("inputInvoiceStarGiftAuctionBid", [("flags", flags as Any), ("peer", peer as Any), ("giftId", giftId as Any), ("bidAmount", bidAmount as Any), ("message", message as Any)])
|
||||
case .inputInvoiceStarGiftAuctionUpdateBid(let giftId, let bidAmount):
|
||||
return ("inputInvoiceStarGiftAuctionUpdateBid", [("giftId", giftId as Any), ("bidAmount", bidAmount as Any)])
|
||||
case .inputInvoiceStarGiftDropOriginalDetails(let stargift):
|
||||
return ("inputInvoiceStarGiftDropOriginalDetails", [("stargift", stargift as Any)])
|
||||
case .inputInvoiceStarGiftPrepaidUpgrade(let peer, let hash):
|
||||
|
|
@ -869,9 +859,9 @@ public extension Api {
|
|||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.InputPeer?
|
||||
if let signature = reader.readInt32() {
|
||||
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.InputPeer
|
||||
}
|
||||
} }
|
||||
var _3: Int64?
|
||||
_3 = reader.readInt64()
|
||||
var _4: Int64?
|
||||
|
|
@ -881,26 +871,12 @@ public extension Api {
|
|||
_5 = Api.parse(reader, signature: signature) as? Api.TextWithEntities
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 3) == 0) || _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.InputInvoice.inputInvoiceStarGiftAuctionBid(flags: _1!, peer: _2!, giftId: _3!, bidAmount: _4!, message: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_inputInvoiceStarGiftAuctionUpdateBid(_ reader: BufferReader) -> InputInvoice? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Int64?
|
||||
_2 = reader.readInt64()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.InputInvoice.inputInvoiceStarGiftAuctionUpdateBid(giftId: _1!, bidAmount: _2!)
|
||||
return Api.InputInvoice.inputInvoiceStarGiftAuctionBid(flags: _1!, peer: _2, giftId: _3!, bidAmount: _4!, message: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -560,7 +560,7 @@ open class TelegramBaseController: ViewController, KeyShortcutResponder {
|
|||
guard let self, let auction else {
|
||||
return
|
||||
}
|
||||
let controller = self.context.sharedContext.makeGiftAuctionBidScreen(context: self.context, auctionContext: auction)
|
||||
let controller = self.context.sharedContext.makeGiftAuctionBidScreen(context: self.context, toPeerId: auction.currentBidPeerId ?? self.context.account.peerId, auctionContext: auction)
|
||||
self.push(controller)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@ public enum BotPaymentInvoiceSource {
|
|||
case starGiftResale(slug: String, toPeerId: EnginePeer.Id, ton: Bool)
|
||||
case starGiftPrepaidUpgrade(peerId: EnginePeer.Id, hash: String)
|
||||
case starGiftDropOriginalDetails(reference: StarGiftReference)
|
||||
case starGiftAuctionBid(hideName: Bool, peerId: EnginePeer.Id, giftId: Int64, bidAmount: Int64, text: String?, entities: [MessageTextEntity]?)
|
||||
case starGiftAuctionUpdateBid(giftId: Int64, bidAmount: Int64)
|
||||
case starGiftAuctionBid(update: Bool, hideName: Bool, peerId: EnginePeer.Id, giftId: Int64, bidAmount: Int64, text: String?, entities: [MessageTextEntity]?)
|
||||
}
|
||||
|
||||
public struct BotPaymentInvoiceFields: OptionSet {
|
||||
|
|
@ -426,7 +425,7 @@ func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInv
|
|||
case let .starGiftDropOriginalDetails(reference):
|
||||
return reference.apiStarGiftReference(transaction: transaction).flatMap { .inputInvoiceStarGiftDropOriginalDetails(stargift: $0) }
|
||||
|
||||
case let .starGiftAuctionBid(hideName, peerId, giftId, bidAmount, text, entities):
|
||||
case let .starGiftAuctionBid(update, hideName, peerId, giftId, bidAmount, text, entities):
|
||||
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -434,14 +433,17 @@ func _internal_parseInputInvoice(transaction: Transaction, source: BotPaymentInv
|
|||
if hideName {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
if update {
|
||||
flags |= (1 << 2)
|
||||
}
|
||||
flags |= (1 << 3)
|
||||
|
||||
var message: Api.TextWithEntities?
|
||||
if let text, !text.isEmpty {
|
||||
flags |= (1 << 1)
|
||||
message = .textWithEntities(text: text, entities: entities.flatMap { apiEntitiesFromMessageTextEntities($0, associatedPeers: SimpleDictionary()) } ?? [])
|
||||
}
|
||||
return .inputInvoiceStarGiftAuctionBid(flags: flags, peer: inputPeer, giftId: giftId, bidAmount: bidAmount, message: message)
|
||||
case let .starGiftAuctionUpdateBid(giftId, bidAmount):
|
||||
return .inputInvoiceStarGiftAuctionUpdateBid(giftId: giftId, bidAmount: bidAmount)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -784,7 +786,7 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
|
|||
receiptMessageId = id
|
||||
}
|
||||
}
|
||||
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid, .starGiftAuctionUpdateBid:
|
||||
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid:
|
||||
receiptMessageId = nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1637,7 +1637,7 @@ func _internal_sendStarsPaymentForm(account: Account, formId: Int64, source: Bot
|
|||
receiptMessageId = id
|
||||
}
|
||||
}
|
||||
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid, .starGiftAuctionUpdateBid:
|
||||
case .giftCode, .stars, .starsGift, .starsChatSubscription, .starGift, .starGiftUpgrade, .starGiftTransfer, .premiumGift, .starGiftResale, .starGiftPrepaidUpgrade, .starGiftDropOriginalDetails, .starGiftAuctionBid:
|
||||
receiptMessageId = nil
|
||||
}
|
||||
} else if case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _, _, peerId, _, savedId, _, canTransferDate, canResaleDate, dropOriginalDetailsStars, _) = action.action, case let .Id(messageId) = message.id {
|
||||
|
|
|
|||
|
|
@ -2034,12 +2034,10 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||
availableModeControlSize = availableSize
|
||||
}
|
||||
|
||||
let availableModes: [CameraMode]
|
||||
//#if DEBUG
|
||||
availableModes = [.photo, .video, .live]
|
||||
//#else
|
||||
//availableModes = [.photo, .video]
|
||||
//#endif
|
||||
var availableModes: [CameraMode] = [.photo, .video]
|
||||
if !isTablet {
|
||||
availableModes.append(.live)
|
||||
}
|
||||
|
||||
let modeControl = modeControl.update(
|
||||
component: ModeComponent(
|
||||
|
|
|
|||
|
|
@ -389,6 +389,7 @@ final class GiftOptionsScreenComponent: Component {
|
|||
if currentBidPeerId == component.peerId {
|
||||
let giftController = component.context.sharedContext.makeGiftAuctionBidScreen(
|
||||
context: component.context,
|
||||
toPeerId: currentBidPeerId,
|
||||
auctionContext: auctionContext
|
||||
)
|
||||
mainController.push(giftController)
|
||||
|
|
@ -411,6 +412,7 @@ final class GiftOptionsScreenComponent: Component {
|
|||
}
|
||||
let giftController = component.context.sharedContext.makeGiftAuctionBidScreen(
|
||||
context: component.context,
|
||||
toPeerId: currentBidPeerId,
|
||||
auctionContext: auctionContext
|
||||
)
|
||||
mainController.push(giftController)
|
||||
|
|
@ -424,6 +426,7 @@ final class GiftOptionsScreenComponent: Component {
|
|||
} else {
|
||||
let giftController = component.context.sharedContext.makeGiftAuctionViewScreen(
|
||||
context: component.context,
|
||||
toPeerId: component.peerId,
|
||||
auctionContext: auctionContext
|
||||
)
|
||||
mainController.push(giftController)
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ private final class GiftAuctionAcquiredScreenComponent: Component {
|
|||
} else {
|
||||
fillingSize = min(availableSize.width, 428.0) - environment.safeInsets.left * 2.0
|
||||
}
|
||||
let rawSideInset = floor((availableSize.width - fillingSize) * 0.5)
|
||||
let sideInset: CGFloat = floor((availableSize.width - fillingSize) * 0.5) + 24.0
|
||||
|
||||
self.component = component
|
||||
|
|
@ -474,7 +475,7 @@ private final class GiftAuctionAcquiredScreenComponent: Component {
|
|||
environment: {},
|
||||
containerSize: CGSize(width: 40.0, height: 40.0)
|
||||
)
|
||||
let closeButtonFrame = CGRect(origin: CGPoint(x: 16.0, y: 16.0), size: closeButtonSize)
|
||||
let closeButtonFrame = CGRect(origin: CGPoint(x: rawSideInset + 16.0, y: 16.0), size: closeButtonSize)
|
||||
if let closeButtonView = self.closeButton.view {
|
||||
if closeButtonView.superview == nil {
|
||||
self.navigationBarContainer.addSubview(closeButtonView)
|
||||
|
|
@ -538,12 +539,11 @@ private final class GiftAuctionAcquiredScreenComponent: Component {
|
|||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 54.0)
|
||||
containerSize: CGSize(width: fillingSize - buttonInsets.left - buttonInsets.right, height: 54.0)
|
||||
)
|
||||
|
||||
|
||||
let edgeEffectHeight: CGFloat = 80.0
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: edgeEffectHeight))
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: rawSideInset, y: 0.0), size: CGSize(width: fillingSize, height: edgeEffectHeight))
|
||||
transition.setFrame(view: self.topEdgeEffectView, frame: edgeEffectFrame)
|
||||
self.topEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: edgeEffectFrame, edge: .top, edgeSize: edgeEffectFrame.height, transition: transition)
|
||||
if self.topEdgeEffectView.superview == nil {
|
||||
|
|
@ -553,14 +553,14 @@ private final class GiftAuctionAcquiredScreenComponent: Component {
|
|||
var bottomPanelHeight = 13.0 + buttonInsets.bottom + actionButtonSize.height
|
||||
|
||||
let bottomEdgeEffectHeight: CGFloat = bottomPanelHeight
|
||||
let bottomEdgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - bottomEdgeEffectHeight), size: CGSize(width: availableSize.width, height: bottomEdgeEffectHeight))
|
||||
let bottomEdgeEffectFrame = CGRect(origin: CGPoint(x: rawSideInset, y: availableSize.height - bottomEdgeEffectHeight), size: CGSize(width: fillingSize, height: bottomEdgeEffectHeight))
|
||||
transition.setFrame(view: self.bottomEdgeEffectView, frame: bottomEdgeEffectFrame)
|
||||
self.bottomEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: bottomEdgeEffectFrame, edge: .bottom, edgeSize: bottomEdgeEffectFrame.height, transition: transition)
|
||||
if self.bottomEdgeEffectView.superview == nil {
|
||||
self.containerView.addSubview(self.bottomEdgeEffectView)
|
||||
}
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: rawSideInset + buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
|
||||
bottomPanelHeight -= 1.0
|
||||
if let actionButtonView = actionButton.view {
|
||||
if actionButtonView.superview == nil {
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ private final class GiftAuctionActiveBidsScreenComponent: Component {
|
|||
}
|
||||
controller.dismiss()
|
||||
|
||||
let bidController = component.context.sharedContext.makeGiftAuctionBidScreen(context: component.context, auctionContext: auction)
|
||||
let bidController = component.context.sharedContext.makeGiftAuctionBidScreen(context: component.context, toPeerId: auction.currentBidPeerId ?? component.context.account.peerId, auctionContext: auction)
|
||||
navigationController.pushViewController(bidController)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,6 +486,7 @@ private final class PeerComponent: Component {
|
|||
let amount: Int64
|
||||
let status: Status?
|
||||
let isLast: Bool
|
||||
let action: (() -> Void)?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
|
|
@ -495,7 +496,8 @@ private final class PeerComponent: Component {
|
|||
place: Int32,
|
||||
amount: Int64,
|
||||
status: Status? = nil,
|
||||
isLast: Bool
|
||||
isLast: Bool,
|
||||
action: (() -> Void)?
|
||||
) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
|
|
@ -505,6 +507,7 @@ private final class PeerComponent: Component {
|
|||
self.amount = amount
|
||||
self.status = status
|
||||
self.isLast = isLast
|
||||
self.action = action
|
||||
}
|
||||
|
||||
static func ==(lhs: PeerComponent, rhs: PeerComponent) -> Bool {
|
||||
|
|
@ -533,31 +536,59 @@ private final class PeerComponent: Component {
|
|||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let selectionLayer = SimpleLayer()
|
||||
private var avatarNode: AvatarNode?
|
||||
private let place = ComponentView<Empty>()
|
||||
private let title = ComponentView<Empty>()
|
||||
private let amount = ComponentView<Empty>()
|
||||
private let amountStar = UIImageView()
|
||||
private let separator = SimpleLayer()
|
||||
private let button = HighlightTrackingButton()
|
||||
|
||||
private var component: PeerComponent?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
self.selectionLayer.opacity = 0.0
|
||||
|
||||
self.layer.addSublayer(self.separator)
|
||||
self.layer.addSublayer(self.selectionLayer)
|
||||
|
||||
self.amountStar.image = UIImage(bundleImageName: "Premium/Stars/StarSmall")
|
||||
self.addSubview(self.amountStar)
|
||||
|
||||
self.button.addTarget(self, action: #selector(self.buttonPressed), for: .touchUpInside)
|
||||
self.addSubview(self.button)
|
||||
|
||||
self.button.highligthedChanged = { [weak self] highlighted in
|
||||
if let self {
|
||||
if highlighted {
|
||||
self.selectionLayer.removeAnimation(forKey: "opacity")
|
||||
self.selectionLayer.opacity = 1.0
|
||||
} else {
|
||||
self.selectionLayer.opacity = 0.0
|
||||
self.selectionLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
if let component = self.component {
|
||||
component.action?()
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: PeerComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.component = component
|
||||
|
||||
self.button.isUserInteractionEnabled = component.action != nil
|
||||
|
||||
let size = CGSize(width: availableSize.width, height: 52.0)
|
||||
|
||||
var color = component.theme.list.itemSecondaryTextColor
|
||||
|
|
@ -569,6 +600,7 @@ private final class PeerComponent: Component {
|
|||
default:
|
||||
break
|
||||
}
|
||||
self.selectionLayer.backgroundColor = component.theme.list.itemHighlightedBackgroundColor.cgColor
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let placeSize = self.place.update(
|
||||
|
|
@ -580,6 +612,7 @@ private final class PeerComponent: Component {
|
|||
let placeFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((size.height - placeSize.height) / 2.0)), size: placeSize)
|
||||
if let placeView = self.place.view {
|
||||
if placeView.superview == nil {
|
||||
placeView.isUserInteractionEnabled = false
|
||||
self.addSubview(placeView)
|
||||
}
|
||||
placeView.frame = placeFrame
|
||||
|
|
@ -590,6 +623,7 @@ private final class PeerComponent: Component {
|
|||
avatarNode = current
|
||||
} else {
|
||||
avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 16.0))
|
||||
avatarNode.isUserInteractionEnabled = false
|
||||
self.avatarNode = avatarNode
|
||||
self.addSubview(avatarNode.view)
|
||||
}
|
||||
|
|
@ -611,6 +645,7 @@ private final class PeerComponent: Component {
|
|||
let titleFrame = CGRect(origin: CGPoint(x: 110.0, y: floorToScreenPixels((size.height - titleSize.height) / 2.0)), size: titleSize)
|
||||
if let titleView = self.title.view {
|
||||
if titleView.superview == nil {
|
||||
titleView.isUserInteractionEnabled = false
|
||||
self.addSubview(titleView)
|
||||
}
|
||||
titleView.frame = titleFrame
|
||||
|
|
@ -627,6 +662,7 @@ private final class PeerComponent: Component {
|
|||
let amountFrame = CGRect(origin: CGPoint(x: availableSize.width - amountSize.width, y: floorToScreenPixels((size.height - amountSize.height) / 2.0)), size: amountSize)
|
||||
if let amountView = self.amount.view {
|
||||
if amountView.superview == nil {
|
||||
amountView.isUserInteractionEnabled = false
|
||||
self.addSubview(amountView)
|
||||
}
|
||||
amountView.frame = amountFrame
|
||||
|
|
@ -637,9 +673,12 @@ private final class PeerComponent: Component {
|
|||
}
|
||||
|
||||
self.separator.backgroundColor = component.theme.list.itemPlainSeparatorColor.cgColor
|
||||
self.separator.frame = CGRect(origin: CGPoint(x: 110.0, y: size.height), size: CGSize(width: size.width - 110.0, height: 1.0 - UIScreenPixel))
|
||||
self.separator.frame = CGRect(origin: CGPoint(x: 110.0, y: size.height - UIScreenPixel), size: CGSize(width: size.width - 110.0, height: UIScreenPixel))
|
||||
transition.setAlpha(layer: self.separator, alpha: component.isLast ? 0.0 : 1.0)
|
||||
|
||||
self.button.frame = CGRect(origin: .zero, size: size)
|
||||
self.selectionLayer.frame = CGRect(origin: .zero, size: size).insetBy(dx: -24.0, dy: -UIScreenPixel)
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
|
@ -900,15 +939,18 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
||||
let context: AccountContext
|
||||
let toPeerId: EnginePeer.Id
|
||||
let gift: StarGift
|
||||
let auctionContext: GiftAuctionContext
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
toPeerId: EnginePeer.Id,
|
||||
gift: StarGift,
|
||||
auctionContext: GiftAuctionContext
|
||||
) {
|
||||
self.context = context
|
||||
self.toPeerId = toPeerId
|
||||
self.gift = gift
|
||||
self.auctionContext = auctionContext
|
||||
}
|
||||
|
|
@ -1412,22 +1454,15 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
self.isLoading = true
|
||||
self.state?.updated()
|
||||
|
||||
let source: BotPaymentInvoiceSource
|
||||
if let state = self.giftAuctionState, state.myState.bidAmount != nil {
|
||||
source = .starGiftAuctionUpdateBid(
|
||||
giftId: gift.id,
|
||||
bidAmount: value
|
||||
)
|
||||
} else {
|
||||
source = .starGiftAuctionBid(
|
||||
hideName: false,
|
||||
peerId: component.context.account.peerId,
|
||||
giftId: gift.id,
|
||||
bidAmount: value,
|
||||
text: nil,
|
||||
entities: nil
|
||||
)
|
||||
}
|
||||
let source: BotPaymentInvoiceSource = .starGiftAuctionBid(
|
||||
update: isUpdate,
|
||||
hideName: false,
|
||||
peerId: component.toPeerId,
|
||||
giftId: gift.id,
|
||||
bidAmount: value,
|
||||
text: nil,
|
||||
entities: nil
|
||||
)
|
||||
|
||||
let signal = BotCheckoutController.InputData.fetch(context: component.context, source: source)
|
||||
|> `catch` { error -> Signal<BotCheckoutController.InputData, SendBotPaymentFormError> in
|
||||
|
|
@ -1644,6 +1679,29 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
controller.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
|
||||
func presentCustomBidController() {
|
||||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
if "".isEmpty {
|
||||
return
|
||||
}
|
||||
let controller = giftAuctionCustomBidController(
|
||||
context: component.context,
|
||||
title: "Place a Custom Bid",
|
||||
text: "Description",
|
||||
placeholder: "Bid",
|
||||
value: 100,
|
||||
apply: { [weak self] value in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.commitBid(value: value)
|
||||
}
|
||||
)
|
||||
self.environment?.controller()?.present(controller, in: .window(.root))
|
||||
}
|
||||
|
||||
func update(component: GiftAuctionBidScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: ComponentTransition) -> CGSize {
|
||||
self.isUpdating = true
|
||||
defer {
|
||||
|
|
@ -1661,6 +1719,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
} else {
|
||||
fillingSize = min(availableSize.width, 428.0) - environment.safeInsets.left * 2.0
|
||||
}
|
||||
let rawSideInset = floor((availableSize.width - fillingSize) * 0.5)
|
||||
let sideInset: CGFloat = floor((availableSize.width - fillingSize) * 0.5) + 24.0
|
||||
|
||||
let context = component.context
|
||||
|
|
@ -1794,7 +1853,8 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
})
|
||||
|
||||
self.giftAuctionTimer = SwiftSignalKit.Timer(timeout: 0.5, repeat: true, completion: { [weak self] in
|
||||
self?.state?.updated()
|
||||
let _ = self
|
||||
//self?.state?.updated()
|
||||
}, queue: Queue.mainQueue())
|
||||
self.giftAuctionTimer?.start()
|
||||
}
|
||||
|
|
@ -1827,7 +1887,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
return
|
||||
}
|
||||
|
||||
let maxAmount: Int = 1000
|
||||
let maxAmount: Int = 999
|
||||
|
||||
self.amount = self.amount.withSliderValue(value)
|
||||
self.didChangeAmount = true
|
||||
|
|
@ -1851,6 +1911,10 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
}
|
||||
}
|
||||
|
||||
if sliderValue == 1.0 && self.previousSliderValue != 1.0 {
|
||||
self.presentCustomBidController()
|
||||
}
|
||||
|
||||
self.previousSliderValue = sliderValue
|
||||
self.previousTimestamp = currentTimestamp
|
||||
}
|
||||
|
|
@ -1985,7 +2049,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
let badgeOriginX = sliderBackgroundFrame.minX + sliderForegroundFrame.width - 15.0
|
||||
badgeFrame = CGRect(origin: CGPoint(x: badgeOriginX - apparentBadgeSize.width * 0.5, y: sliderForegroundFrame.minY - 9.0 - badgeSize.height), size: apparentBadgeSize)
|
||||
|
||||
let badgeSideInset: CGFloat = 23.0
|
||||
let badgeSideInset: CGFloat = rawSideInset + 23.0
|
||||
|
||||
let badgeOverflowWidth: CGFloat
|
||||
if badgeFrame.minX < badgeSideInset {
|
||||
|
|
@ -2008,7 +2072,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
|
||||
let starsRect = CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: sliderForegroundFrame.midY))
|
||||
self.badgeStars.frame = starsRect
|
||||
self.badgeStars.update(size: starsRect.size, color: sliderColor, emitterPosition: CGPoint(x: badgeFrame.minX, y: badgeFrame.midY - 64.0))
|
||||
self.badgeStars.update(size: starsRect.size, color: sliderColor, emitterPosition: CGPoint(x: badgeFrame.midX, y: badgeFrame.maxY - 32.0))
|
||||
}
|
||||
|
||||
var perks: [([AnimatedTextComponent.Item], String)] = []
|
||||
|
|
@ -2116,7 +2180,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
|
||||
let perkHeight: CGFloat = 60.0
|
||||
let perkSpacing: CGFloat = 10.0
|
||||
let perkWidth: CGFloat = floor((fillingSize - sideInset * 2.0 - perkSpacing * CGFloat(perks.count - 1)) / CGFloat(perks.count))
|
||||
let perkWidth: CGFloat = floor((availableSize.width - sideInset * 2.0 - perkSpacing * CGFloat(perks.count - 1)) / CGFloat(perks.count))
|
||||
|
||||
for i in 0 ..< perks.count {
|
||||
var perkFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (perkWidth + perkSpacing), y: contentHeight), size: CGSize(width: perkWidth, height: perkHeight))
|
||||
|
|
@ -2187,7 +2251,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
environment: {},
|
||||
containerSize: CGSize(width: 40.0, height: 40.0)
|
||||
)
|
||||
let closeButtonFrame = CGRect(origin: CGPoint(x: 16.0, y: 16.0), size: closeButtonSize)
|
||||
let closeButtonFrame = CGRect(origin: CGPoint(x: rawSideInset + 16.0, y: 16.0), size: closeButtonSize)
|
||||
if let closeButtonView = self.closeButton.view {
|
||||
if closeButtonView.superview == nil {
|
||||
self.navigationBarContainer.addSubview(closeButtonView)
|
||||
|
|
@ -2223,7 +2287,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
environment: {},
|
||||
containerSize: CGSize(width: 40.0, height: 40.0)
|
||||
)
|
||||
let infoButtonFrame = CGRect(origin: CGPoint(x: availableSize.width - 16.0 - moreButtonSize.width, y: 16.0), size: moreButtonSize)
|
||||
let infoButtonFrame = CGRect(origin: CGPoint(x: availableSize.width - rawSideInset - 16.0 - moreButtonSize.width, y: 16.0), size: moreButtonSize)
|
||||
if let infoButtonView = self.moreButton.view {
|
||||
if infoButtonView.superview == nil {
|
||||
self.navigationBarContainer.addSubview(infoButtonView)
|
||||
|
|
@ -2290,7 +2354,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
}
|
||||
|
||||
myBidTitleComponent = AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: bidTitle.uppercased(), font: Font.medium(13.0), textColor: bidTitleColor))))
|
||||
myBidComponent = AnyComponent(PeerComponent(context: component.context, theme: environment.theme, groupingSeparator: environment.dateTimeFormat.groupingSeparator, peer: peer, place: place, amount: myBidAmount, status: bidStatus, isLast: true))
|
||||
myBidComponent = AnyComponent(PeerComponent(context: component.context, theme: environment.theme, groupingSeparator: environment.dateTimeFormat.groupingSeparator, peer: peer, place: place, amount: myBidAmount, status: bidStatus, isLast: true, action: nil))
|
||||
}
|
||||
|
||||
var i: Int32 = 1
|
||||
|
|
@ -2303,7 +2367,7 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
break
|
||||
}
|
||||
}
|
||||
topBidsComponents.append((bidder, AnyComponent(PeerComponent(context: component.context, theme: environment.theme, groupingSeparator: environment.dateTimeFormat.groupingSeparator, peer: peer, place: i, amount: bid, isLast: i == topBidders.count))))
|
||||
topBidsComponents.append((bidder, AnyComponent(PeerComponent(context: component.context, theme: environment.theme, groupingSeparator: environment.dateTimeFormat.groupingSeparator, peer: peer, place: i, amount: bid, isLast: i == topBidders.count, action: peer.id != component.context.account.peerId ? { [weak self] in self?.openPeer(peer, dismiss: false) } : nil))))
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
|
@ -2541,11 +2605,11 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
}
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - buttonInsets.left - buttonInsets.right, height: 54.0)
|
||||
containerSize: CGSize(width: fillingSize - buttonInsets.left - buttonInsets.right, height: 54.0)
|
||||
)
|
||||
|
||||
let edgeEffectHeight: CGFloat = 80.0
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: edgeEffectHeight))
|
||||
let edgeEffectFrame = CGRect(origin: CGPoint(x: rawSideInset, y: 0.0), size: CGSize(width: fillingSize, height: edgeEffectHeight))
|
||||
transition.setFrame(view: self.topEdgeEffectView, frame: edgeEffectFrame)
|
||||
self.topEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: edgeEffectFrame, edge: .top, edgeSize: edgeEffectFrame.height, transition: transition)
|
||||
if self.topEdgeEffectView.superview == nil {
|
||||
|
|
@ -2555,14 +2619,14 @@ private final class GiftAuctionBidScreenComponent: Component {
|
|||
var bottomPanelHeight = 13.0 + buttonInsets.bottom + actionButtonSize.height
|
||||
|
||||
let bottomEdgeEffectHeight: CGFloat = bottomPanelHeight
|
||||
let bottomEdgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - bottomEdgeEffectHeight), size: CGSize(width: availableSize.width, height: bottomEdgeEffectHeight))
|
||||
let bottomEdgeEffectFrame = CGRect(origin: CGPoint(x: rawSideInset, y: availableSize.height - bottomEdgeEffectHeight), size: CGSize(width: fillingSize, height: bottomEdgeEffectHeight))
|
||||
transition.setFrame(view: self.bottomEdgeEffectView, frame: bottomEdgeEffectFrame)
|
||||
self.bottomEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: bottomEdgeEffectFrame, edge: .bottom, edgeSize: bottomEdgeEffectFrame.height, transition: transition)
|
||||
if self.bottomEdgeEffectView.superview == nil {
|
||||
self.containerView.addSubview(self.bottomEdgeEffectView)
|
||||
}
|
||||
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
|
||||
let actionButtonFrame = CGRect(origin: CGPoint(x: rawSideInset + buttonInsets.left, y: availableSize.height - buttonInsets.bottom - actionButtonSize.height), size: actionButtonSize)
|
||||
bottomPanelHeight -= 1.0
|
||||
if let actionButtonView = actionButton.view {
|
||||
if actionButtonView.superview == nil {
|
||||
|
|
@ -2645,11 +2709,12 @@ public class GiftAuctionBidScreen: ViewControllerComponentContainer {
|
|||
private var didPlayAppearAnimation: Bool = false
|
||||
private var isDismissed: Bool = false
|
||||
|
||||
public init(context: AccountContext, auctionContext: GiftAuctionContext) {
|
||||
public init(context: AccountContext, toPeerId: EnginePeer.Id, auctionContext: GiftAuctionContext) {
|
||||
self.context = context
|
||||
|
||||
super.init(context: context, component: GiftAuctionBidScreenComponent(
|
||||
context: context,
|
||||
toPeerId: toPeerId,
|
||||
gift: auctionContext.gift,
|
||||
auctionContext: auctionContext
|
||||
), navigationBarAppearance: .none, theme: .default)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,440 @@
|
|||
import Foundation
|
||||
import UIKit
|
||||
import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import UrlEscaping
|
||||
|
||||
private final class GiftAuctionCustomBidInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegate {
|
||||
private var theme: PresentationTheme
|
||||
private let backgroundNode: ASImageNode
|
||||
private let textInputNode: EditableTextNode
|
||||
private let placeholderNode: ASTextNode
|
||||
|
||||
var updateHeight: (() -> Void)?
|
||||
var complete: (() -> Void)?
|
||||
var textChanged: ((String) -> Void)?
|
||||
|
||||
private let backgroundInsets = UIEdgeInsets(top: 8.0, left: 16.0, bottom: 15.0, right: 16.0)
|
||||
private let inputInsets = UIEdgeInsets(top: 5.0, left: 12.0, bottom: 5.0, right: 12.0)
|
||||
|
||||
var text: String {
|
||||
get {
|
||||
return self.textInputNode.attributedText?.string ?? ""
|
||||
}
|
||||
set {
|
||||
self.textInputNode.attributedText = NSAttributedString(string: newValue, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputTextColor)
|
||||
self.placeholderNode.isHidden = !newValue.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
var placeholder: String = "" {
|
||||
didSet {
|
||||
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholder, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
|
||||
}
|
||||
}
|
||||
|
||||
init(theme: PresentationTheme, placeholder: String, returnKeyType: UIReturnKeyType = .done) {
|
||||
self.theme = theme
|
||||
|
||||
self.backgroundNode = ASImageNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
self.backgroundNode.displaysAsynchronously = false
|
||||
self.backgroundNode.displayWithoutProcessing = true
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 12.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
|
||||
|
||||
self.textInputNode = EditableTextNode()
|
||||
self.textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: theme.actionSheet.inputTextColor]
|
||||
self.textInputNode.clipsToBounds = true
|
||||
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
self.textInputNode.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0)
|
||||
self.textInputNode.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.textInputNode.keyboardType = .default
|
||||
self.textInputNode.autocapitalizationType = .sentences
|
||||
self.textInputNode.returnKeyType = returnKeyType
|
||||
self.textInputNode.autocorrectionType = .default
|
||||
self.textInputNode.tintColor = theme.actionSheet.controlAccentColor
|
||||
self.textInputNode.keyboardType = .numberPad
|
||||
|
||||
self.placeholderNode = ASTextNode()
|
||||
self.placeholderNode.isUserInteractionEnabled = false
|
||||
self.placeholderNode.displaysAsynchronously = false
|
||||
self.placeholderNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
|
||||
|
||||
super.init()
|
||||
|
||||
self.textInputNode.delegate = self
|
||||
|
||||
self.addSubnode(self.backgroundNode)
|
||||
self.addSubnode(self.textInputNode)
|
||||
self.addSubnode(self.placeholderNode)
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
|
||||
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 12.0, color: self.theme.actionSheet.inputHollowBackgroundColor, strokeColor: self.theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
|
||||
self.textInputNode.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholderNode.attributedText?.string ?? "", font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
|
||||
self.textInputNode.tintColor = self.theme.actionSheet.controlAccentColor
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
let backgroundInsets = self.backgroundInsets
|
||||
let inputInsets = self.inputInsets
|
||||
|
||||
let textFieldHeight = self.calculateTextFieldMetrics(width: width)
|
||||
let panelHeight = textFieldHeight + backgroundInsets.top + backgroundInsets.bottom
|
||||
|
||||
let backgroundFrame = CGRect(origin: CGPoint(x: backgroundInsets.left, y: backgroundInsets.top), size: CGSize(width: width - backgroundInsets.left - backgroundInsets.right, height: panelHeight - backgroundInsets.top - backgroundInsets.bottom))
|
||||
transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame)
|
||||
|
||||
let placeholderSize = self.placeholderNode.measure(backgroundFrame.size)
|
||||
transition.updateFrame(node: self.placeholderNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY + floor((backgroundFrame.size.height - placeholderSize.height) / 2.0)), size: placeholderSize))
|
||||
|
||||
transition.updateFrame(node: self.textInputNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY), size: CGSize(width: backgroundFrame.size.width - inputInsets.left - inputInsets.right - 20.0, height: backgroundFrame.size.height)))
|
||||
|
||||
return panelHeight
|
||||
}
|
||||
|
||||
func activateInput() {
|
||||
self.textInputNode.becomeFirstResponder()
|
||||
}
|
||||
|
||||
func deactivateInput() {
|
||||
self.textInputNode.resignFirstResponder()
|
||||
}
|
||||
|
||||
@objc func editableTextNodeDidUpdateText(_ editableTextNode: ASEditableTextNode) {
|
||||
self.updateTextNodeText(animated: true)
|
||||
self.textChanged?(editableTextNode.textView.text)
|
||||
self.placeholderNode.isHidden = !(editableTextNode.textView.text ?? "").isEmpty
|
||||
}
|
||||
|
||||
func editableTextNodeDidBeginEditing(_ editableTextNode: ASEditableTextNode) {
|
||||
}
|
||||
|
||||
func editableTextNodeDidFinishEditing(_ editableTextNode: ASEditableTextNode) {
|
||||
}
|
||||
|
||||
func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
let updatedText = (editableTextNode.textView.text as NSString).replacingCharacters(in: range, with: text)
|
||||
if updatedText.count > 1 {
|
||||
self.textInputNode.layer.addShakeAnimation()
|
||||
return false
|
||||
}
|
||||
if text == "\n" {
|
||||
self.complete?()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private func calculateTextFieldMetrics(width: CGFloat) -> CGFloat {
|
||||
let backgroundInsets = self.backgroundInsets
|
||||
let inputInsets = self.inputInsets
|
||||
|
||||
let unboundTextFieldHeight = max(33.0, ceil(self.textInputNode.measure(CGSize(width: width - backgroundInsets.left - backgroundInsets.right - inputInsets.left - inputInsets.right - 20.0, height: CGFloat.greatestFiniteMagnitude)).height))
|
||||
|
||||
return min(61.0, max(33.0, unboundTextFieldHeight))
|
||||
}
|
||||
|
||||
private func updateTextNodeText(animated: Bool) {
|
||||
let backgroundInsets = self.backgroundInsets
|
||||
|
||||
let textFieldHeight = self.calculateTextFieldMetrics(width: self.bounds.size.width)
|
||||
|
||||
let panelHeight = textFieldHeight + backgroundInsets.top + backgroundInsets.bottom
|
||||
if !self.bounds.size.height.isEqual(to: panelHeight) {
|
||||
self.updateHeight?()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func clearPressed() {
|
||||
self.placeholderNode.isHidden = false
|
||||
|
||||
self.textInputNode.attributedText = nil
|
||||
self.updateHeight?()
|
||||
}
|
||||
}
|
||||
|
||||
private final class giftAuctionCustomBidAlertContentNode: AlertContentNode {
|
||||
private let strings: PresentationStrings
|
||||
private let title: String
|
||||
private let text: String
|
||||
|
||||
private let titleNode: ASTextNode
|
||||
private let textNode: ASTextNode
|
||||
let inputFieldNode: GiftAuctionCustomBidInputFieldNode
|
||||
|
||||
private let actionNodesSeparator: ASDisplayNode
|
||||
private let actionNodes: [TextAlertContentActionNode]
|
||||
private let actionVerticalSeparators: [ASDisplayNode]
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
private var validLayout: CGSize?
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
var complete: (() -> Void)? {
|
||||
didSet {
|
||||
self.inputFieldNode.complete = self.complete
|
||||
}
|
||||
}
|
||||
|
||||
override var dismissOnOutsideTap: Bool {
|
||||
return self.isUserInteractionEnabled
|
||||
}
|
||||
|
||||
init(theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, actions: [TextAlertAction], title: String, text: String, placeholder: String, value: Int64) {
|
||||
self.strings = strings
|
||||
self.title = title
|
||||
self.text = text
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.maximumNumberOfLines = 2
|
||||
self.textNode = ASTextNode()
|
||||
self.textNode.maximumNumberOfLines = 8
|
||||
|
||||
self.inputFieldNode = GiftAuctionCustomBidInputFieldNode(theme: ptheme, placeholder: placeholder)
|
||||
self.inputFieldNode.text = "\(value)"
|
||||
|
||||
self.actionNodesSeparator = ASDisplayNode()
|
||||
self.actionNodesSeparator.isLayerBacked = true
|
||||
|
||||
self.actionNodes = actions.map { action -> TextAlertContentActionNode in
|
||||
return TextAlertContentActionNode(theme: theme, action: action)
|
||||
}
|
||||
|
||||
var actionVerticalSeparators: [ASDisplayNode] = []
|
||||
if actions.count > 1 {
|
||||
for _ in 0 ..< actions.count - 1 {
|
||||
let separatorNode = ASDisplayNode()
|
||||
separatorNode.isLayerBacked = true
|
||||
actionVerticalSeparators.append(separatorNode)
|
||||
}
|
||||
}
|
||||
self.actionVerticalSeparators = actionVerticalSeparators
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
self.addSubnode(self.inputFieldNode)
|
||||
|
||||
self.addSubnode(self.actionNodesSeparator)
|
||||
|
||||
for actionNode in self.actionNodes {
|
||||
self.addSubnode(actionNode)
|
||||
}
|
||||
|
||||
for separatorNode in self.actionVerticalSeparators {
|
||||
self.addSubnode(separatorNode)
|
||||
}
|
||||
|
||||
self.inputFieldNode.updateHeight = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
if let _ = strongSelf.validLayout {
|
||||
strongSelf.requestLayout?(.animated(duration: 0.15, curve: .spring))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.updateTheme(theme)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
var value: String {
|
||||
return self.inputFieldNode.text
|
||||
}
|
||||
|
||||
override func updateTheme(_ theme: AlertControllerTheme) {
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.bold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
||||
for actionNode in self.actionNodes {
|
||||
actionNode.updateTheme(theme)
|
||||
}
|
||||
for separatorNode in self.actionVerticalSeparators {
|
||||
separatorNode.backgroundColor = theme.separatorColor
|
||||
}
|
||||
|
||||
if let size = self.validLayout {
|
||||
_ = self.updateLayout(size: size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
override func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
|
||||
var size = size
|
||||
size.width = min(size.width, 270.0)
|
||||
let measureSize = CGSize(width: size.width - 16.0 * 2.0, height: CGFloat.greatestFiniteMagnitude)
|
||||
|
||||
let hadValidLayout = self.validLayout != nil
|
||||
|
||||
self.validLayout = size
|
||||
|
||||
var origin: CGPoint = CGPoint(x: 0.0, y: 20.0)
|
||||
let spacing: CGFloat = 5.0
|
||||
|
||||
let titleSize = self.titleNode.measure(measureSize)
|
||||
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: origin.y), size: titleSize))
|
||||
origin.y += titleSize.height + 4.0
|
||||
|
||||
let textSize = self.textNode.measure(measureSize)
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: origin.y), size: textSize))
|
||||
origin.y += textSize.height + 6.0 + spacing
|
||||
|
||||
let actionButtonHeight: CGFloat = 44.0
|
||||
var minActionsWidth: CGFloat = 0.0
|
||||
let maxActionWidth: CGFloat = floor(size.width / CGFloat(self.actionNodes.count))
|
||||
let actionTitleInsets: CGFloat = 8.0
|
||||
|
||||
var effectiveActionLayout = TextAlertContentActionLayout.horizontal
|
||||
for actionNode in self.actionNodes {
|
||||
let actionTitleSize = actionNode.titleNode.updateLayout(CGSize(width: maxActionWidth, height: actionButtonHeight))
|
||||
if case .horizontal = effectiveActionLayout, actionTitleSize.height > actionButtonHeight * 0.6667 {
|
||||
effectiveActionLayout = .vertical
|
||||
}
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
minActionsWidth += actionTitleSize.width + actionTitleInsets
|
||||
case .vertical:
|
||||
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
|
||||
}
|
||||
}
|
||||
|
||||
let insets = UIEdgeInsets(top: 18.0, left: 18.0, bottom: 9.0, right: 18.0)
|
||||
|
||||
var contentWidth = max(titleSize.width, minActionsWidth)
|
||||
contentWidth = max(contentWidth, 234.0)
|
||||
|
||||
var actionsHeight: CGFloat = 0.0
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
actionsHeight = actionButtonHeight
|
||||
case .vertical:
|
||||
actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count)
|
||||
}
|
||||
|
||||
let resultWidth = contentWidth + insets.left + insets.right
|
||||
|
||||
let inputFieldWidth = resultWidth
|
||||
let inputFieldHeight = self.inputFieldNode.updateLayout(width: inputFieldWidth, transition: transition)
|
||||
let inputHeight = inputFieldHeight
|
||||
transition.updateFrame(node: self.inputFieldNode, frame: CGRect(x: 0.0, y: origin.y, width: resultWidth, height: inputFieldHeight))
|
||||
transition.updateAlpha(node: self.inputFieldNode, alpha: inputHeight > 0.0 ? 1.0 : 0.0)
|
||||
|
||||
let resultSize = CGSize(width: resultWidth, height: titleSize.height + textSize.height + spacing + inputHeight + actionsHeight + insets.top + insets.bottom)
|
||||
|
||||
transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||
|
||||
var actionOffset: CGFloat = 0.0
|
||||
let actionWidth: CGFloat = floor(resultSize.width / CGFloat(self.actionNodes.count))
|
||||
var separatorIndex = -1
|
||||
var nodeIndex = 0
|
||||
for actionNode in self.actionNodes {
|
||||
if separatorIndex >= 0 {
|
||||
let separatorNode = self.actionVerticalSeparators[separatorIndex]
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
|
||||
case .vertical:
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
|
||||
}
|
||||
}
|
||||
separatorIndex += 1
|
||||
|
||||
let currentActionWidth: CGFloat
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
if nodeIndex == self.actionNodes.count - 1 {
|
||||
currentActionWidth = resultSize.width - actionOffset
|
||||
} else {
|
||||
currentActionWidth = actionWidth
|
||||
}
|
||||
case .vertical:
|
||||
currentActionWidth = resultSize.width
|
||||
}
|
||||
|
||||
let actionNodeFrame: CGRect
|
||||
switch effectiveActionLayout {
|
||||
case .horizontal:
|
||||
actionNodeFrame = CGRect(origin: CGPoint(x: actionOffset, y: resultSize.height - actionsHeight), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
|
||||
actionOffset += currentActionWidth
|
||||
case .vertical:
|
||||
actionNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
|
||||
actionOffset += actionButtonHeight
|
||||
}
|
||||
|
||||
transition.updateFrame(node: actionNode, frame: actionNodeFrame)
|
||||
|
||||
nodeIndex += 1
|
||||
}
|
||||
|
||||
if !hadValidLayout {
|
||||
self.inputFieldNode.activateInput()
|
||||
}
|
||||
|
||||
return resultSize
|
||||
}
|
||||
|
||||
func animateError() {
|
||||
self.inputFieldNode.layer.addShakeAnimation()
|
||||
self.hapticFeedback.error()
|
||||
}
|
||||
}
|
||||
|
||||
func giftAuctionCustomBidController(context: AccountContext, title: String, text: String, placeholder: String, value: Int64, apply: @escaping (Int64) -> Void) -> AlertController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var dismissImpl: ((Bool) -> Void)?
|
||||
var applyImpl: (() -> Void)?
|
||||
|
||||
let actions: [TextAlertAction] = [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
dismissImpl?(true)
|
||||
}), TextAlertAction(type: .defaultAction, title: "Place a Bid", action: {
|
||||
applyImpl?()
|
||||
})]
|
||||
|
||||
let contentNode = giftAuctionCustomBidAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: presentationData.strings, actions: actions, title: title, text: text, placeholder: placeholder, value: value)
|
||||
contentNode.complete = {
|
||||
applyImpl?()
|
||||
}
|
||||
applyImpl = { [weak contentNode] in
|
||||
guard let contentNode = contentNode else {
|
||||
return
|
||||
}
|
||||
dismissImpl?(true)
|
||||
|
||||
if let value = Int64(contentNode.value.trimmingCharacters(in: .whitespacesAndNewlines)) {
|
||||
apply(value)
|
||||
}
|
||||
}
|
||||
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
|
||||
let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
|
||||
controller?.theme = AlertControllerTheme(presentationData: presentationData)
|
||||
contentNode?.inputFieldNode.updateTheme(presentationData.theme)
|
||||
})
|
||||
controller.dismissed = { _ in
|
||||
presentationDataDisposable.dispose()
|
||||
}
|
||||
dismissImpl = { [weak controller, weak contentNode] animated in
|
||||
contentNode?.inputFieldNode.deactivateInput()
|
||||
if animated {
|
||||
controller?.dismissAnimated()
|
||||
} else {
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
|
@ -33,17 +33,20 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
||||
let context: AccountContext
|
||||
let toPeerId: EnginePeer.Id
|
||||
let auctionContext: GiftAuctionContext
|
||||
let animateOut: ActionSlot<Action<()>>
|
||||
let getController: () -> ViewController?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
toPeerId: EnginePeer.Id,
|
||||
auctionContext: GiftAuctionContext,
|
||||
animateOut: ActionSlot<Action<()>>,
|
||||
getController: @escaping () -> ViewController?
|
||||
) {
|
||||
self.context = context
|
||||
self.toPeerId = toPeerId
|
||||
self.auctionContext = auctionContext
|
||||
self.animateOut = animateOut
|
||||
self.getController = getController
|
||||
|
|
@ -60,6 +63,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||
let averagePriceTag = GenericComponentViewTag()
|
||||
|
||||
private let context: AccountContext
|
||||
private let toPeerId: EnginePeer.Id
|
||||
private let auctionContext: GiftAuctionContext
|
||||
private let animateOut: ActionSlot<Action<()>>
|
||||
private let getController: () -> ViewController?
|
||||
|
|
@ -78,11 +82,13 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||
|
||||
init(
|
||||
context: AccountContext,
|
||||
toPeerId: EnginePeer.Id,
|
||||
auctionContext: GiftAuctionContext,
|
||||
animateOut: ActionSlot<Action<()>>,
|
||||
getController: @escaping () -> ViewController?
|
||||
) {
|
||||
self.context = context
|
||||
self.toPeerId = toPeerId
|
||||
self.auctionContext = auctionContext
|
||||
self.animateOut = animateOut
|
||||
self.getController = getController
|
||||
|
|
@ -163,7 +169,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||
|
||||
self.dismiss(animated: true)
|
||||
|
||||
let bidController = self.context.sharedContext.makeGiftAuctionBidScreen(context: self.context, auctionContext: self.auctionContext)
|
||||
let bidController = self.context.sharedContext.makeGiftAuctionBidScreen(context: self.context, toPeerId: self.auctionContext.currentBidPeerId ?? self.toPeerId, auctionContext: self.auctionContext)
|
||||
navigationController.pushViewController(bidController)
|
||||
}
|
||||
|
||||
|
|
@ -344,7 +350,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
|
|||
}
|
||||
|
||||
func makeState() -> State {
|
||||
return State(context: self.context, auctionContext: self.auctionContext, animateOut: self.animateOut, getController: self.getController)
|
||||
return State(context: self.context, toPeerId: self.toPeerId, auctionContext: self.auctionContext, animateOut: self.animateOut, getController: self.getController)
|
||||
}
|
||||
|
||||
static var body: Body {
|
||||
|
|
@ -958,13 +964,16 @@ final class GiftAuctionViewSheetComponent: CombinedComponent {
|
|||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
||||
let context: AccountContext
|
||||
let toPeerId: EnginePeer.Id
|
||||
let auctionContext: GiftAuctionContext
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
toPeerId: EnginePeer.Id,
|
||||
auctionContext: GiftAuctionContext
|
||||
) {
|
||||
self.context = context
|
||||
self.toPeerId = toPeerId
|
||||
self.auctionContext = auctionContext
|
||||
}
|
||||
|
||||
|
|
@ -989,6 +998,7 @@ final class GiftAuctionViewSheetComponent: CombinedComponent {
|
|||
component: SheetComponent<EnvironmentType>(
|
||||
content: AnyComponent<EnvironmentType>(GiftAuctionViewSheetContent(
|
||||
context: context.component.context,
|
||||
toPeerId: context.component.toPeerId,
|
||||
auctionContext: context.component.auctionContext,
|
||||
animateOut: animateOut,
|
||||
getController: controller
|
||||
|
|
@ -1071,12 +1081,14 @@ final class GiftAuctionViewSheetComponent: CombinedComponent {
|
|||
public final class GiftAuctionViewScreen: ViewControllerComponentContainer {
|
||||
public init(
|
||||
context: AccountContext,
|
||||
toPeerId: EnginePeer.Id,
|
||||
auctionContext: GiftAuctionContext
|
||||
) {
|
||||
super.init(
|
||||
context: context,
|
||||
component: GiftAuctionViewSheetComponent(
|
||||
context: context,
|
||||
toPeerId: toPeerId,
|
||||
auctionContext: auctionContext
|
||||
),
|
||||
navigationBarAppearance: .none,
|
||||
|
|
|
|||
|
|
@ -1499,15 +1499,17 @@ func openResolvedUrlImpl(
|
|||
}
|
||||
case let .auction(auctionContext):
|
||||
if let auctionContext {
|
||||
if let _ = auctionContext.currentBidPeerId {
|
||||
if let currentBidPeerId = auctionContext.currentBidPeerId {
|
||||
let controller = context.sharedContext.makeGiftAuctionBidScreen(
|
||||
context: context,
|
||||
toPeerId: currentBidPeerId,
|
||||
auctionContext: auctionContext
|
||||
)
|
||||
navigationController?.pushViewController(controller)
|
||||
} else {
|
||||
let controller = context.sharedContext.makeGiftAuctionViewScreen(
|
||||
context: context,
|
||||
toPeerId: context.account.peerId,
|
||||
auctionContext: auctionContext
|
||||
)
|
||||
navigationController?.pushViewController(controller)
|
||||
|
|
|
|||
|
|
@ -3846,12 +3846,12 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
return GiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: completion)
|
||||
}
|
||||
|
||||
public func makeGiftAuctionBidScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController {
|
||||
return GiftAuctionBidScreen(context: context, auctionContext: auctionContext)
|
||||
public func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, auctionContext: GiftAuctionContext) -> ViewController {
|
||||
return GiftAuctionBidScreen(context: context, toPeerId: toPeerId, auctionContext: auctionContext)
|
||||
}
|
||||
|
||||
public func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext) -> ViewController {
|
||||
return GiftAuctionViewScreen(context: context, auctionContext: auctionContext)
|
||||
public func makeGiftAuctionViewScreen(context: AccountContext, toPeerId: EnginePeer.Id, auctionContext: GiftAuctionContext) -> ViewController {
|
||||
return GiftAuctionViewScreen(context: context, toPeerId: toPeerId, auctionContext: auctionContext)
|
||||
}
|
||||
|
||||
public func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue