mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
c504c1d70e
commit
c400ccda24
@ -1005,6 +1005,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeStarsTransactionsScreen(context: AccountContext, starsContext: StarsContext) -> ViewController
|
func makeStarsTransactionsScreen(context: AccountContext, starsContext: StarsContext) -> ViewController
|
||||||
func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, completion: @escaping (Int64) -> Void) -> ViewController
|
func makeStarsPurchaseScreen(context: AccountContext, starsContext: StarsContext, options: [Any], purpose: StarsPurchasePurpose, completion: @escaping (Int64) -> Void) -> ViewController
|
||||||
func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, extendedMedia: [TelegramExtendedMedia], inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>, completion: @escaping (Bool) -> Void) -> ViewController
|
func makeStarsTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, source: BotPaymentInvoiceSource, extendedMedia: [TelegramExtendedMedia], inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>, completion: @escaping (Bool) -> Void) -> ViewController
|
||||||
|
func makeStarsSubscriptionTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, link: String, inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>, navigateToPeer: @escaping (EnginePeer) -> Void) -> ViewController
|
||||||
func makeStarsTransactionScreen(context: AccountContext, transaction: StarsContext.State.Transaction, peer: EnginePeer) -> ViewController
|
func makeStarsTransactionScreen(context: AccountContext, transaction: StarsContext.State.Transaction, peer: EnginePeer) -> ViewController
|
||||||
func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt) -> ViewController
|
func makeStarsReceiptScreen(context: AccountContext, receipt: BotPaymentReceipt) -> ViewController
|
||||||
func makeStarsSubscriptionScreen(context: AccountContext, subscription: StarsContext.State.Subscription, update: @escaping (Bool) -> Void) -> ViewController
|
func makeStarsSubscriptionScreen(context: AccountContext, subscription: StarsContext.State.Subscription, update: @escaping (Bool) -> Void) -> ViewController
|
||||||
|
@ -22,13 +22,25 @@ import TextFormat
|
|||||||
private final class InviteLinkEditControllerArguments {
|
private final class InviteLinkEditControllerArguments {
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let updateState: ((InviteLinkEditControllerState) -> InviteLinkEditControllerState) -> Void
|
let updateState: ((InviteLinkEditControllerState) -> InviteLinkEditControllerState) -> Void
|
||||||
|
let focusOnItem: (InviteLinksEditEntryTag) -> Void
|
||||||
|
let errorWithItem: (InviteLinksEditEntryTag) -> Void
|
||||||
let scrollToUsage: () -> Void
|
let scrollToUsage: () -> Void
|
||||||
let dismissInput: () -> Void
|
let dismissInput: () -> Void
|
||||||
let revoke: () -> Void
|
let revoke: () -> Void
|
||||||
|
|
||||||
init(context: AccountContext, updateState: @escaping ((InviteLinkEditControllerState) -> InviteLinkEditControllerState) -> Void, scrollToUsage: @escaping () -> Void, dismissInput: @escaping () -> Void, revoke: @escaping () -> Void) {
|
init(
|
||||||
|
context: AccountContext,
|
||||||
|
updateState: @escaping ((InviteLinkEditControllerState) -> InviteLinkEditControllerState) -> Void,
|
||||||
|
focusOnItem: @escaping (InviteLinksEditEntryTag) -> Void,
|
||||||
|
errorWithItem: @escaping (InviteLinksEditEntryTag) -> Void,
|
||||||
|
scrollToUsage: @escaping () -> Void,
|
||||||
|
dismissInput: @escaping () -> Void,
|
||||||
|
revoke: @escaping () -> Void)
|
||||||
|
{
|
||||||
self.context = context
|
self.context = context
|
||||||
self.updateState = updateState
|
self.updateState = updateState
|
||||||
|
self.focusOnItem = focusOnItem
|
||||||
|
self.errorWithItem = errorWithItem
|
||||||
self.scrollToUsage = scrollToUsage
|
self.scrollToUsage = scrollToUsage
|
||||||
self.dismissInput = dismissInput
|
self.dismissInput = dismissInput
|
||||||
self.revoke = revoke
|
self.revoke = revoke
|
||||||
@ -45,6 +57,7 @@ private enum InviteLinksEditSection: Int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private enum InviteLinksEditEntryTag: ItemListItemTag {
|
private enum InviteLinksEditEntryTag: ItemListItemTag {
|
||||||
|
case subscriptionFee
|
||||||
case usage
|
case usage
|
||||||
|
|
||||||
func isEqual(to other: ItemListItemTag) -> Bool {
|
func isEqual(to other: ItemListItemTag) -> Bool {
|
||||||
@ -79,7 +92,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
|||||||
|
|
||||||
|
|
||||||
case subscriptionFeeToggle(PresentationTheme, String, Bool, Bool)
|
case subscriptionFeeToggle(PresentationTheme, String, Bool, Bool)
|
||||||
case subscriptionFee(PresentationTheme, String, Bool, Int64?, String)
|
case subscriptionFee(PresentationTheme, String, Bool, Int64?, String, Int64?)
|
||||||
case subscriptionFeeInfo(PresentationTheme, String)
|
case subscriptionFeeInfo(PresentationTheme, String)
|
||||||
|
|
||||||
case requestApproval(PresentationTheme, String, Bool, Bool)
|
case requestApproval(PresentationTheme, String, Bool, Bool)
|
||||||
@ -182,8 +195,8 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .subscriptionFee(lhsTheme, lhsText, lhsValue, lhsEnabled, lhsLabel):
|
case let .subscriptionFee(lhsTheme, lhsText, lhsValue, lhsEnabled, lhsLabel, lhsMaxValue):
|
||||||
if case let .subscriptionFee(rhsTheme, rhsText, rhsValue, rhsEnabled, rhsLabel) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsEnabled == rhsEnabled, lhsLabel == rhsLabel {
|
if case let .subscriptionFee(rhsTheme, rhsText, rhsValue, rhsEnabled, rhsLabel, rhsMaxValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue, lhsEnabled == rhsEnabled, lhsLabel == rhsLabel, lhsMaxValue == rhsMaxValue {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -300,17 +313,26 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
|||||||
}
|
}
|
||||||
return updatedState
|
return updatedState
|
||||||
}
|
}
|
||||||
|
if value {
|
||||||
|
Queue.mainQueue().after(0.1) {
|
||||||
|
arguments.focusOnItem(.subscriptionFee)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
case let .subscriptionFee(_, placeholder, enabled, value, label):
|
case let .subscriptionFee(_, placeholder, enabled, value, label, maxValue):
|
||||||
let title = NSMutableAttributedString(string: "⭐️", font: Font.semibold(18.0), textColor: .white)
|
let title = NSMutableAttributedString(string: "⭐️", font: Font.semibold(18.0), textColor: .white)
|
||||||
if let range = title.string.range(of: "⭐️") {
|
if let range = title.string.range(of: "⭐️") {
|
||||||
title.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: title.string))
|
title.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: title.string))
|
||||||
title.addAttribute(.baselineOffset, value: -1.0, range: NSRange(range, in: title.string))
|
title.addAttribute(.baselineOffset, value: -1.0, range: NSRange(range, in: title.string))
|
||||||
}
|
}
|
||||||
return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, title: title, text: value.flatMap { "\($0)" } ?? "", placeholder: placeholder, label: label, type: .number, spacing: 3.0, enabled: enabled, sectionId: self.section, textUpdated: { text in
|
return ItemListSingleLineInputItem(context: arguments.context, presentationData: presentationData, title: title, text: value.flatMap { "\($0)" } ?? "", placeholder: placeholder, label: label, type: .number, spacing: 3.0, enabled: enabled, tag: InviteLinksEditEntryTag.subscriptionFee, sectionId: self.section, textUpdated: { text in
|
||||||
arguments.updateState { state in
|
arguments.updateState { state in
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
if let value = Int64(text) {
|
if var value = Int64(text) {
|
||||||
|
if let maxValue, value > maxValue {
|
||||||
|
value = maxValue
|
||||||
|
arguments.errorWithItem(.subscriptionFee)
|
||||||
|
}
|
||||||
updatedState.subscriptionFee = value
|
updatedState.subscriptionFee = value
|
||||||
} else {
|
} else {
|
||||||
updatedState.subscriptionFee = nil
|
updatedState.subscriptionFee = nil
|
||||||
@ -457,7 +479,7 @@ private enum InviteLinksEditEntry: ItemListNodeEntry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: InviteLinkEditControllerState, isGroup: Bool, isPublic: Bool, presentationData: PresentationData, starsState: StarsRevenueStats?) -> [InviteLinksEditEntry] {
|
private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state: InviteLinkEditControllerState, isGroup: Bool, isPublic: Bool, presentationData: PresentationData, starsState: StarsRevenueStats?, configuration: StarsSubscriptionConfiguration) -> [InviteLinksEditEntry] {
|
||||||
var entries: [InviteLinksEditEntry] = []
|
var entries: [InviteLinksEditEntry] = []
|
||||||
|
|
||||||
entries.append(.titleHeader(presentationData.theme, presentationData.strings.InviteLink_Create_LinkNameTitle.uppercased()))
|
entries.append(.titleHeader(presentationData.theme, presentationData.strings.InviteLink_Create_LinkNameTitle.uppercased()))
|
||||||
@ -472,9 +494,9 @@ private func inviteLinkEditControllerEntries(invite: ExportedInvitation?, state:
|
|||||||
if state.subscriptionEnabled {
|
if state.subscriptionEnabled {
|
||||||
var label: String = ""
|
var label: String = ""
|
||||||
if let subscriptionFee = state.subscriptionFee, subscriptionFee > 0, let starsState {
|
if let subscriptionFee = state.subscriptionFee, subscriptionFee > 0, let starsState {
|
||||||
label = formatTonUsdValue(subscriptionFee, divide: false, rate: starsState.usdRate, dateTimeFormat: presentationData.dateTimeFormat)
|
label = "≈\(formatTonUsdValue(subscriptionFee, divide: false, rate: starsState.usdRate, dateTimeFormat: presentationData.dateTimeFormat)) / month"
|
||||||
}
|
}
|
||||||
entries.append(.subscriptionFee(presentationData.theme, "Stars amount per month", isEditingEnabled, state.subscriptionFee, label))
|
entries.append(.subscriptionFee(presentationData.theme, "Stars amount per month", isEditingEnabled, state.subscriptionFee, label, configuration.maxFee))
|
||||||
}
|
}
|
||||||
let infoText: String
|
let infoText: String
|
||||||
if let _ = invite, state.subscriptionEnabled {
|
if let _ = invite, state.subscriptionEnabled {
|
||||||
@ -585,9 +607,15 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
|
|||||||
var dismissImpl: (() -> Void)?
|
var dismissImpl: (() -> Void)?
|
||||||
var dismissInputImpl: (() -> Void)?
|
var dismissInputImpl: (() -> Void)?
|
||||||
var scrollToUsageImpl: (() -> Void)?
|
var scrollToUsageImpl: (() -> Void)?
|
||||||
|
var focusImpl: ((InviteLinksEditEntryTag) -> Void)?
|
||||||
|
var errorImpl: ((InviteLinksEditEntryTag) -> Void)?
|
||||||
|
|
||||||
let arguments = InviteLinkEditControllerArguments(context: context, updateState: { f in
|
let arguments = InviteLinkEditControllerArguments(context: context, updateState: { f in
|
||||||
updateState(f)
|
updateState(f)
|
||||||
|
}, focusOnItem: { tag in
|
||||||
|
focusImpl?(tag)
|
||||||
|
}, errorWithItem: { tag in
|
||||||
|
errorImpl?(tag)
|
||||||
}, scrollToUsage: {
|
}, scrollToUsage: {
|
||||||
scrollToUsageImpl?()
|
scrollToUsageImpl?()
|
||||||
}, dismissInput: {
|
}, dismissInput: {
|
||||||
@ -648,6 +676,8 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
|
|||||||
|
|
||||||
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
|
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
|
||||||
|
|
||||||
|
let configuration = StarsSubscriptionConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
let previousState = Atomic<InviteLinkEditControllerState?>(value: nil)
|
let previousState = Atomic<InviteLinkEditControllerState?>(value: nil)
|
||||||
let signal = combineLatest(
|
let signal = combineLatest(
|
||||||
presentationData,
|
presentationData,
|
||||||
@ -762,7 +792,7 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(invite == nil ? presentationData.strings.InviteLink_Create_Title : presentationData.strings.InviteLink_Create_EditTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(invite == nil ? presentationData.strings.InviteLink_Create_Title : presentationData.strings.InviteLink_Create_EditTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkEditControllerEntries(invite: invite, state: state, isGroup: isGroup, isPublic: isPublic, presentationData: presentationData, starsState: starsState), style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges)
|
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: inviteLinkEditControllerEntries(invite: invite, state: state, isGroup: isGroup, isPublic: isPublic, presentationData: presentationData, starsState: starsState, configuration: configuration), style: .blocks, emptyStateItem: nil, crossfadeState: false, animateChanges: animateChanges)
|
||||||
|
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
}
|
}
|
||||||
@ -806,5 +836,41 @@ public func inviteLinkEditController(context: AccountContext, updatedPresentatio
|
|||||||
dismissImpl = { [weak controller] in
|
dismissImpl = { [weak controller] in
|
||||||
controller?.dismiss()
|
controller?.dismiss()
|
||||||
}
|
}
|
||||||
|
focusImpl = { [weak controller] targetTag in
|
||||||
|
controller?.forEachItemNode { itemNode in
|
||||||
|
if let itemNode = itemNode as? ItemListSingleLineInputItemNode, let tag = itemNode.tag, tag.isEqual(to: targetTag) {
|
||||||
|
itemNode.focus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let hapticFeedback = HapticFeedback()
|
||||||
|
errorImpl = { [weak controller] targetTag in
|
||||||
|
hapticFeedback.error()
|
||||||
|
controller?.forEachItemNode { itemNode in
|
||||||
|
if let itemNode = itemNode as? ItemListSingleLineInputItemNode, let tag = itemNode.tag, tag.isEqual(to: targetTag) {
|
||||||
|
itemNode.animateError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct StarsSubscriptionConfiguration {
|
||||||
|
static var defaultValue: StarsSubscriptionConfiguration {
|
||||||
|
return StarsSubscriptionConfiguration(maxFee: 2500)
|
||||||
|
}
|
||||||
|
|
||||||
|
let maxFee: Int64?
|
||||||
|
|
||||||
|
fileprivate init(maxFee: Int64?) {
|
||||||
|
self.maxFee = maxFee
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func with(appConfiguration: AppConfiguration) -> StarsSubscriptionConfiguration {
|
||||||
|
if let data = appConfiguration.data, let value = data["stars_subscription_amount_max"] as? Double {
|
||||||
|
return StarsSubscriptionConfiguration(maxFee: Int64(value))
|
||||||
|
} else {
|
||||||
|
return .defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -141,6 +141,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
private let textNode: TextFieldNode
|
private let textNode: TextFieldNode
|
||||||
private let clearIconNode: ASImageNode
|
private let clearIconNode: ASImageNode
|
||||||
private let clearButtonNode: HighlightableButtonNode
|
private let clearButtonNode: HighlightableButtonNode
|
||||||
|
private let labelNode: TextNode
|
||||||
|
|
||||||
private var item: ItemListSingleLineInputItem?
|
private var item: ItemListSingleLineInputItem?
|
||||||
|
|
||||||
@ -171,12 +172,17 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
|
|
||||||
self.clearButtonNode = HighlightableButtonNode()
|
self.clearButtonNode = HighlightableButtonNode()
|
||||||
|
|
||||||
|
self.labelNode = TextNode()
|
||||||
|
self.labelNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init(layerBacked: false, dynamicBounce: false)
|
super.init(layerBacked: false, dynamicBounce: false)
|
||||||
|
|
||||||
self.addSubnode(self.titleNode.textNode)
|
self.addSubnode(self.titleNode.textNode)
|
||||||
self.addSubnode(self.textNode)
|
self.addSubnode(self.textNode)
|
||||||
self.addSubnode(self.clearIconNode)
|
self.addSubnode(self.clearIconNode)
|
||||||
self.addSubnode(self.clearButtonNode)
|
self.addSubnode(self.clearButtonNode)
|
||||||
|
self.addSubnode(self.textNode)
|
||||||
|
self.addSubnode(self.labelNode)
|
||||||
|
|
||||||
self.clearButtonNode.addTarget(self, action: #selector(self.clearButtonPressed), forControlEvents: .touchUpInside)
|
self.clearButtonNode.addTarget(self, action: #selector(self.clearButtonPressed), forControlEvents: .touchUpInside)
|
||||||
self.clearButtonNode.highligthedChanged = { [weak self] highlighted in
|
self.clearButtonNode.highligthedChanged = { [weak self] highlighted in
|
||||||
@ -218,6 +224,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode.textNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode.textNode)
|
||||||
let makeTitleWithEntitiesLayout = TextNodeWithEntities.asyncLayout(self.titleNode)
|
let makeTitleWithEntitiesLayout = TextNodeWithEntities.asyncLayout(self.titleNode)
|
||||||
let makeMeasureTitleSizeLayout = TextNode.asyncLayout(self.measureTitleSizeNode)
|
let makeMeasureTitleSizeLayout = TextNode.asyncLayout(self.measureTitleSizeNode)
|
||||||
|
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||||
|
|
||||||
let currentItem = self.item
|
let currentItem = self.item
|
||||||
|
|
||||||
@ -262,6 +269,8 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
|
|
||||||
let (measureTitleLayout, measureTitleSizeApply) = makeMeasureTitleSizeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "A", font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize)), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - 32.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (measureTitleLayout, measureTitleSizeApply) = makeMeasureTitleSizeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "A", font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize)), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - 32.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
|
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label ?? "", font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - 32.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
let separatorHeight = UIScreenPixel
|
let separatorHeight = UIScreenPixel
|
||||||
|
|
||||||
let contentSize = CGSize(width: params.width, height: max(titleLayout.size.height, measureTitleLayout.size.height) + 22.0)
|
let contentSize = CGSize(width: params.width, height: max(titleLayout.size.height, measureTitleLayout.size.height) + 22.0)
|
||||||
@ -310,6 +319,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
strongSelf.titleNode.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((layout.contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size)
|
strongSelf.titleNode.textNode.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((layout.contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size)
|
||||||
|
|
||||||
let _ = measureTitleSizeApply()
|
let _ = measureTitleSizeApply()
|
||||||
|
let _ = labelApply()
|
||||||
|
|
||||||
let secureEntry: Bool
|
let secureEntry: Bool
|
||||||
let capitalizationType: UITextAutocapitalizationType
|
let capitalizationType: UITextAutocapitalizationType
|
||||||
@ -379,6 +389,8 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
|||||||
|
|
||||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset + titleLayout.size.width + item.spacing, y: 0.0), size: CGSize(width: max(1.0, params.width - (leftInset + rightInset + titleLayout.size.width + item.spacing)), height: layout.contentSize.height - 2.0))
|
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset + titleLayout.size.width + item.spacing, y: 0.0), size: CGSize(width: max(1.0, params.width - (leftInset + rightInset + titleLayout.size.width + item.spacing)), height: layout.contentSize.height - 2.0))
|
||||||
|
|
||||||
|
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: layoutSize.width - rightInset - labelLayout.size.width, y: floorToScreenPixels((layout.contentSize.height - labelLayout.size.height) / 2.0)), size: labelLayout.size)
|
||||||
|
|
||||||
switch item.alignment {
|
switch item.alignment {
|
||||||
case .default:
|
case .default:
|
||||||
strongSelf.textNode.textField.textAlignment = .natural
|
strongSelf.textNode.textField.textAlignment = .natural
|
||||||
|
@ -911,6 +911,7 @@ private final class StarsSubscriptionsContextImpl {
|
|||||||
|
|
||||||
private let disposable = MetaDisposable()
|
private let disposable = MetaDisposable()
|
||||||
private var stateDisposable: Disposable?
|
private var stateDisposable: Disposable?
|
||||||
|
private let updateDisposable = MetaDisposable()
|
||||||
|
|
||||||
init(account: Account, starsContext: StarsContext) {
|
init(account: Account, starsContext: StarsContext) {
|
||||||
assert(Queue.mainQueue().isCurrent())
|
assert(Queue.mainQueue().isCurrent())
|
||||||
@ -931,6 +932,7 @@ private final class StarsSubscriptionsContextImpl {
|
|||||||
assert(Queue.mainQueue().isCurrent())
|
assert(Queue.mainQueue().isCurrent())
|
||||||
self.disposable.dispose()
|
self.disposable.dispose()
|
||||||
self.stateDisposable?.dispose()
|
self.stateDisposable?.dispose()
|
||||||
|
self.updateDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMore() {
|
func loadMore() {
|
||||||
@ -978,6 +980,7 @@ private final class StarsSubscriptionsContextImpl {
|
|||||||
updatedState.subscriptions[index] = updatedSubscription
|
updatedState.subscriptions[index] = updatedSubscription
|
||||||
}
|
}
|
||||||
self.updateState(updatedState)
|
self.updateState(updatedState)
|
||||||
|
self.updateDisposable.set(_internal_updateStarsSubscription(account: self.account, peerId: self.account.peerId, subscriptionId: id, cancel: cancel).startStrict())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +93,5 @@ public extension TelegramEngine {
|
|||||||
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
||||||
return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source)
|
return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateStarsSubscription(peerId: EnginePeer.Id, subscriptionId: String, cancel: Bool) -> Signal<Never, UpdateStarsSubsciptionError> {
|
|
||||||
return _internal_updateStarsSubscription(account: self.account, peerId: peerId, subscriptionId: subscriptionId, cancel: cancel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
let source: BotPaymentInvoiceSource
|
let source: BotPaymentInvoiceSource
|
||||||
let extendedMedia: [TelegramExtendedMedia]
|
let extendedMedia: [TelegramExtendedMedia]
|
||||||
let inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>
|
let inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>
|
||||||
|
let navigateToPeer: (EnginePeer) -> Void
|
||||||
let dismiss: () -> Void
|
let dismiss: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
@ -38,6 +39,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
source: BotPaymentInvoiceSource,
|
source: BotPaymentInvoiceSource,
|
||||||
extendedMedia: [TelegramExtendedMedia],
|
extendedMedia: [TelegramExtendedMedia],
|
||||||
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>,
|
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>,
|
||||||
|
navigateToPeer: @escaping (EnginePeer) -> Void,
|
||||||
dismiss: @escaping () -> Void
|
dismiss: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -46,6 +48,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
self.source = source
|
self.source = source
|
||||||
self.extendedMedia = extendedMedia
|
self.extendedMedia = extendedMedia
|
||||||
self.inputData = inputData
|
self.inputData = inputData
|
||||||
|
self.navigateToPeer = navigateToPeer
|
||||||
self.dismiss = dismiss
|
self.dismiss = dismiss
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +80,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
private var peerDisposable: Disposable?
|
private var peerDisposable: Disposable?
|
||||||
private(set) var balance: Int64?
|
private(set) var balance: Int64?
|
||||||
private(set) var form: BotPaymentForm?
|
private(set) var form: BotPaymentForm?
|
||||||
|
private(set) var navigateToPeer: (EnginePeer) -> Void
|
||||||
|
|
||||||
private var stateDisposable: Disposable?
|
private var stateDisposable: Disposable?
|
||||||
|
|
||||||
@ -96,13 +100,15 @@ private final class SheetContent: CombinedComponent {
|
|||||||
source: BotPaymentInvoiceSource,
|
source: BotPaymentInvoiceSource,
|
||||||
extendedMedia: [TelegramExtendedMedia],
|
extendedMedia: [TelegramExtendedMedia],
|
||||||
invoice: TelegramMediaInvoice,
|
invoice: TelegramMediaInvoice,
|
||||||
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>
|
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>,
|
||||||
|
navigateToPeer: @escaping (EnginePeer) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.starsContext = starsContext
|
self.starsContext = starsContext
|
||||||
self.source = source
|
self.source = source
|
||||||
self.extendedMedia = extendedMedia
|
self.extendedMedia = extendedMedia
|
||||||
self.invoice = invoice
|
self.invoice = invoice
|
||||||
|
self.navigateToPeer = navigateToPeer
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -159,6 +165,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let navigateToPeer = self.navigateToPeer
|
||||||
let action = { [weak self] in
|
let action = { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -167,8 +174,19 @@ private final class SheetContent: CombinedComponent {
|
|||||||
self.updated()
|
self.updated()
|
||||||
|
|
||||||
let _ = (self.context.engine.payments.sendStarsPaymentForm(formId: form.id, source: self.source)
|
let _ = (self.context.engine.payments.sendStarsPaymentForm(formId: form.id, source: self.source)
|
||||||
|> deliverOnMainQueue).start(next: { _ in
|
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
completion(true)
|
completion(true)
|
||||||
|
if case let .starsChatSubscription(link) = self.source {
|
||||||
|
let _ = (self.context.engine.peers.joinLinkInformation(link)
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { result in
|
||||||
|
if case let .alreadyJoined(peer) = result {
|
||||||
|
navigateToPeer(peer)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}, error: { [weak self] error in
|
}, error: { [weak self] error in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -235,7 +253,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeState() -> State {
|
func makeState() -> State {
|
||||||
return State(context: self.context, starsContext: self.starsContext, source: self.source, extendedMedia: self.extendedMedia, invoice: self.invoice, inputData: self.inputData)
|
return State(context: self.context, starsContext: self.starsContext, source: self.source, extendedMedia: self.extendedMedia, invoice: self.invoice, inputData: self.inputData, navigateToPeer: self.navigateToPeer)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var body: Body {
|
static var body: Body {
|
||||||
@ -639,6 +657,7 @@ private final class StarsTransferSheetComponent: CombinedComponent {
|
|||||||
private let source: BotPaymentInvoiceSource
|
private let source: BotPaymentInvoiceSource
|
||||||
private let extendedMedia: [TelegramExtendedMedia]
|
private let extendedMedia: [TelegramExtendedMedia]
|
||||||
private let inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>
|
private let inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>
|
||||||
|
private let navigateToPeer: (EnginePeer) -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
@ -646,7 +665,8 @@ private final class StarsTransferSheetComponent: CombinedComponent {
|
|||||||
invoice: TelegramMediaInvoice,
|
invoice: TelegramMediaInvoice,
|
||||||
source: BotPaymentInvoiceSource,
|
source: BotPaymentInvoiceSource,
|
||||||
extendedMedia: [TelegramExtendedMedia],
|
extendedMedia: [TelegramExtendedMedia],
|
||||||
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>
|
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>,
|
||||||
|
navigateToPeer: @escaping (EnginePeer) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.starsContext = starsContext
|
self.starsContext = starsContext
|
||||||
@ -654,6 +674,7 @@ private final class StarsTransferSheetComponent: CombinedComponent {
|
|||||||
self.source = source
|
self.source = source
|
||||||
self.extendedMedia = extendedMedia
|
self.extendedMedia = extendedMedia
|
||||||
self.inputData = inputData
|
self.inputData = inputData
|
||||||
|
self.navigateToPeer = navigateToPeer
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: StarsTransferSheetComponent, rhs: StarsTransferSheetComponent) -> Bool {
|
static func ==(lhs: StarsTransferSheetComponent, rhs: StarsTransferSheetComponent) -> Bool {
|
||||||
@ -687,6 +708,7 @@ private final class StarsTransferSheetComponent: CombinedComponent {
|
|||||||
source: context.component.source,
|
source: context.component.source,
|
||||||
extendedMedia: context.component.extendedMedia,
|
extendedMedia: context.component.extendedMedia,
|
||||||
inputData: context.component.inputData,
|
inputData: context.component.inputData,
|
||||||
|
navigateToPeer: context.component.navigateToPeer,
|
||||||
dismiss: {
|
dismiss: {
|
||||||
animateOut.invoke(Action { _ in
|
animateOut.invoke(Action { _ in
|
||||||
if let controller = controller() {
|
if let controller = controller() {
|
||||||
@ -747,6 +769,7 @@ public final class StarsTransferScreen: ViewControllerComponentContainer {
|
|||||||
source: BotPaymentInvoiceSource,
|
source: BotPaymentInvoiceSource,
|
||||||
extendedMedia: [TelegramExtendedMedia] = [],
|
extendedMedia: [TelegramExtendedMedia] = [],
|
||||||
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>,
|
inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>,
|
||||||
|
navigateToPeer: @escaping (EnginePeer) -> Void = { _ in },
|
||||||
completion: @escaping (Bool) -> Void
|
completion: @escaping (Bool) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -761,7 +784,8 @@ public final class StarsTransferScreen: ViewControllerComponentContainer {
|
|||||||
invoice: invoice,
|
invoice: invoice,
|
||||||
source: source,
|
source: source,
|
||||||
extendedMedia: extendedMedia,
|
extendedMedia: extendedMedia,
|
||||||
inputData: inputData
|
inputData: inputData,
|
||||||
|
navigateToPeer: navigateToPeer
|
||||||
),
|
),
|
||||||
navigationBarAppearance: .none,
|
navigationBarAppearance: .none,
|
||||||
statusBarStyle: .ignore,
|
statusBarStyle: .ignore,
|
||||||
|
@ -323,7 +323,8 @@ func openResolvedUrlImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let _ = (starsInputData |> filter { $0 != nil } |> take(1) |> deliverOnMainQueue).start(next: { _ in
|
let _ = (starsInputData |> filter { $0 != nil } |> take(1) |> deliverOnMainQueue).start(next: { _ in
|
||||||
let controller = context.sharedContext.makeStarsTransferScreen(context: context, starsContext: starsContext, invoice: invoice, source: .starsChatSubscription(hash: link), extendedMedia: [], inputData: starsInputData, completion: { _ in
|
let controller = context.sharedContext.makeStarsSubscriptionTransferScreen(context: context, starsContext: starsContext, invoice: invoice, link: link, inputData: starsInputData, navigateToPeer: { peer in
|
||||||
|
openPeer(peer, .chat(textInputState: nil, subject: nil, peekData: nil))
|
||||||
})
|
})
|
||||||
navigationController?.pushViewController(controller)
|
navigationController?.pushViewController(controller)
|
||||||
})
|
})
|
||||||
|
@ -2743,6 +2743,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return StarsTransferScreen(context: context, starsContext: starsContext, invoice: invoice, source: source, extendedMedia: extendedMedia, inputData: inputData, completion: completion)
|
return StarsTransferScreen(context: context, starsContext: starsContext, invoice: invoice, source: source, extendedMedia: extendedMedia, inputData: inputData, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func makeStarsSubscriptionTransferScreen(context: AccountContext, starsContext: StarsContext, invoice: TelegramMediaInvoice, link: String, inputData: Signal<(StarsContext.State, BotPaymentForm, EnginePeer?)?, NoError>, navigateToPeer: @escaping (EnginePeer) -> Void) -> ViewController {
|
||||||
|
return StarsTransferScreen(context: context, starsContext: starsContext, invoice: invoice, source: .starsChatSubscription(hash: link), extendedMedia: [], inputData: inputData, navigateToPeer: navigateToPeer, completion: { _ in })
|
||||||
|
}
|
||||||
|
|
||||||
public func makeStarsTransactionScreen(context: AccountContext, transaction: StarsContext.State.Transaction, peer: EnginePeer) -> ViewController {
|
public func makeStarsTransactionScreen(context: AccountContext, transaction: StarsContext.State.Transaction, peer: EnginePeer) -> ViewController {
|
||||||
return StarsTransactionScreen(context: context, subject: .transaction(transaction, peer))
|
return StarsTransactionScreen(context: context, subject: .transaction(transaction, peer))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user