Various improvements

This commit is contained in:
Ilya Laktyushin
2025-01-18 13:44:42 +04:00
parent a8fd8c6085
commit ef6c097f6f
57 changed files with 1892 additions and 485 deletions

View File

@@ -385,6 +385,7 @@ private final class GiftViewSheetContent: CombinedComponent {
let strings = environment.strings
let dateTimeFormat = environment.dateTimeFormat
let nameDisplayOrder = component.context.sharedContext.currentPresentationData.with { $0 }.nameDisplayOrder
let controller = environment.controller
let state = context.state
let subject = state.subject
@@ -410,6 +411,7 @@ private final class GiftViewSheetContent: CombinedComponent {
var upgradeStars: Int64?
var uniqueGift: StarGift.UniqueGift?
var isSelfGift = false
var isChannelGift = false
if case let .soldOutGift(gift) = subject {
animationFile = gift.file
@@ -444,7 +446,12 @@ private final class GiftViewSheetContent: CombinedComponent {
uniqueGift = gift
}
savedToProfile = arguments.savedToProfile
incoming = arguments.incoming || arguments.peerId == component.context.account.peerId
if let reference = arguments.reference, case .peer = reference {
isChannelGift = true
incoming = true
} else {
incoming = arguments.incoming || arguments.peerId == component.context.account.peerId
}
nameHidden = arguments.nameHidden
isSelfGift = arguments.messageId?.peerId == component.context.account.peerId
@@ -482,6 +489,9 @@ private final class GiftViewSheetContent: CombinedComponent {
return
}
if state.inWearPreview {
if let controller = controller() as? GiftViewScreen {
controller.dismissAllTooltips()
}
state.inWearPreview = false
state.updated(transition: .spring(duration: 0.4))
} else if state.inUpgradePreview {
@@ -849,8 +859,7 @@ private final class GiftViewSheetContent: CombinedComponent {
textColor: secondaryTextColor,
accentColor: linkColor,
iconName: "Premium/Collectible/Tradable",
iconColor: linkColor,
badge: strings.Gift_Upgrade_Soon
iconColor: linkColor
))
)
)
@@ -937,9 +946,9 @@ private final class GiftViewSheetContent: CombinedComponent {
} else if let convertStars, !upgraded {
if !converted {
if canUpgrade || upgradeStars != nil {
descriptionText = strings.Gift_View_KeepUpgradeOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
descriptionText = isChannelGift ? strings.Gift_View_KeepUpgradeOrConvertDescription_Channel(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string : strings.Gift_View_KeepUpgradeOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
} else {
descriptionText = strings.Gift_View_KeepOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
descriptionText = isChannelGift ? strings.Gift_View_KeepOrConvertDescription_Channel(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string : strings.Gift_View_KeepOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
}
} else {
descriptionText = strings.Gift_View_ConvertedDescription(strings.Gift_View_ConvertedDescription_Stars(Int32(convertStars))).string
@@ -1152,7 +1161,7 @@ private final class GiftViewSheetContent: CombinedComponent {
),
action: {
component.openPeer(peer)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1188,7 +1197,7 @@ private final class GiftViewSheetContent: CombinedComponent {
),
action: {
component.openPeer(peer)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1215,7 +1224,7 @@ private final class GiftViewSheetContent: CombinedComponent {
isBot = true
}
let fromComponent: AnyComponent<Empty>
if incoming && !peer.isDeleted && !isBot {
if incoming && !peer.isDeleted && !isBot && !isChannelGift {
fromComponent = AnyComponent(
HStack([
AnyComponentWithIdentity(
@@ -1231,7 +1240,7 @@ private final class GiftViewSheetContent: CombinedComponent {
),
action: {
component.openPeer(peer)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1247,7 +1256,7 @@ private final class GiftViewSheetContent: CombinedComponent {
)),
action: {
component.sendGift(peerId)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1267,7 +1276,7 @@ private final class GiftViewSheetContent: CombinedComponent {
),
action: {
component.openPeer(peer)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1315,7 +1324,7 @@ private final class GiftViewSheetContent: CombinedComponent {
effectAlignment: .center,
action: {
component.transferGift()
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1326,9 +1335,10 @@ private final class GiftViewSheetContent: CombinedComponent {
)
context.add(transferButton
.position(CGPoint(x: sideInset + buttonWidth / 2.0, y: headerHeight - buttonHeight / 2.0 - 16.0))
.appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true))
)
let controller = environment.controller
let wearButton = wearButton.update(
component: PlainButtonComponent(
content: AnyComponent(
@@ -1345,7 +1355,7 @@ private final class GiftViewSheetContent: CombinedComponent {
state.pendingWear = false
state.updated(transition: .spring(duration: 0.4))
component.showAttributeInfo(statusTag, "You took off \(uniqueGift.title) #\(uniqueGift.number)")
component.showAttributeInfo(statusTag, strings.Gift_View_TookOff("\(uniqueGift.title) #\(uniqueGift.number)").string)
} else {
if let controller = controller() as? GiftViewScreen {
controller.dismissAllTooltips()
@@ -1362,6 +1372,8 @@ private final class GiftViewSheetContent: CombinedComponent {
)
context.add(wearButton
.position(CGPoint(x: context.availableSize.width / 2.0, y: headerHeight - buttonHeight / 2.0 - 16.0))
.appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true))
)
let shareButton = shareButton.update(
@@ -1383,6 +1395,8 @@ private final class GiftViewSheetContent: CombinedComponent {
)
context.add(shareButton
.position(CGPoint(x: context.availableSize.width - sideInset - buttonWidth / 2.0, y: headerHeight - buttonHeight / 2.0 - 16.0))
.appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true))
)
}
@@ -1506,7 +1520,7 @@ private final class GiftViewSheetContent: CombinedComponent {
}
if let mention = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerMention)] as? TelegramPeerMention, let peer = state.peerMap[mention.peerId] {
component.openPeer(peer)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1734,11 +1748,11 @@ private final class GiftViewSheetContent: CombinedComponent {
}
let descriptionText: String
if savedToProfile {
descriptionText = strings.Gift_View_DisplayedInfoHide
descriptionText = isChannelGift ? strings.Gift_View_DisplayedInfoHide_Channel : strings.Gift_View_DisplayedInfoHide
} else if let upgradeStars, upgradeStars > 0 && !upgraded {
descriptionText = strings.Gift_View_HiddenInfoShow
descriptionText = isChannelGift ? strings.Gift_View_HiddenInfoShow_Channel : strings.Gift_View_HiddenInfoShow
} else {
descriptionText = strings.Gift_View_HiddenInfo
descriptionText = isChannelGift ? strings.Gift_View_HiddenInfo_Channel : strings.Gift_View_HiddenInfo
}
let textFont = Font.regular(13.0)
@@ -1769,7 +1783,7 @@ private final class GiftViewSheetContent: CombinedComponent {
},
tapAction: { _, _ in
component.updateSavedToProfile(!savedToProfile)
Queue.mainQueue().after(1.0, {
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
@@ -1794,26 +1808,74 @@ private final class GiftViewSheetContent: CombinedComponent {
)
let buttonChild: _UpdatedChildComponent
if state.inWearPreview, let uniqueGift {
let buttonContent: AnyComponentWithIdentity<Empty>
if !component.context.isPremium {
buttonContent = AnyComponentWithIdentity(
id: AnyHashable("wear_locked"),
component: AnyComponent(
HStack([
AnyComponentWithIdentity(
id: AnyHashable("icon"),
component: AnyComponent(BundleIconComponent(name: "Chat/Stickers/Lock", tintColor: theme.list.itemCheckColors.foregroundColor))
),
AnyComponentWithIdentity(
id: AnyHashable("label"),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Wear_Start, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
)
], spacing: 3.0)
)
)
} else {
buttonContent = AnyComponentWithIdentity(
id: AnyHashable("wear"),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Wear_Start, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
)
}
buttonChild = button.update(
component: ButtonComponent(
background: buttonBackground,
content: AnyComponentWithIdentity(
id: AnyHashable("wear"),
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Wear_Start, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
),
content: buttonContent,
isEnabled: true,
displaysProgress: false,
action: { [weak state] in
if let state {
state.pendingWear = true
state.pendingTakeOff = false
state.inWearPreview = false
state.updated(transition: .spring(duration: 0.4))
let _ = component.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).start()
Queue.mainQueue().after(0.2) {
component.showAttributeInfo(statusTag, "You put on \(uniqueGift.title) #\(uniqueGift.number)")
let context = component.context
if !context.isPremium, let controller = controller() as? GiftViewScreen {
controller.dismissAllTooltips()
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let text = strings.Gift_View_TooltipPremiumWearing
let tooltipController = UndoOverlayController(
presentationData: presentationData,
content: .premiumPaywall(title: nil, text: text, customUndoText: nil, timeout: nil, linkAction: nil),
position: .bottom,
animateInAsReplacement: false,
appearance: UndoOverlayController.Appearance(sideInset: 16.0, bottomInset: 62.0),
action: { [weak controller] action in
if case .info = action {
controller?.dismissAllTooltips()
let premiumController = context.sharedContext.makePremiumIntroController(context: context, source: .messageEffects, forceDark: false, dismissed: nil)
controller?.push(premiumController)
Queue.mainQueue().after(0.6, {
component.cancel(false)
})
}
return false
}
)
controller.present(tooltipController, in: .window(.root))
} else {
state.pendingWear = true
state.pendingTakeOff = false
state.inWearPreview = false
state.updated(transition: .spring(duration: 0.4))
let _ = component.context.engine.accountData.setStarGiftStatus(starGift: uniqueGift, expirationDate: nil).start()
Queue.mainQueue().after(0.2) {
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string)
}
}
}
}),
@@ -1901,7 +1963,7 @@ private final class GiftViewSheetContent: CombinedComponent {
transition: context.transition
)
} else if incoming && !converted && !savedToProfile {
let buttonTitle = savedToProfile ? strings.Gift_View_Hide : strings.Gift_View_Display
let buttonTitle = isChannelGift ? strings.Gift_View_Display_Channel : strings.Gift_View_Display
buttonChild = button.update(
component: ButtonComponent(
background: buttonBackground,
@@ -2131,9 +2193,21 @@ public class GiftViewScreen: ViewControllerComponentContainer {
case let .message(message):
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
switch action.action {
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _, upgradeMessageId, _, _):
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, .message(messageId: message.id), message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil, upgradeMessageId)
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _):
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _, upgradeMessageId, peerId, senderId, savedId):
var reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
} else {
reference = .message(messageId: message.id)
}
return (message.id.peerId, senderId ?? message.author?.id, message.author?.compactDisplayTitle, message.id, reference, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil, upgradeMessageId)
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, _, peerId, senderId, savedId):
var reference: StarGiftReference
if let peerId, let savedId {
reference = .peer(peerId: peerId, id: savedId)
} else {
reference = .message(messageId: message.id)
}
var incoming = false
if isUpgrade {
if message.author?.id != message.id.peerId {
@@ -2146,7 +2220,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
} else {
incoming = message.flags.contains(.Incoming)
}
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, .message(messageId: message.id), incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, false, nil, transferStars, canExportDate, nil)
return (message.id.peerId, senderId ?? message.author?.id, message.author?.compactDisplayTitle, message.id, reference, incoming, gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, false, nil, transferStars, canExportDate, nil)
default:
return nil
}
@@ -2545,7 +2619,7 @@ public class GiftViewScreen: ViewControllerComponentContainer {
return
}
openPeerImpl?(peer)
Queue.mainQueue().after(1.0) {
Queue.mainQueue().after(0.6) {
self?.dismiss(animated: false, completion: nil)
}
})
@@ -3398,13 +3472,16 @@ private final class GiftViewContextReferenceContentSource: ContextReferenceConte
private final class HeaderButtonComponent: CombinedComponent {
let title: String
let iconName: String
let isLocked: Bool
public init(
title: String,
iconName: String
iconName: String,
isLocked: Bool = false
) {
self.title = title
self.iconName = iconName
self.isLocked = isLocked
}
static func ==(lhs: HeaderButtonComponent, rhs: HeaderButtonComponent) -> Bool {
@@ -3414,6 +3491,9 @@ private final class HeaderButtonComponent: CombinedComponent {
if lhs.iconName != rhs.iconName {
return false
}
if lhs.isLocked != rhs.isLocked {
return false
}
return true
}
@@ -3421,6 +3501,7 @@ private final class HeaderButtonComponent: CombinedComponent {
let background = Child(RoundedRectangle.self)
let title = Child(MultilineTextComponent.self)
let icon = Child(BundleIconComponent.self)
let lockIcon = Child(BundleIconComponent.self)
return { context in
let component = context.component
@@ -3448,7 +3529,7 @@ private final class HeaderButtonComponent: CombinedComponent {
context.add(icon
.position(CGPoint(x: context.availableSize.width / 2.0, y: 22.0))
)
let title = title.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(
@@ -3463,8 +3544,27 @@ private final class HeaderButtonComponent: CombinedComponent {
availableSize: CGSize(width: context.availableSize.width - 16.0, height: context.availableSize.height),
transition: .immediate
)
var totalTitleWidth = title.size.width
var titleOriginX = context.availableSize.width / 2.0 - totalTitleWidth / 2.0
if component.isLocked {
let titleSpacing: CGFloat = 2.0
let lockIcon = lockIcon.update(
component: BundleIconComponent(
name: "Chat List/StatusLockIcon",
tintColor: UIColor.white
),
availableSize: context.availableSize,
transition: .immediate
)
totalTitleWidth += lockIcon.size.width + titleSpacing
titleOriginX = context.availableSize.width / 2.0 - totalTitleWidth / 2.0
context.add(lockIcon
.position(CGPoint(x: titleOriginX + lockIcon.size.width / 2.0, y: 42.0))
)
titleOriginX += lockIcon.size.width + titleSpacing
}
context.add(title
.position(CGPoint(x: context.availableSize.width / 2.0, y: 42.0))
.position(CGPoint(x: titleOriginX + title.size.width / 2.0, y: 42.0))
)
return context.availableSize