Merge commit '17140bf9616ce2aca148d07c36b72577012aa3ab'

This commit is contained in:
Isaac 2025-07-28 11:55:59 +02:00
commit 200b86a384
9 changed files with 186 additions and 66 deletions

View File

@ -34,6 +34,7 @@ public final class MultilineTextWithEntitiesComponent: Component {
public let handleSpoilers: Bool
public let manualVisibilityControl: Bool
public let resetAnimationsOnVisibilityChange: Bool
public let displaysAsynchronously: Bool
public let highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)?
public let tapAction: (([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,
manualVisibilityControl: Bool = false,
resetAnimationsOnVisibilityChange: Bool = false,
displaysAsynchronously: Bool = true,
highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? = nil,
tapAction: (([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.manualVisibilityControl = manualVisibilityControl
self.resetAnimationsOnVisibilityChange = resetAnimationsOnVisibilityChange
self.displaysAsynchronously = displaysAsynchronously
self.tapAction = tapAction
self.longTapAction = longTapAction
}
@ -120,6 +123,9 @@ public final class MultilineTextWithEntitiesComponent: Component {
if lhs.resetAnimationsOnVisibilityChange != rhs.resetAnimationsOnVisibilityChange {
return false
}
if lhs.displaysAsynchronously != rhs.displaysAsynchronously {
return false
}
if let lhsTextShadowColor = lhs.textShadowColor, let rhsTextShadowColor = rhs.textShadowColor {
if !lhsTextShadowColor.isEqual(rhsTextShadowColor) {
return false
@ -161,6 +167,7 @@ public final class MultilineTextWithEntitiesComponent: Component {
public override init(frame: CGRect) {
self.textNode = ImmediateTextNodeWithEntities()
super.init(frame: frame)
self.addSubview(self.textNode.view)
@ -175,6 +182,8 @@ public final class MultilineTextWithEntitiesComponent: Component {
}
public func update(component: MultilineTextWithEntitiesComponent, availableSize: CGSize, transition: ComponentTransition) -> CGSize {
self.textNode.displaysAsynchronously = component.displaysAsynchronously
let attributedString: NSAttributedString
switch component.text {
case let .plain(string):

View File

@ -618,7 +618,7 @@ private func autosaveLabelAndValue(presentationData: PresentationData, settings:
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] = []
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(.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(.sensitiveContentInfo(presentationData.strings.Settings_SensitiveContentInfo))
}
@ -685,6 +685,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
var pushControllerImpl: ((ViewController) -> Void)?
var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)?
var presentAgeVerificationImpl: ((@escaping () -> Void) -> Void)?
let actionsDisposable = DisposableSet()
@ -914,14 +915,18 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
}
if value {
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: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
TextAlertAction(type: .defaultAction, title: presentationData.strings.SensitiveContent_Enable_Confirm, action: {
update()
})
])
presentControllerImpl?(alertController, nil)
if requireAgeVerification(context: context) {
presentAgeVerificationImpl?(update)
} else {
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: [
TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}),
TextAlertAction(type: .defaultAction, title: presentationData.strings.SensitiveContent_Enable_Confirm, action: {
update()
})
])
presentControllerImpl?(alertController, nil)
}
} else {
update()
}
@ -983,7 +988,7 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
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 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))
} |> afterDisposed {
@ -999,6 +1004,14 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
presentControllerImpl = { [weak controller] c, a in
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
}

View File

@ -4,6 +4,7 @@ import SwiftSignalKit
import AsyncDisplayKit
import Display
import ComponentFlow
import ComponentDisplayAdapters
import Postbox
import TelegramCore
import TelegramPresentationData
@ -323,28 +324,41 @@ public class ChatMessagePaymentAlertController: AlertController {
private weak var parentNavigationController: NavigationController?
private let chatPeerId: EnginePeer.Id
private let showBalance: Bool
private let animateBalanceOverlay: Bool
private var didUpdateCurrency = false
public var currency: CurrencyAmount.Currency {
didSet {
self.didUpdateCurrency = true
if let layout = self.validLayout {
self.containerLayoutUpdated(layout, transition: .immediate)
self.containerLayoutUpdated(layout, transition: .animated(duration: 0.25, curve: .easeInOut))
}
}
}
private let balance = ComponentView<Empty>()
private var didAppear = false
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.presentationData = presentationData
self.parentNavigationController = navigationController
self.chatPeerId = chatPeerId
self.showBalance = showBalance
self.currency = currency
self.animateBalanceOverlay = animateBalanceOverlay
super.init(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
@ -361,9 +375,18 @@ public class ChatMessagePaymentAlertController: AlertController {
}
private func animateOut() {
if let view = self.balance.view {
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)
if !self.animateBalanceOverlay {
if self.currency == .ton && self.didUpdateCurrency {
self.currency = .stars
}
Queue.mainQueue().after(0.39, {
})
} else {
if let view = self.balance.view {
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)
}
}
}
@ -389,8 +412,13 @@ public class ChatMessagePaymentAlertController: AlertController {
if let context = self.context, let _ = self.parentNavigationController, self.showBalance {
let insets = layout.insets(options: .statusBar)
var balanceTransition = ComponentTransition(transition)
if self.balance.view == nil {
balanceTransition = .immediate
}
let balanceSize = self.balance.update(
transition: .immediate,
transition: balanceTransition,
component: AnyComponent(
StarsBalanceOverlayComponent(
context: context,
@ -401,20 +429,28 @@ public class ChatMessagePaymentAlertController: AlertController {
guard let self, let starsContext = context.starsContext, let navigationController = self.parentNavigationController else {
return
}
switch self.currency {
case .stars:
let _ = (context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { options in
let controller = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options,
purpose: .generic,
completion: { _ in }
)
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()
let _ = (context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { options in
let controller = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options,
purpose: .generic,
completion: { _ in }
)
navigationController.pushViewController(controller)
})
}
)
),
@ -425,11 +461,13 @@ public class ChatMessagePaymentAlertController: AlertController {
if view.superview == nil {
self.view.addSubview(view)
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.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
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.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.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))
}
}
}

View File

@ -162,9 +162,11 @@ final class GiftStoreScreenComponent: Component {
}
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
}
//, self.state?.starGiftsState?.dataState != .loading
let availableWidth = self.scrollView.bounds.width
let availableHeight = self.scrollView.bounds.height
@ -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)
if interactive, bottomContentOffset < 1000.0 {
if interactive, bottomContentOffset < 800.0 {
self.state?.starGiftsContext.loadMore()
}
}
@ -1142,7 +1144,7 @@ final class GiftStoreScreenComponent: Component {
context: component.context,
colors: FilterSelectorComponent.Colors(
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,
selectedItemId: self.selectedFilterId

View File

@ -446,7 +446,8 @@ public func giftPurchaseAlertController(
gift: StarGift.UniqueGift,
peer: EnginePeer,
navigationController: NavigationController?,
commit: @escaping (CurrencyAmount.Currency) -> Void
commit: @escaping (CurrencyAmount.Currency) -> Void,
dismissed: @escaping () -> Void
) -> AlertController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
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)
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
if animated {

View File

@ -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 {
self.inProgress = true
self.updated()
@ -1384,7 +1385,7 @@ private final class GiftViewSheetContent: CombinedComponent {
context: context,
starsContext: starsContext,
options: options ?? [],
purpose: .buyStarGift(requiredStars: price),
purpose: .buyStarGift(requiredStars: resellAmount.amount.value),
completion: { [weak self, weak starsContext] stars in
guard let self, let starsContext else {
return
@ -1402,7 +1403,7 @@ private final class GiftViewSheetContent: CombinedComponent {
guard let self, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
return
}
if starsState.balance < StarsAmount(value: price, nanos: 0) {
if starsState.balance < resellAmount.amount {
self.inProgress = false
self.updated()
@ -1416,11 +1417,11 @@ private final class GiftViewSheetContent: CombinedComponent {
)
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 {
return
}
let needed = StarsAmount(value: price, nanos: 0) - tonState.balance
let needed = resellAmount.amount - tonState.balance
var fragmentUrl = "https://fragment.com/ads/topup"
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let value = data["ton_topup_url"] as? String {
fragmentUrl = value
@ -1463,9 +1464,18 @@ private final class GiftViewSheetContent: CombinedComponent {
navigationController: controller.navigationController as? NavigationController,
commit: { currency in
action(currency)
},
dismissed: { [weak controller] in
if let balanceView = controller?.balanceOverlay.view {
balanceView.isHidden = false
}
}
)
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
private let balanceOverlay = ComponentView<Empty>()
fileprivate let balanceOverlay = ComponentView<Empty>()
fileprivate let updateSavedToProfile: ((StarGiftReference, Bool) -> Void)?
fileprivate let convertToStars: (() -> Void)?
@ -4007,20 +4017,28 @@ public class GiftViewScreen: ViewControllerComponentContainer {
guard let self, let starsContext = context.starsContext, let navigationController = self.navigationController as? NavigationController else {
return
}
switch self.balanceCurrency {
case .stars:
let _ = (context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { options in
let controller = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options,
purpose: .generic,
completion: { _ in }
)
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()
let _ = (context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { options in
let controller = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options,
purpose: .generic,
completion: { _ in }
)
navigationController.pushViewController(controller)
})
}
)
),

View File

@ -16,6 +16,7 @@ swift_library(
"//submodules/SSignalKit/SwiftSignalKit",
"//submodules/AccountContext",
"//submodules/ComponentFlow",
"//submodules/Components/ComponentDisplayAdapters",
"//submodules/Components/MultilineTextComponent",
"//submodules/Components/MultilineTextWithEntitiesComponent",
"//submodules/TelegramPresentationData",

View File

@ -2,6 +2,7 @@ import Foundation
import UIKit
import Display
import ComponentFlow
import ComponentDisplayAdapters
import SwiftSignalKit
import TelegramCore
import AccountContext
@ -172,7 +173,13 @@ public final class StarsBalanceOverlayComponent: Component {
if previousComponent?.currency != component.currency {
if let textView = self.text.view {
textView.removeFromSuperview()
if !transition.animation.isImmediate {
transition.setAlpha(view: textView, alpha: 0.0, completion: { _ in
textView.removeFromSuperview()
})
} else {
textView.removeFromSuperview()
}
}
self.text = ComponentView()
}
@ -185,7 +192,8 @@ public final class StarsBalanceOverlayComponent: Component {
animationCache: component.context.animationCache,
animationRenderer: component.context.animationRenderer,
placeholderColor: .white,
text: .plain(attributedText)
text: .plain(attributedText),
displaysAsynchronously: false
)
),
environment: {},
@ -219,7 +227,12 @@ public final class StarsBalanceOverlayComponent: Component {
if let actionView = self.action.view {
if actionView.superview == nil {
actionView.alpha = 1.0
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)
}
@ -227,19 +240,30 @@ public final class StarsBalanceOverlayComponent: Component {
size = CGSize(width: textSize.width + 40.0, height: 35.0)
if let actionView = self.action.view, actionView.superview != nil {
actionView.removeFromSuperview()
if !transition.animation.isImmediate {
transition.setAlpha(view: actionView, alpha: 0.0, completion: { _ in
actionView.removeFromSuperview()
})
} else {
actionView.removeFromSuperview()
}
}
}
if let textView = self.text.view {
if textView.superview == nil {
textView.alpha = 1.0
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)
}
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))
return CGSize(width: availableSize.width, height: size.height)

View File

@ -842,7 +842,8 @@ private final class ItemComponent: CombinedComponent {
animationCache: component.context?.animationCache,
animationRenderer: component.context?.animationRenderer,
placeholderColor: .white,
text: .plain(attributedTitle)
text: .plain(attributedTitle),
displaysAsynchronously: false
),
availableSize: context.availableSize,
transition: .immediate
@ -864,7 +865,8 @@ private final class ItemComponent: CombinedComponent {
animationCache: nil,
animationRenderer: nil,
placeholderColor: .white,
text: .plain(selectedAttributedTitle)
text: .plain(selectedAttributedTitle),
displaysAsynchronously: false
),
availableSize: context.availableSize,
transition: .immediate