Improved pinned gift replace panel

This commit is contained in:
Ilya Laktyushin 2025-03-27 15:13:08 +04:00
parent b19e056a37
commit 19e37d149b
7 changed files with 131 additions and 87 deletions

View File

@ -14094,6 +14094,7 @@ Sorry for the inconvenience.";
"Gift.Unpin.Title" = "Too Manu Pinned Gifts"; "Gift.Unpin.Title" = "Too Manu Pinned Gifts";
"Gift.Unpin.Subtitle" = "Select a gift to unpin below:"; "Gift.Unpin.Subtitle" = "Select a gift to unpin below:";
"Gift.Unpin.Unpin" = "Unpin"; "Gift.Unpin.Unpin" = "Unpin";
"Gift.Unpin.Replace" = "Replace";
"ChatList.Search.Ad" = "Ad"; "ChatList.Search.Ad" = "Ad";

View File

@ -180,6 +180,7 @@ public final class _UpdatedChildComponent {
var _opacity: CGFloat? var _opacity: CGFloat?
var _cornerRadius: CGFloat? var _cornerRadius: CGFloat?
var _clipsToBounds: Bool? var _clipsToBounds: Bool?
var _allowsGroupOpacity: Bool?
var _shadow: Shadow? var _shadow: Shadow?
fileprivate var transitionAppear: ComponentTransition.Appear? fileprivate var transitionAppear: ComponentTransition.Appear?
@ -262,6 +263,11 @@ public final class _UpdatedChildComponent {
return self return self
} }
@discardableResult public func allowsGroupOpacity(_ allowsGroupOpacity: Bool) -> _UpdatedChildComponent {
self._allowsGroupOpacity = allowsGroupOpacity
return self
}
@discardableResult public func shadow(_ shadow: Shadow?) -> _UpdatedChildComponent { @discardableResult public func shadow(_ shadow: Shadow?) -> _UpdatedChildComponent {
self._shadow = shadow self._shadow = shadow
return self return self
@ -712,6 +718,9 @@ public extension CombinedComponent {
updatedChild.view.alpha = updatedChild._opacity ?? 1.0 updatedChild.view.alpha = updatedChild._opacity ?? 1.0
updatedChild.view.clipsToBounds = updatedChild._clipsToBounds ?? false updatedChild.view.clipsToBounds = updatedChild._clipsToBounds ?? false
updatedChild.view.layer.cornerRadius = updatedChild._cornerRadius ?? 0.0 updatedChild.view.layer.cornerRadius = updatedChild._cornerRadius ?? 0.0
if let allowsGroupOpacity = updatedChild._allowsGroupOpacity {
updatedChild.view.layer.allowsGroupOpacity = allowsGroupOpacity
}
if let shadow = updatedChild._shadow { if let shadow = updatedChild._shadow {
updatedChild.view.layer.shadowColor = shadow.color.withAlphaComponent(1.0).cgColor updatedChild.view.layer.shadowColor = shadow.color.withAlphaComponent(1.0).cgColor
updatedChild.view.layer.shadowRadius = shadow.radius updatedChild.view.layer.shadowRadius = shadow.radius

View File

@ -490,9 +490,9 @@ public struct ComponentTransition {
self.setScaleWithSpring(layer: view.layer, scale: scale, delay: delay, completion: completion) self.setScaleWithSpring(layer: view.layer, scale: scale, delay: delay, completion: completion)
} }
public func setScale(layer: CALayer, scale: CGFloat, delay: Double = 0.0, completion: ((Bool) -> Void)? = nil) { public func setScale(layer: CALayer, scale: CGFloat, delay: Double = 0.0, beginWithCurrentState: Bool = false, completion: ((Bool) -> Void)? = nil) {
let currentTransform: CATransform3D let currentTransform: CATransform3D
if layer.animation(forKey: "transform") != nil || layer.animation(forKey: "transform.scale") != nil { if beginWithCurrentState, layer.animation(forKey: "transform") != nil || layer.animation(forKey: "transform.scale") != nil {
currentTransform = layer.presentation()?.transform ?? layer.transform currentTransform = layer.presentation()?.transform ?? layer.transform
} else { } else {
currentTransform = layer.transform currentTransform = layer.transform

View File

@ -235,6 +235,8 @@ public final class GiftItemComponent: Component {
private var animationLayer: InlineStickerItemLayer? private var animationLayer: InlineStickerItemLayer?
private var selectionLayer: SimpleShapeLayer? private var selectionLayer: SimpleShapeLayer?
private var animationFile: TelegramMediaFile?
private var disposables = DisposableSet() private var disposables = DisposableSet()
private var fetchedFiles = Set<Int64>() private var fetchedFiles = Set<Int64>()
@ -280,7 +282,7 @@ public final class GiftItemComponent: Component {
let previousComponent = self.component let previousComponent = self.component
self.component = component self.component = component
self.componentState = state self.componentState = state
self.isGestureEnabled = component.contextAction != nil self.isGestureEnabled = component.contextAction != nil
var themeUpdated = false var themeUpdated = false
@ -317,6 +319,10 @@ public final class GiftItemComponent: Component {
iconSize = CGSize(width: floor(size.width * 0.6), height: floor(size.width * 0.6)) iconSize = CGSize(width: floor(size.width * 0.6), height: floor(size.width * 0.6))
cornerRadius = 4.0 cornerRadius = 4.0
} }
var backgroundSize = size
if case .grid = component.mode {
backgroundSize = CGSize(width: backgroundSize.width - 4.0, height: backgroundSize.height - 4.0)
}
self.backgroundLayer.cornerRadius = cornerRadius self.backgroundLayer.cornerRadius = cornerRadius
@ -413,7 +419,14 @@ public final class GiftItemComponent: Component {
} }
} }
if self.animationLayer == nil, let emoji { var animationTransition = transition
if self.animationFile != animationFile, let emoji {
animationTransition = .immediate
self.animationFile = animationFile
if let animationLayer = self.animationLayer {
self.animationLayer = nil
animationLayer.removeFromSuperlayer()
}
let animationLayer = InlineStickerItemLayer( let animationLayer = InlineStickerItemLayer(
context: .account(component.context), context: .account(component.context),
userLocation: .other, userLocation: .other,
@ -434,7 +447,7 @@ public final class GiftItemComponent: Component {
let animationFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - iconSize.width) / 2.0), y: component.mode == .generic ? animationOffset : floorToScreenPixels((size.height - iconSize.height) / 2.0)), size: iconSize) let animationFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - iconSize.width) / 2.0), y: component.mode == .generic ? animationOffset : floorToScreenPixels((size.height - iconSize.height) / 2.0)), size: iconSize)
if let animationLayer = self.animationLayer { if let animationLayer = self.animationLayer {
transition.setFrame(layer: animationLayer, frame: animationFrame) animationTransition.setFrame(layer: animationLayer, frame: animationFrame)
} }
if let backgroundColor { if let backgroundColor {
@ -445,14 +458,14 @@ public final class GiftItemComponent: Component {
subject: .custom(backgroundColor, secondBackgroundColor, patternColor, patternFile?.fileId.id), subject: .custom(backgroundColor, secondBackgroundColor, patternColor, patternFile?.fileId.id),
files: files, files: files,
isDark: false, isDark: false,
avatarCenter: CGPoint(x: size.width / 2.0, y: animationFrame.midY), avatarCenter: CGPoint(x: backgroundSize.width / 2.0, y: animationFrame.midY),
avatarScale: 1.0, avatarScale: 1.0,
defaultHeight: size.height, defaultHeight: backgroundSize.height,
avatarTransitionFraction: 0.0, avatarTransitionFraction: 0.0,
patternTransitionFraction: 0.0 patternTransitionFraction: 0.0
)), )),
environment: {}, environment: {},
containerSize: availableSize containerSize: backgroundSize
) )
if let backgroundView = self.patternView.view { if let backgroundView = self.patternView.view {
if backgroundView.superview == nil { if backgroundView.superview == nil {
@ -463,7 +476,7 @@ public final class GiftItemComponent: Component {
backgroundView.clipsToBounds = true backgroundView.clipsToBounds = true
self.insertSubview(backgroundView, at: 1) self.insertSubview(backgroundView, at: 1)
} }
backgroundView.frame = CGRect(origin: .zero, size: size) backgroundView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize)
} }
} }
@ -634,11 +647,17 @@ public final class GiftItemComponent: Component {
} }
self.ribbon.image = generateGradientTintedImage(image: UIImage(bundleImageName: "Premium/GiftRibbon"), colors: ribbon.color.colors(theme: component.theme), direction: direction) self.ribbon.image = generateGradientTintedImage(image: UIImage(bundleImageName: "Premium/GiftRibbon"), colors: ribbon.color.colors(theme: component.theme), direction: direction)
} }
var ribbonOffset: CGPoint = CGPoint(x: 2.0, y: -2.0)
if case .grid = component.mode {
ribbonOffset = .zero
}
if let ribbonImage = self.ribbon.image { if let ribbonImage = self.ribbon.image {
self.ribbon.frame = CGRect(origin: CGPoint(x: size.width - ribbonImage.size.width + 2.0, y: -2.0), size: ribbonImage.size) self.ribbon.frame = CGRect(origin: CGPoint(x: size.width - ribbonImage.size.width + ribbonOffset.x, y: ribbonOffset.y), size: ribbonImage.size)
} }
ribbonTextView.transform = CGAffineTransform(rotationAngle: .pi / 4.0) ribbonTextView.transform = CGAffineTransform(rotationAngle: .pi / 4.0)
ribbonTextView.center = CGPoint(x: size.width - 20.0, y: 20.0) ribbonTextView.center = CGPoint(x: size.width - 22.0 + ribbonOffset.x, y: 22.0 + ribbonOffset.y)
} }
} else { } else {
if self.ribbonText.view?.superview != nil { if self.ribbonText.view?.superview != nil {
@ -676,7 +695,8 @@ public final class GiftItemComponent: Component {
self.backgroundLayer.backgroundColor = component.theme.list.itemBlocksBackgroundColor.cgColor self.backgroundLayer.backgroundColor = component.theme.list.itemBlocksBackgroundColor.cgColor
} }
transition.setFrame(layer: self.backgroundLayer, frame: CGRect(origin: .zero, size: size)) let backgroundFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - backgroundSize.width) / 2.0), y: floorToScreenPixels((size.height - backgroundSize.height) / 2.0)), size: backgroundSize)
transition.setFrame(layer: self.backgroundLayer, frame: backgroundFrame)
transition.setFrame(view: self.containerButton, frame: CGRect(origin: .zero, size: size)) transition.setFrame(view: self.containerButton, frame: CGRect(origin: .zero, size: size))
var iconBackgroundSize: CGSize? var iconBackgroundSize: CGSize?
@ -785,7 +805,7 @@ public final class GiftItemComponent: Component {
if case .grid = component.mode { if case .grid = component.mode {
let lineWidth: CGFloat = 2.0 let lineWidth: CGFloat = 2.0
let selectionFrame = CGRect(origin: .zero, size: size).insetBy(dx: 3.0, dy: 3.0) let selectionFrame = backgroundFrame.insetBy(dx: 3.0, dy: 3.0)
if component.isSelected { if component.isSelected {
let selectionLayer: SimpleShapeLayer let selectionLayer: SimpleShapeLayer

View File

@ -21,18 +21,21 @@ private final class SheetContent: CombinedComponent {
typealias EnvironmentType = ViewControllerComponentContainer.Environment typealias EnvironmentType = ViewControllerComponentContainer.Environment
let context: AccountContext let context: AccountContext
let gifts: [ProfileGiftsContext.State.StarGift] let gift: ProfileGiftsContext.State.StarGift
let pinnedGifts: [ProfileGiftsContext.State.StarGift]
let completion: (StarGiftReference) -> Void let completion: (StarGiftReference) -> Void
let dismiss: () -> Void let dismiss: () -> Void
init( init(
context: AccountContext, context: AccountContext,
gifts: [ProfileGiftsContext.State.StarGift], gift: ProfileGiftsContext.State.StarGift,
pinnedGifts: [ProfileGiftsContext.State.StarGift],
completion: @escaping (StarGiftReference) -> Void, completion: @escaping (StarGiftReference) -> Void,
dismiss: @escaping () -> Void dismiss: @escaping () -> Void
) { ) {
self.context = context self.context = context
self.gifts = gifts self.gift = gift
self.pinnedGifts = pinnedGifts
self.completion = completion self.completion = completion
self.dismiss = dismiss self.dismiss = dismiss
} }
@ -41,7 +44,10 @@ private final class SheetContent: CombinedComponent {
if lhs.context !== rhs.context { if lhs.context !== rhs.context {
return false return false
} }
if lhs.gifts != rhs.gifts { if lhs.gift != rhs.gift {
return false
}
if lhs.pinnedGifts != rhs.pinnedGifts {
return false return false
} }
return true return true
@ -62,6 +68,8 @@ private final class SheetContent: CombinedComponent {
let text = Child(BalancedTextComponent.self) let text = Child(BalancedTextComponent.self)
let gifts = ChildMap(environment: Empty.self, keyedBy: AnyHashable.self) let gifts = ChildMap(environment: Empty.self, keyedBy: AnyHashable.self)
let button = Child(ButtonComponent.self) let button = Child(ButtonComponent.self)
var appliedSelectedGift: StarGiftReference?
return { context in return { context in
let environment = context.environment[EnvironmentType.self] let environment = context.environment[EnvironmentType.self]
@ -134,18 +142,30 @@ private final class SheetContent: CombinedComponent {
var updatedGifts: [_UpdatedChildComponent] = [] var updatedGifts: [_UpdatedChildComponent] = []
var index = 0 var index = 0
var nextOriginX = itemsSideInset var nextOriginX = itemsSideInset
for gift in component.gifts { for gift in component.pinnedGifts {
guard case let .unique(uniqueGift) = gift.gift else { guard case let .unique(uniqueGift) = gift.gift else {
continue continue
} }
var alpha: CGFloat = 1.0
var displayGift = uniqueGift
if let selectedGift = state.selectedGift {
alpha = selectedGift == gift.reference ? 1.0 : 0.5
if selectedGift == gift.reference {
if case let .unique(uniqueGift) = component.gift.gift {
displayGift = uniqueGift
}
}
}
var ribbonColor: GiftItemComponent.Ribbon.Color = .blue var ribbonColor: GiftItemComponent.Ribbon.Color = .blue
for attribute in uniqueGift.attributes { for attribute in displayGift.attributes {
if case let .backdrop(_, innerColor, outerColor, _, _, _) = attribute { if case let .backdrop(_, innerColor, outerColor, _, _, _) = attribute {
ribbonColor = .custom(outerColor, innerColor) ribbonColor = .custom(outerColor, innerColor)
break break
} }
} }
let inset: CGFloat = 2.0
updatedGifts.append( updatedGifts.append(
gifts[index].update( gifts[index].update(
component: AnyComponent( component: AnyComponent(
@ -155,9 +175,8 @@ private final class SheetContent: CombinedComponent {
context: component.context, context: component.context,
theme: theme, theme: theme,
strings: strings, strings: strings,
subject: .uniqueGift(gift: uniqueGift), subject: .uniqueGift(gift: displayGift),
ribbon: GiftItemComponent.Ribbon(text: "#\(uniqueGift.number)", font: .monospaced, color: ribbonColor), ribbon: GiftItemComponent.Ribbon(text: "#\(displayGift.number)", font: .monospaced, color: ribbonColor),
isSelected: state.selectedGift == gift.reference,
mode: .grid mode: .grid
) )
), ),
@ -166,23 +185,45 @@ private final class SheetContent: CombinedComponent {
guard let state else { guard let state else {
return return
} }
state.selectedGift = gift.reference if state.selectedGift == gift.reference {
state.selectedGift = nil
} else {
state.selectedGift = gift.reference
}
state.updated(transition: .spring(duration: 0.3)) state.updated(transition: .spring(duration: 0.3))
}, },
animateAlpha: false animateAlpha: false
) )
), ),
availableSize: CGSize(width: width, height: width), availableSize: CGSize(width: width + inset * 2.0, height: width + inset * 2.0),
transition: context.transition transition: context.transition
) )
) )
context.add(updatedGifts[index]
.position(CGPoint(x: nextOriginX + updatedGifts[index].size.width / 2.0, y: contentSize.height + updatedGifts[index].size.height / 2.0))
)
nextOriginX += updatedGifts[index].size.width + spacing var updatedGift = updatedGifts[index]
.position(CGPoint(x: nextOriginX + updatedGifts[index].size.width / 2.0 - inset, y: contentSize.height + updatedGifts[index].size.height / 2.0 - inset))
.allowsGroupOpacity(true)
.opacity(alpha)
if gift.reference == state.selectedGift && appliedSelectedGift != gift.reference {
updatedGift = updatedGift.update(ComponentTransition.Update({ _, view, transition in
UIView.transition(with: view, duration: 0.3, options: [.transitionFlipFromLeft, .curveEaseOut], animations: {
view.alpha = alpha
})
}))
} else if let appliedSelectedGift, appliedSelectedGift == gift.reference && gift.reference != state.selectedGift {
updatedGift = updatedGift.update(ComponentTransition.Update({ _, view, transition in
UIView.transition(with: view, duration: 0.3, options: [.transitionFlipFromRight, .curveEaseOut], animations: {
view.alpha = alpha
})
}))
}
context.add(updatedGift)
nextOriginX += updatedGifts[index].size.width - inset * 2.0 + spacing
if nextOriginX > context.availableSize.width - itemsSideInset { if nextOriginX > context.availableSize.width - itemsSideInset {
contentSize.height += updatedGifts[index].size.height + spacing contentSize.height += updatedGifts[index].size.height - inset * 2.0 + spacing
nextOriginX = itemsSideInset nextOriginX = itemsSideInset
} }
@ -190,42 +231,6 @@ private final class SheetContent: CombinedComponent {
} }
contentSize.height += 14.0 contentSize.height += 14.0
var giftTitle: String?
if let selectedGift = state.selectedGift, let gift = component.gifts.first(where: { $0.reference == selectedGift }) {
if case let .unique(uniqueGift) = gift.gift {
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
giftTitle = "\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, presentationData.dateTimeFormat.groupingSeparator))"
}
}
let buttonContent: AnyComponentWithIdentity<Empty>
if let giftTitle {
buttonContent = AnyComponentWithIdentity(
id: AnyHashable("unpinGift"),
component: AnyComponent(
VStack([
AnyComponentWithIdentity(
id: AnyHashable("unpin"),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Unpin_Unpin, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
),
AnyComponentWithIdentity(
id: AnyHashable(giftTitle),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: giftTitle, font: Font.regular(13.0), textColor: theme.list.itemCheckColors.foregroundColor.withAlphaComponent(0.7), paragraphAlignment: .center))))
)
], spacing: 0.0)
)
)
} else {
buttonContent = AnyComponentWithIdentity(
id: AnyHashable("unpin"),
component: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Unpin_Unpin, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)))
)
)
}
let button = button.update( let button = button.update(
component: ButtonComponent( component: ButtonComponent(
background: ButtonComponent.Background( background: ButtonComponent.Background(
@ -233,7 +238,12 @@ private final class SheetContent: CombinedComponent {
foreground: theme.list.itemCheckColors.foregroundColor, foreground: theme.list.itemCheckColors.foregroundColor,
pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9) pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9)
), ),
content: buttonContent, content: AnyComponentWithIdentity(
id: AnyHashable("unpin"),
component: AnyComponent(
MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Unpin_Replace, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)))
)
),
isEnabled: state.selectedGift != nil, isEnabled: state.selectedGift != nil,
displaysProgress: false, displaysProgress: false,
action: { [weak state] in action: { [weak state] in
@ -258,6 +268,8 @@ private final class SheetContent: CombinedComponent {
let effectiveBottomInset: CGFloat = environment.metrics.isTablet ? 0.0 : environment.safeInsets.bottom let effectiveBottomInset: CGFloat = environment.metrics.isTablet ? 0.0 : environment.safeInsets.bottom
contentSize.height += 5.0 + effectiveBottomInset contentSize.height += 5.0 + effectiveBottomInset
appliedSelectedGift = state.selectedGift
return contentSize return contentSize
} }
@ -268,16 +280,19 @@ private final class SheetContainerComponent: CombinedComponent {
typealias EnvironmentType = ViewControllerComponentContainer.Environment typealias EnvironmentType = ViewControllerComponentContainer.Environment
let context: AccountContext let context: AccountContext
let gifts: [ProfileGiftsContext.State.StarGift] let gift: ProfileGiftsContext.State.StarGift
let pinnedGifts: [ProfileGiftsContext.State.StarGift]
let completion: (StarGiftReference) -> Void let completion: (StarGiftReference) -> Void
init( init(
context: AccountContext, context: AccountContext,
gifts: [ProfileGiftsContext.State.StarGift], gift: ProfileGiftsContext.State.StarGift,
pinnedGifts: [ProfileGiftsContext.State.StarGift],
completion: @escaping (StarGiftReference) -> Void completion: @escaping (StarGiftReference) -> Void
) { ) {
self.context = context self.context = context
self.gifts = gifts self.gift = gift
self.pinnedGifts = pinnedGifts
self.completion = completion self.completion = completion
} }
@ -285,7 +300,10 @@ private final class SheetContainerComponent: CombinedComponent {
if lhs.context !== rhs.context { if lhs.context !== rhs.context {
return false return false
} }
if lhs.gifts != rhs.gifts { if lhs.gift != rhs.gift {
return false
}
if lhs.pinnedGifts != rhs.pinnedGifts {
return false return false
} }
return true return true
@ -306,7 +324,8 @@ private final class SheetContainerComponent: CombinedComponent {
component: SheetComponent<EnvironmentType>( component: SheetComponent<EnvironmentType>(
content: AnyComponent<EnvironmentType>(SheetContent( content: AnyComponent<EnvironmentType>(SheetContent(
context: context.component.context, context: context.component.context,
gifts: context.component.gifts, gift: context.component.gift,
pinnedGifts: context.component.pinnedGifts,
completion: context.component.completion, completion: context.component.completion,
dismiss: { dismiss: {
animateOut.invoke(Action { _ in animateOut.invoke(Action { _ in
@ -374,24 +393,18 @@ private final class SheetContainerComponent: CombinedComponent {
public class GiftUnpinScreen: ViewControllerComponentContainer { public class GiftUnpinScreen: ViewControllerComponentContainer {
private let context: AccountContext
private let gifts: [ProfileGiftsContext.State.StarGift]
private let completion: (StarGiftReference) -> Void
public init( public init(
context: AccountContext, context: AccountContext,
gifts: [ProfileGiftsContext.State.StarGift], gift: ProfileGiftsContext.State.StarGift,
pinnedGifts: [ProfileGiftsContext.State.StarGift],
completion: @escaping (StarGiftReference) -> Void completion: @escaping (StarGiftReference) -> Void
) { ) {
self.context = context
self.gifts = gifts
self.completion = completion
super.init( super.init(
context: context, context: context,
component: SheetContainerComponent( component: SheetContainerComponent(
context: context, context: context,
gifts: gifts, gift: gift,
pinnedGifts: pinnedGifts,
completion: completion completion: completion
), ),
navigationBarAppearance: .none, navigationBarAppearance: .none,

View File

@ -376,12 +376,13 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
private func displayUnpinScreen(gift: ProfileGiftsContext.State.StarGift, completion: (() -> Void)? = nil) { private func displayUnpinScreen(gift: ProfileGiftsContext.State.StarGift, completion: (() -> Void)? = nil) {
guard let gifts = self.profileGifts.currentState?.gifts.filter({ $0.pinnedToTop }), let presentationData = self.currentParams?.presentationData else { guard let pinnedGifts = self.profileGifts.currentState?.gifts.filter({ $0.pinnedToTop }), let presentationData = self.currentParams?.presentationData else {
return return
} }
let controller = GiftUnpinScreen( let controller = GiftUnpinScreen(
context: context, context: self.context,
gifts: gifts, gift: gift,
pinnedGifts: pinnedGifts,
completion: { [weak self] unpinnedReference in completion: { [weak self] unpinnedReference in
guard let self else { guard let self else {
return return
@ -389,7 +390,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
completion?() completion?()
var replacingTitle = "" var replacingTitle = ""
for gift in gifts { for gift in pinnedGifts {
if gift.reference == unpinnedReference, case let .unique(uniqueGift) = gift.gift { if gift.reference == unpinnedReference, case let .unique(uniqueGift) = gift.gift {
replacingTitle = "\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, presentationData.dateTimeFormat.groupingSeparator))" replacingTitle = "\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, presentationData.dateTimeFormat.groupingSeparator))"
} }

View File

@ -143,7 +143,7 @@ final class GiftListItemComponent: Component {
) )
), ),
environment: {}, environment: {},
containerSize: itemFrame.size containerSize: itemFrame.insetBy(dx: -2.0, dy: -2.0).size
) )
if let itemView = visibleItem.view { if let itemView = visibleItem.view {
if itemView.superview == nil { if itemView.superview == nil {
@ -154,7 +154,7 @@ final class GiftListItemComponent: Component {
itemView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25) itemView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
} }
} }
itemTransition.setFrame(view: itemView, frame: itemFrame) itemTransition.setFrame(view: itemView, frame: itemFrame.insetBy(dx: -2.0, dy: -2.0))
} }
} }
itemFrame.origin.x += itemFrame.width + spacing itemFrame.origin.x += itemFrame.width + spacing