mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Merge commit '17140bf9616ce2aca148d07c36b72577012aa3ab'
This commit is contained in:
commit
200b86a384
@ -34,6 +34,7 @@ public final class MultilineTextWithEntitiesComponent: Component {
|
|||||||
public let handleSpoilers: Bool
|
public let handleSpoilers: Bool
|
||||||
public let manualVisibilityControl: Bool
|
public let manualVisibilityControl: Bool
|
||||||
public let resetAnimationsOnVisibilityChange: Bool
|
public let resetAnimationsOnVisibilityChange: Bool
|
||||||
|
public let displaysAsynchronously: Bool
|
||||||
public let highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)?
|
public let highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)?
|
||||||
public let tapAction: (([NSAttributedString.Key: Any], Int) -> Void)?
|
public let tapAction: (([NSAttributedString.Key: Any], Int) -> Void)?
|
||||||
public let longTapAction: (([NSAttributedString.Key: Any], Int) -> Void)?
|
public let longTapAction: (([NSAttributedString.Key: Any], Int) -> Void)?
|
||||||
@ -58,6 +59,7 @@ public final class MultilineTextWithEntitiesComponent: Component {
|
|||||||
handleSpoilers: Bool = false,
|
handleSpoilers: Bool = false,
|
||||||
manualVisibilityControl: Bool = false,
|
manualVisibilityControl: Bool = false,
|
||||||
resetAnimationsOnVisibilityChange: Bool = false,
|
resetAnimationsOnVisibilityChange: Bool = false,
|
||||||
|
displaysAsynchronously: Bool = true,
|
||||||
highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? = nil,
|
highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? = nil,
|
||||||
tapAction: (([NSAttributedString.Key: Any], Int) -> Void)? = nil,
|
tapAction: (([NSAttributedString.Key: Any], Int) -> Void)? = nil,
|
||||||
longTapAction: (([NSAttributedString.Key: Any], Int) -> Void)? = nil
|
longTapAction: (([NSAttributedString.Key: Any], Int) -> Void)? = nil
|
||||||
@ -82,6 +84,7 @@ public final class MultilineTextWithEntitiesComponent: Component {
|
|||||||
self.handleSpoilers = handleSpoilers
|
self.handleSpoilers = handleSpoilers
|
||||||
self.manualVisibilityControl = manualVisibilityControl
|
self.manualVisibilityControl = manualVisibilityControl
|
||||||
self.resetAnimationsOnVisibilityChange = resetAnimationsOnVisibilityChange
|
self.resetAnimationsOnVisibilityChange = resetAnimationsOnVisibilityChange
|
||||||
|
self.displaysAsynchronously = displaysAsynchronously
|
||||||
self.tapAction = tapAction
|
self.tapAction = tapAction
|
||||||
self.longTapAction = longTapAction
|
self.longTapAction = longTapAction
|
||||||
}
|
}
|
||||||
@ -120,6 +123,9 @@ public final class MultilineTextWithEntitiesComponent: Component {
|
|||||||
if lhs.resetAnimationsOnVisibilityChange != rhs.resetAnimationsOnVisibilityChange {
|
if lhs.resetAnimationsOnVisibilityChange != rhs.resetAnimationsOnVisibilityChange {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.displaysAsynchronously != rhs.displaysAsynchronously {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if let lhsTextShadowColor = lhs.textShadowColor, let rhsTextShadowColor = rhs.textShadowColor {
|
if let lhsTextShadowColor = lhs.textShadowColor, let rhsTextShadowColor = rhs.textShadowColor {
|
||||||
if !lhsTextShadowColor.isEqual(rhsTextShadowColor) {
|
if !lhsTextShadowColor.isEqual(rhsTextShadowColor) {
|
||||||
return false
|
return false
|
||||||
@ -161,6 +167,7 @@ public final class MultilineTextWithEntitiesComponent: Component {
|
|||||||
public override init(frame: CGRect) {
|
public override init(frame: CGRect) {
|
||||||
self.textNode = ImmediateTextNodeWithEntities()
|
self.textNode = ImmediateTextNodeWithEntities()
|
||||||
|
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.addSubview(self.textNode.view)
|
self.addSubview(self.textNode.view)
|
||||||
@ -175,6 +182,8 @@ public final class MultilineTextWithEntitiesComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func update(component: MultilineTextWithEntitiesComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
|
public func update(component: MultilineTextWithEntitiesComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
|
||||||
|
self.textNode.displaysAsynchronously = component.displaysAsynchronously
|
||||||
|
|
||||||
let attributedString: NSAttributedString
|
let attributedString: NSAttributedString
|
||||||
switch component.text {
|
switch component.text {
|
||||||
case let .plain(string):
|
case let .plain(string):
|
||||||
|
|||||||
@ -618,7 +618,7 @@ private func autosaveLabelAndValue(presentationData: PresentationData, settings:
|
|||||||
return (label, value)
|
return (label, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dataAndStorageControllerEntries(state: DataAndStorageControllerState, data: DataAndStorageData, presentationData: PresentationData, defaultWebBrowser: String, contentSettingsConfiguration: ContentSettingsConfiguration?, networkUsage: Int64, storageUsage: Int64, mediaAutoSaveSettings: MediaAutoSaveSettings, autosaveExceptionPeers: [EnginePeer.Id: EnginePeer?], mediaSettings: MediaDisplaySettings, showSensitiveContentSetting: Bool) -> [DataAndStorageEntry] {
|
private func dataAndStorageControllerEntries(context: AccountContext, state: DataAndStorageControllerState, data: DataAndStorageData, presentationData: PresentationData, defaultWebBrowser: String, contentSettingsConfiguration: ContentSettingsConfiguration?, networkUsage: Int64, storageUsage: Int64, mediaAutoSaveSettings: MediaAutoSaveSettings, autosaveExceptionPeers: [EnginePeer.Id: EnginePeer?], mediaSettings: MediaDisplaySettings, showSensitiveContentSetting: Bool) -> [DataAndStorageEntry] {
|
||||||
var entries: [DataAndStorageEntry] = []
|
var entries: [DataAndStorageEntry] = []
|
||||||
|
|
||||||
entries.append(.storageUsage(presentationData.theme, presentationData.strings.ChatSettings_Cache, dataSizeString(storageUsage, formatting: DataSizeStringFormatting(presentationData: presentationData))))
|
entries.append(.storageUsage(presentationData.theme, presentationData.strings.ChatSettings_Cache, dataSizeString(storageUsage, formatting: DataSizeStringFormatting(presentationData: presentationData))))
|
||||||
@ -657,7 +657,7 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
|||||||
entries.append(.raiseToListen(presentationData.theme, presentationData.strings.Settings_RaiseToListen, data.mediaInputSettings.enableRaiseToSpeak))
|
entries.append(.raiseToListen(presentationData.theme, presentationData.strings.Settings_RaiseToListen, data.mediaInputSettings.enableRaiseToSpeak))
|
||||||
entries.append(.raiseToListenInfo(presentationData.theme, presentationData.strings.Settings_RaiseToListenInfo))
|
entries.append(.raiseToListenInfo(presentationData.theme, presentationData.strings.Settings_RaiseToListenInfo))
|
||||||
|
|
||||||
if let contentSettingsConfiguration = contentSettingsConfiguration, contentSettingsConfiguration.canAdjustSensitiveContent && showSensitiveContentSetting {
|
if let contentSettingsConfiguration = contentSettingsConfiguration, contentSettingsConfiguration.canAdjustSensitiveContent && (showSensitiveContentSetting || requireAgeVerification(context: context)) {
|
||||||
entries.append(.sensitiveContent(presentationData.strings.Settings_SensitiveContent, contentSettingsConfiguration.sensitiveContentEnabled))
|
entries.append(.sensitiveContent(presentationData.strings.Settings_SensitiveContent, contentSettingsConfiguration.sensitiveContentEnabled))
|
||||||
entries.append(.sensitiveContentInfo(presentationData.strings.Settings_SensitiveContentInfo))
|
entries.append(.sensitiveContentInfo(presentationData.strings.Settings_SensitiveContentInfo))
|
||||||
}
|
}
|
||||||
@ -685,6 +685,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
|
|
||||||
var pushControllerImpl: ((ViewController) -> Void)?
|
var pushControllerImpl: ((ViewController) -> Void)?
|
||||||
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
|
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
|
||||||
|
var presentAgeVerificationImpl: ((@escaping () -> Void) -> Void)?
|
||||||
|
|
||||||
let actionsDisposable = DisposableSet()
|
let actionsDisposable = DisposableSet()
|
||||||
|
|
||||||
@ -914,6 +915,9 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
|
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
|
||||||
}
|
}
|
||||||
if value {
|
if value {
|
||||||
|
if requireAgeVerification(context: context) {
|
||||||
|
presentAgeVerificationImpl?(update)
|
||||||
|
} else {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let alertController = textAlertController(context: context, title: presentationData.strings.SensitiveContent_Enable_Title, text: presentationData.strings.SensitiveContent_Enable_Text, actions: [
|
let alertController = textAlertController(context: context, title: presentationData.strings.SensitiveContent_Enable_Title, text: presentationData.strings.SensitiveContent_Enable_Text, actions: [
|
||||||
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
|
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
|
||||||
@ -922,6 +926,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
})
|
})
|
||||||
])
|
])
|
||||||
presentControllerImpl?(alertController, nil)
|
presentControllerImpl?(alertController, nil)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
@ -983,7 +988,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
let showSensitiveContentSetting = canAdjustSensitiveContent.with { $0 } ?? false
|
let showSensitiveContentSetting = canAdjustSensitiveContent.with { $0 } ?? false
|
||||||
|
|
||||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChatSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChatSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: dataAndStorageControllerEntries(state: state, data: dataAndStorageData, presentationData: presentationData, defaultWebBrowser: defaultWebBrowser, contentSettingsConfiguration: contentSettingsConfiguration, networkUsage: usageSignal.network, storageUsage: usageSignal.storage, mediaAutoSaveSettings: mediaAutoSaveSettings, autosaveExceptionPeers: autosaveExceptionPeers, mediaSettings: mediaSettings, showSensitiveContentSetting: showSensitiveContentSetting), style: .blocks, ensureVisibleItemTag: focusOnItemTag, emptyStateItem: nil, animateChanges: animateChanges)
|
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: dataAndStorageControllerEntries(context: context, state: state, data: dataAndStorageData, presentationData: presentationData, defaultWebBrowser: defaultWebBrowser, contentSettingsConfiguration: contentSettingsConfiguration, networkUsage: usageSignal.network, storageUsage: usageSignal.storage, mediaAutoSaveSettings: mediaAutoSaveSettings, autosaveExceptionPeers: autosaveExceptionPeers, mediaSettings: mediaSettings, showSensitiveContentSetting: showSensitiveContentSetting), style: .blocks, ensureVisibleItemTag: focusOnItemTag, emptyStateItem: nil, animateChanges: animateChanges)
|
||||||
|
|
||||||
return (controllerState, (listState, arguments))
|
return (controllerState, (listState, arguments))
|
||||||
} |> afterDisposed {
|
} |> afterDisposed {
|
||||||
@ -999,6 +1004,14 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
presentControllerImpl = { [weak controller] c, a in
|
presentControllerImpl = { [weak controller] c, a in
|
||||||
controller?.present(c, in: .window(.root), with: a)
|
controller?.present(c, in: .window(.root), with: a)
|
||||||
}
|
}
|
||||||
|
presentAgeVerificationImpl = { [weak controller] update in
|
||||||
|
guard let controller else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
presentAgeVerification(context: context, parentController: controller, completion: {
|
||||||
|
update()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import SwiftSignalKit
|
|||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
import Display
|
import Display
|
||||||
import ComponentFlow
|
import ComponentFlow
|
||||||
|
import ComponentDisplayAdapters
|
||||||
import Postbox
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
@ -323,11 +324,14 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
private weak var parentNavigationController: NavigationController?
|
private weak var parentNavigationController: NavigationController?
|
||||||
private let chatPeerId: EnginePeer.Id
|
private let chatPeerId: EnginePeer.Id
|
||||||
private let showBalance: Bool
|
private let showBalance: Bool
|
||||||
|
private let animateBalanceOverlay: Bool
|
||||||
|
|
||||||
|
private var didUpdateCurrency = false
|
||||||
public var currency: CurrencyAmount.Currency {
|
public var currency: CurrencyAmount.Currency {
|
||||||
didSet {
|
didSet {
|
||||||
|
self.didUpdateCurrency = true
|
||||||
if let layout = self.validLayout {
|
if let layout = self.validLayout {
|
||||||
self.containerLayoutUpdated(layout, transition: .immediate)
|
self.containerLayoutUpdated(layout, transition: .animated(duration: 0.25, curve: .easeInOut))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,13 +342,23 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
|
|
||||||
private var validLayout: ContainerViewLayout?
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
public init(context: AccountContext?, presentationData: PresentationData, contentNode: AlertContentNode, navigationController: NavigationController?, chatPeerId: EnginePeer.Id, showBalance: Bool = true, currency: CurrencyAmount.Currency = .stars) {
|
public init(
|
||||||
|
context: AccountContext?,
|
||||||
|
presentationData: PresentationData,
|
||||||
|
contentNode: AlertContentNode,
|
||||||
|
navigationController: NavigationController?,
|
||||||
|
chatPeerId: EnginePeer.Id,
|
||||||
|
showBalance: Bool = true,
|
||||||
|
currency: CurrencyAmount.Currency = .stars,
|
||||||
|
animateBalanceOverlay: Bool = true
|
||||||
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.parentNavigationController = navigationController
|
self.parentNavigationController = navigationController
|
||||||
self.chatPeerId = chatPeerId
|
self.chatPeerId = chatPeerId
|
||||||
self.showBalance = showBalance
|
self.showBalance = showBalance
|
||||||
self.currency = currency
|
self.currency = currency
|
||||||
|
self.animateBalanceOverlay = animateBalanceOverlay
|
||||||
|
|
||||||
super.init(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
|
super.init(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
|
||||||
|
|
||||||
@ -361,11 +375,20 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func animateOut() {
|
private func animateOut() {
|
||||||
|
if !self.animateBalanceOverlay {
|
||||||
|
if self.currency == .ton && self.didUpdateCurrency {
|
||||||
|
self.currency = .stars
|
||||||
|
}
|
||||||
|
Queue.mainQueue().after(0.39, {
|
||||||
|
|
||||||
|
})
|
||||||
|
} else {
|
||||||
if let view = self.balance.view {
|
if let view = self.balance.view {
|
||||||
view.layer.animateScale(from: 1.0, to: 0.8, duration: 0.4, removeOnCompletion: false)
|
view.layer.animateScale(from: 1.0, to: 0.8, duration: 0.4, removeOnCompletion: false)
|
||||||
view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override func dismissAnimated() {
|
public override func dismissAnimated() {
|
||||||
super.dismissAnimated()
|
super.dismissAnimated()
|
||||||
@ -389,8 +412,13 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
|
|
||||||
if let context = self.context, let _ = self.parentNavigationController, self.showBalance {
|
if let context = self.context, let _ = self.parentNavigationController, self.showBalance {
|
||||||
let insets = layout.insets(options: .statusBar)
|
let insets = layout.insets(options: .statusBar)
|
||||||
|
var balanceTransition = ComponentTransition(transition)
|
||||||
|
if self.balance.view == nil {
|
||||||
|
balanceTransition = .immediate
|
||||||
|
}
|
||||||
|
|
||||||
let balanceSize = self.balance.update(
|
let balanceSize = self.balance.update(
|
||||||
transition: .immediate,
|
transition: balanceTransition,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
StarsBalanceOverlayComponent(
|
StarsBalanceOverlayComponent(
|
||||||
context: context,
|
context: context,
|
||||||
@ -401,8 +429,8 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
guard let self, let starsContext = context.starsContext, let navigationController = self.parentNavigationController else {
|
guard let self, let starsContext = context.starsContext, let navigationController = self.parentNavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.dismissAnimated()
|
switch self.currency {
|
||||||
|
case .stars:
|
||||||
let _ = (context.engine.payments.starsTopUpOptions()
|
let _ = (context.engine.payments.starsTopUpOptions()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).startStandalone(next: { options in
|
|> deliverOnMainQueue).startStandalone(next: { options in
|
||||||
@ -415,6 +443,14 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
)
|
)
|
||||||
navigationController.pushViewController(controller)
|
navigationController.pushViewController(controller)
|
||||||
})
|
})
|
||||||
|
case .ton:
|
||||||
|
var fragmentUrl = "https://fragment.com/ads/topup"
|
||||||
|
if let data = context.currentAppConfiguration.with({ $0 }).data, let value = data["ton_topup_url"] as? String {
|
||||||
|
fragmentUrl = value
|
||||||
|
}
|
||||||
|
context.sharedContext.applicationBindings.openUrl(fragmentUrl)
|
||||||
|
}
|
||||||
|
self.dismissAnimated()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -425,11 +461,13 @@ public class ChatMessagePaymentAlertController: AlertController {
|
|||||||
if view.superview == nil {
|
if view.superview == nil {
|
||||||
self.view.addSubview(view)
|
self.view.addSubview(view)
|
||||||
|
|
||||||
|
if self.animateBalanceOverlay {
|
||||||
view.layer.animatePosition(from: CGPoint(x: 0.0, y: -64.0), to: .zero, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
view.layer.animatePosition(from: CGPoint(x: 0.0, y: -64.0), to: .zero, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||||
view.layer.animateSpring(from: 0.8 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, removeOnCompletion: true, additive: false, completion: nil)
|
view.layer.animateSpring(from: 0.8 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, removeOnCompletion: true, additive: false, completion: nil)
|
||||||
view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||||
}
|
}
|
||||||
view.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - balanceSize.width) / 2.0), y: insets.top + 5.0), size: balanceSize)
|
}
|
||||||
|
balanceTransition.setFrame(view: view, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - balanceSize.width) / 2.0), y: insets.top + 5.0), size: balanceSize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -162,10 +162,12 @@ final class GiftStoreScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
|
private func updateScrolling(interactive: Bool = false, transition: ComponentTransition) {
|
||||||
guard let environment = self.environment, let component = self.component, self.state?.starGiftsState?.dataState != .loading else {
|
guard let environment = self.environment, let component = self.component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//, self.state?.starGiftsState?.dataState != .loading
|
||||||
|
|
||||||
let availableWidth = self.scrollView.bounds.width
|
let availableWidth = self.scrollView.bounds.width
|
||||||
let availableHeight = self.scrollView.bounds.height
|
let availableHeight = self.scrollView.bounds.height
|
||||||
let contentOffset = self.scrollView.contentOffset.y
|
let contentOffset = self.scrollView.contentOffset.y
|
||||||
@ -456,7 +458,7 @@ final class GiftStoreScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let bottomContentOffset = max(0.0, self.scrollView.contentSize.height - self.scrollView.contentOffset.y - self.scrollView.frame.height)
|
let bottomContentOffset = max(0.0, self.scrollView.contentSize.height - self.scrollView.contentOffset.y - self.scrollView.frame.height)
|
||||||
if interactive, bottomContentOffset < 1000.0 {
|
if interactive, bottomContentOffset < 800.0 {
|
||||||
self.state?.starGiftsContext.loadMore()
|
self.state?.starGiftsContext.loadMore()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1142,7 +1144,7 @@ final class GiftStoreScreenComponent: Component {
|
|||||||
context: component.context,
|
context: component.context,
|
||||||
colors: FilterSelectorComponent.Colors(
|
colors: FilterSelectorComponent.Colors(
|
||||||
foreground: theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.65),
|
foreground: theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.65),
|
||||||
background: theme.list.itemSecondaryTextColor.mixedWith(theme.list.blocksBackgroundColor, alpha: 0.85)
|
background: theme.list.itemSecondaryTextColor.withMultipliedAlpha(0.15)
|
||||||
),
|
),
|
||||||
items: filterItems,
|
items: filterItems,
|
||||||
selectedItemId: self.selectedFilterId
|
selectedItemId: self.selectedFilterId
|
||||||
|
|||||||
@ -446,7 +446,8 @@ public func giftPurchaseAlertController(
|
|||||||
gift: StarGift.UniqueGift,
|
gift: StarGift.UniqueGift,
|
||||||
peer: EnginePeer,
|
peer: EnginePeer,
|
||||||
navigationController: NavigationController?,
|
navigationController: NavigationController?,
|
||||||
commit: @escaping (CurrencyAmount.Currency) -> Void
|
commit: @escaping (CurrencyAmount.Currency) -> Void,
|
||||||
|
dismissed: @escaping () -> Void
|
||||||
) -> AlertController {
|
) -> AlertController {
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
let strings = presentationData.strings
|
let strings = presentationData.strings
|
||||||
@ -463,7 +464,19 @@ public func giftPurchaseAlertController(
|
|||||||
|
|
||||||
contentNode = GiftPurchaseAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), presentationTheme: presentationData.theme, strings: strings, gift: gift, peer: peer, actions: actions)
|
contentNode = GiftPurchaseAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), presentationTheme: presentationData.theme, strings: strings, gift: gift, peer: peer, actions: actions)
|
||||||
|
|
||||||
let controller = ChatMessagePaymentAlertController(context: context, presentationData: presentationData, contentNode: contentNode!, navigationController: navigationController, chatPeerId: context.account.peerId, showBalance: true, currency: gift.resellForTonOnly ? .ton : .stars)
|
let controller = ChatMessagePaymentAlertController(
|
||||||
|
context: context,
|
||||||
|
presentationData: presentationData,
|
||||||
|
contentNode: contentNode!,
|
||||||
|
navigationController: navigationController,
|
||||||
|
chatPeerId: context.account.peerId,
|
||||||
|
showBalance: true,
|
||||||
|
currency: gift.resellForTonOnly ? .ton : .stars,
|
||||||
|
animateBalanceOverlay: false
|
||||||
|
)
|
||||||
|
controller.dismissed = { _ in
|
||||||
|
dismissed()
|
||||||
|
}
|
||||||
|
|
||||||
dismissImpl = { [weak controller] animated in
|
dismissImpl = { [weak controller] animated in
|
||||||
if animated {
|
if animated {
|
||||||
|
|||||||
@ -1367,8 +1367,9 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let buyForm = self.buyForm, let price = buyForm.invoice.prices.first?.amount {
|
|
||||||
if buyForm.invoice.currency == "XTR", let starsContext = context.starsContext, let starsState = context.starsContext?.currentState, starsState.balance < StarsAmount(value: price, nanos: 0) {
|
if let _ = self.buyForm {
|
||||||
|
if resellAmount.currency == .stars, let starsContext = context.starsContext, let starsState = context.starsContext?.currentState, starsState.balance < resellAmount.amount {
|
||||||
if self.options.isEmpty {
|
if self.options.isEmpty {
|
||||||
self.inProgress = true
|
self.inProgress = true
|
||||||
self.updated()
|
self.updated()
|
||||||
@ -1384,7 +1385,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
context: context,
|
context: context,
|
||||||
starsContext: starsContext,
|
starsContext: starsContext,
|
||||||
options: options ?? [],
|
options: options ?? [],
|
||||||
purpose: .buyStarGift(requiredStars: price),
|
purpose: .buyStarGift(requiredStars: resellAmount.amount.value),
|
||||||
completion: { [weak self, weak starsContext] stars in
|
completion: { [weak self, weak starsContext] stars in
|
||||||
guard let self, let starsContext else {
|
guard let self, let starsContext else {
|
||||||
return
|
return
|
||||||
@ -1402,7 +1403,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
guard let self, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
guard let self, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if starsState.balance < StarsAmount(value: price, nanos: 0) {
|
if starsState.balance < resellAmount.amount {
|
||||||
self.inProgress = false
|
self.inProgress = false
|
||||||
self.updated()
|
self.updated()
|
||||||
|
|
||||||
@ -1416,11 +1417,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
controller.push(purchaseController)
|
controller.push(purchaseController)
|
||||||
})
|
})
|
||||||
} else if buyForm.invoice.currency == "TON", let tonState = context.tonContext?.currentState, tonState.balance < StarsAmount(value: price, nanos: 0) {
|
} else if resellAmount.currency == .ton, let tonState = context.tonContext?.currentState, tonState.balance < resellAmount.amount {
|
||||||
guard let controller = self.getController() else {
|
guard let controller = self.getController() else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let needed = StarsAmount(value: price, nanos: 0) - tonState.balance
|
let needed = resellAmount.amount - tonState.balance
|
||||||
var fragmentUrl = "https://fragment.com/ads/topup"
|
var fragmentUrl = "https://fragment.com/ads/topup"
|
||||||
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let value = data["ton_topup_url"] as? String {
|
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let value = data["ton_topup_url"] as? String {
|
||||||
fragmentUrl = value
|
fragmentUrl = value
|
||||||
@ -1463,9 +1464,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
navigationController: controller.navigationController as? NavigationController,
|
navigationController: controller.navigationController as? NavigationController,
|
||||||
commit: { currency in
|
commit: { currency in
|
||||||
action(currency)
|
action(currency)
|
||||||
|
},
|
||||||
|
dismissed: { [weak controller] in
|
||||||
|
if let balanceView = controller?.balanceOverlay.view {
|
||||||
|
balanceView.isHidden = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
controller.present(alertController, in: .window(.root))
|
controller.present(alertController, in: .window(.root))
|
||||||
|
|
||||||
|
if let balanceView = controller.balanceOverlay.view {
|
||||||
|
balanceView.isHidden = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -3835,7 +3845,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
}
|
}
|
||||||
fileprivate var balanceCurrency: CurrencyAmount.Currency
|
fileprivate var balanceCurrency: CurrencyAmount.Currency
|
||||||
|
|
||||||
private let balanceOverlay = ComponentView<Empty>()
|
fileprivate let balanceOverlay = ComponentView<Empty>()
|
||||||
|
|
||||||
fileprivate let updateSavedToProfile: ((StarGiftReference, Bool) -> Void)?
|
fileprivate let updateSavedToProfile: ((StarGiftReference, Bool) -> Void)?
|
||||||
fileprivate let convertToStars: (() -> Void)?
|
fileprivate let convertToStars: (() -> Void)?
|
||||||
@ -4007,8 +4017,8 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
guard let self, let starsContext = context.starsContext, let navigationController = self.navigationController as? NavigationController else {
|
guard let self, let starsContext = context.starsContext, let navigationController = self.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.dismissAnimated()
|
switch self.balanceCurrency {
|
||||||
|
case .stars:
|
||||||
let _ = (context.engine.payments.starsTopUpOptions()
|
let _ = (context.engine.payments.starsTopUpOptions()
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).startStandalone(next: { options in
|
|> deliverOnMainQueue).startStandalone(next: { options in
|
||||||
@ -4021,6 +4031,14 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
)
|
)
|
||||||
navigationController.pushViewController(controller)
|
navigationController.pushViewController(controller)
|
||||||
})
|
})
|
||||||
|
case .ton:
|
||||||
|
var fragmentUrl = "https://fragment.com/ads/topup"
|
||||||
|
if let data = context.currentAppConfiguration.with({ $0 }).data, let value = data["ton_topup_url"] as? String {
|
||||||
|
fragmentUrl = value
|
||||||
|
}
|
||||||
|
context.sharedContext.applicationBindings.openUrl(fragmentUrl)
|
||||||
|
}
|
||||||
|
self.dismissAnimated()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
@ -16,6 +16,7 @@ swift_library(
|
|||||||
"//submodules/SSignalKit/SwiftSignalKit",
|
"//submodules/SSignalKit/SwiftSignalKit",
|
||||||
"//submodules/AccountContext",
|
"//submodules/AccountContext",
|
||||||
"//submodules/ComponentFlow",
|
"//submodules/ComponentFlow",
|
||||||
|
"//submodules/Components/ComponentDisplayAdapters",
|
||||||
"//submodules/Components/MultilineTextComponent",
|
"//submodules/Components/MultilineTextComponent",
|
||||||
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||||
"//submodules/TelegramPresentationData",
|
"//submodules/TelegramPresentationData",
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
import Display
|
import Display
|
||||||
import ComponentFlow
|
import ComponentFlow
|
||||||
|
import ComponentDisplayAdapters
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import AccountContext
|
import AccountContext
|
||||||
@ -172,7 +173,13 @@ public final class StarsBalanceOverlayComponent: Component {
|
|||||||
|
|
||||||
if previousComponent?.currency != component.currency {
|
if previousComponent?.currency != component.currency {
|
||||||
if let textView = self.text.view {
|
if let textView = self.text.view {
|
||||||
|
if !transition.animation.isImmediate {
|
||||||
|
transition.setAlpha(view: textView, alpha: 0.0, completion: { _ in
|
||||||
textView.removeFromSuperview()
|
textView.removeFromSuperview()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
textView.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.text = ComponentView()
|
self.text = ComponentView()
|
||||||
}
|
}
|
||||||
@ -185,7 +192,8 @@ public final class StarsBalanceOverlayComponent: Component {
|
|||||||
animationCache: component.context.animationCache,
|
animationCache: component.context.animationCache,
|
||||||
animationRenderer: component.context.animationRenderer,
|
animationRenderer: component.context.animationRenderer,
|
||||||
placeholderColor: .white,
|
placeholderColor: .white,
|
||||||
text: .plain(attributedText)
|
text: .plain(attributedText),
|
||||||
|
displaysAsynchronously: false
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
environment: {},
|
environment: {},
|
||||||
@ -219,7 +227,12 @@ public final class StarsBalanceOverlayComponent: Component {
|
|||||||
|
|
||||||
if let actionView = self.action.view {
|
if let actionView = self.action.view {
|
||||||
if actionView.superview == nil {
|
if actionView.superview == nil {
|
||||||
|
actionView.alpha = 1.0
|
||||||
self.backgroundView.addSubview(actionView)
|
self.backgroundView.addSubview(actionView)
|
||||||
|
|
||||||
|
if !transition.animation.isImmediate {
|
||||||
|
transition.animateAlpha(view: actionView, from: 0.0, to: 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
actionView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - actionSize.width) / 2.0), y: 29.0), size: actionSize)
|
actionView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - actionSize.width) / 2.0), y: 29.0), size: actionSize)
|
||||||
}
|
}
|
||||||
@ -227,19 +240,30 @@ public final class StarsBalanceOverlayComponent: Component {
|
|||||||
size = CGSize(width: textSize.width + 40.0, height: 35.0)
|
size = CGSize(width: textSize.width + 40.0, height: 35.0)
|
||||||
|
|
||||||
if let actionView = self.action.view, actionView.superview != nil {
|
if let actionView = self.action.view, actionView.superview != nil {
|
||||||
|
if !transition.animation.isImmediate {
|
||||||
|
transition.setAlpha(view: actionView, alpha: 0.0, completion: { _ in
|
||||||
actionView.removeFromSuperview()
|
actionView.removeFromSuperview()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
actionView.removeFromSuperview()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let textView = self.text.view {
|
if let textView = self.text.view {
|
||||||
if textView.superview == nil {
|
if textView.superview == nil {
|
||||||
|
textView.alpha = 1.0
|
||||||
self.backgroundView.addSubview(textView)
|
self.backgroundView.addSubview(textView)
|
||||||
|
|
||||||
|
if !transition.animation.isImmediate {
|
||||||
|
transition.animateAlpha(view: textView, from: 0.0, to: 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
textView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: 10.0), size: textSize)
|
textView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: 10.0), size: textSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.backgroundView.updateColor(color: component.theme.rootController.navigationBar.opaqueBackgroundColor, transition: .immediate)
|
self.backgroundView.updateColor(color: component.theme.rootController.navigationBar.opaqueBackgroundColor, transition: .immediate)
|
||||||
self.backgroundView.update(size: size, cornerRadius: size.height / 2.0, transition: .immediate)
|
self.backgroundView.update(size: size, cornerRadius: size.height / 2.0, transition: transition.containedViewLayoutTransition)
|
||||||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - size.width) / 2.0), y: 0.0), size: size))
|
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - size.width) / 2.0), y: 0.0), size: size))
|
||||||
|
|
||||||
return CGSize(width: availableSize.width, height: size.height)
|
return CGSize(width: availableSize.width, height: size.height)
|
||||||
|
|||||||
@ -842,7 +842,8 @@ private final class ItemComponent: CombinedComponent {
|
|||||||
animationCache: component.context?.animationCache,
|
animationCache: component.context?.animationCache,
|
||||||
animationRenderer: component.context?.animationRenderer,
|
animationRenderer: component.context?.animationRenderer,
|
||||||
placeholderColor: .white,
|
placeholderColor: .white,
|
||||||
text: .plain(attributedTitle)
|
text: .plain(attributedTitle),
|
||||||
|
displaysAsynchronously: false
|
||||||
),
|
),
|
||||||
availableSize: context.availableSize,
|
availableSize: context.availableSize,
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
@ -864,7 +865,8 @@ private final class ItemComponent: CombinedComponent {
|
|||||||
animationCache: nil,
|
animationCache: nil,
|
||||||
animationRenderer: nil,
|
animationRenderer: nil,
|
||||||
placeholderColor: .white,
|
placeholderColor: .white,
|
||||||
text: .plain(selectedAttributedTitle)
|
text: .plain(selectedAttributedTitle),
|
||||||
|
displaysAsynchronously: false
|
||||||
),
|
),
|
||||||
availableSize: context.availableSize,
|
availableSize: context.availableSize,
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user