mirror of
https://github.com/ichmagmaus111/ghostgram.git
synced 2026-08-11 16:40:22 +02:00
chore: migrate to new version + fixed several critical bugs
- Migrated project to latest Telegram iOS base (v12.3.2+) - Fixed circular dependency between GhostModeManager and MiscSettingsManager - Fixed multiple Bazel build configuration errors (select() default conditions) - Fixed duplicate type definitions in PeerInfoScreen - Fixed swiftmodule directory resolution in build scripts - Added Ghostgram Settings tab in main Settings menu with all 5 features - Cleared sensitive credentials from config.json (template-only now) - Excluded bazel-cache from version control
This commit is contained in:
+256
-284
@@ -40,6 +40,10 @@ import ChatThemeScreen
|
||||
import ProfileLevelRatingBarComponent
|
||||
import AnimatedTextComponent
|
||||
import InfoParagraphComponent
|
||||
import ChatMessagePaymentAlertController
|
||||
import TableComponent
|
||||
import PeerTableCellComponent
|
||||
import AvatarComponent
|
||||
|
||||
private final class GiftViewSheetContent: CombinedComponent {
|
||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
@@ -120,6 +124,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
let levelsDisposable = MetaDisposable()
|
||||
var nextGiftToUpgrade: ProfileGiftsContext.State.StarGift?
|
||||
|
||||
var giftVariantsDisposable = MetaDisposable()
|
||||
|
||||
var buyForm: BotPaymentForm?
|
||||
var buyFormDisposable: Disposable?
|
||||
var buyDisposable: Disposable?
|
||||
@@ -374,6 +380,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
self.buyDisposable?.dispose()
|
||||
self.levelsDisposable.dispose()
|
||||
self.starsTopUpOptionsDisposable?.dispose()
|
||||
self.giftVariantsDisposable.dispose()
|
||||
}
|
||||
|
||||
func openPeer(_ peer: EnginePeer, gifts: Bool = false, dismiss: Bool = true) {
|
||||
@@ -625,7 +632,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
controller?.dismissAnimated()
|
||||
|
||||
if let navigationController {
|
||||
Queue.mainQueue().after(0.5) {
|
||||
Queue.mainQueue().after(2.5) {
|
||||
starsContext.load(force: true)
|
||||
|
||||
let text: String
|
||||
@@ -730,7 +737,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
Queue.mainQueue().after(0.5) {
|
||||
Queue.mainQueue().after(2.5) {
|
||||
starsContext?.load(force: true)
|
||||
}
|
||||
switch self.subject {
|
||||
@@ -1134,7 +1141,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let peerId = peerIds.first else {
|
||||
return .complete()
|
||||
}
|
||||
Queue.mainQueue().after(1.5, {
|
||||
Queue.mainQueue().after(2.5, {
|
||||
if transferStars > 0 {
|
||||
context.starsContext?.load(force: true)
|
||||
}
|
||||
@@ -1350,6 +1357,33 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func openUpgradeVariants(attribute: StarGift.UniqueGift.Attribute? = nil) {
|
||||
guard let controller = self.getController() as? GiftViewScreen, let arguments = self.subject.arguments else {
|
||||
return
|
||||
}
|
||||
var selectedAttributes: [StarGift.UniqueGift.Attribute]?
|
||||
if case let .unique(uniqueGift) = arguments.gift {
|
||||
selectedAttributes = uniqueGift.attributes
|
||||
}
|
||||
|
||||
self.giftVariantsDisposable.set((self.context.engine.payments.getStarGiftUpgradeAttributes(giftId: arguments.gift.giftId)
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] attributes in
|
||||
guard let self, let attributes else {
|
||||
return
|
||||
}
|
||||
let variantsController = self.context.sharedContext.makeGiftUpgradeVariantsScreen(
|
||||
context: self.context,
|
||||
gift: arguments.gift,
|
||||
attributes: attributes,
|
||||
selectedAttributes: selectedAttributes,
|
||||
focusedAttribute: attribute
|
||||
)
|
||||
controller.push(variantsController)
|
||||
}))
|
||||
}
|
||||
|
||||
func showAttributeInfo(tag: Any, text: String) {
|
||||
guard let controller = self.getController() as? GiftViewScreen else {
|
||||
return
|
||||
@@ -1821,7 +1855,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
|
||||
self.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
Queue.mainQueue().after(0.5) {
|
||||
Queue.mainQueue().after(2.5) {
|
||||
switch finalPrice.currency {
|
||||
case .stars:
|
||||
context.starsContext?.load(force: true)
|
||||
@@ -2114,7 +2148,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
self.subject = .profileGift(peerId, result)
|
||||
self.updated(transition: .spring(duration: 0.4))
|
||||
|
||||
Queue.mainQueue().after(0.5) {
|
||||
Queue.mainQueue().after(2.5) {
|
||||
starsContext?.load(force: true)
|
||||
}
|
||||
})
|
||||
@@ -2233,7 +2267,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
Queue.mainQueue().after(0.5) {
|
||||
Queue.mainQueue().after(2.5) {
|
||||
starsContext?.load(force: true)
|
||||
}
|
||||
|
||||
@@ -2337,6 +2371,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let gift = self.subject.arguments?.gift, case let .unique(uniqueGift) = gift, case let .peerId(ownerPeerId) = uniqueGift.owner, let controller = self.getController() else {
|
||||
return
|
||||
}
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: ownerPeerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
||||
guard let self, let peer else {
|
||||
@@ -2346,13 +2381,41 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.commitGiftBuyOffer(peer: peer, price: amount, duration: duration)
|
||||
|
||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.SendPaidMessageStars(id: peer.id))
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak controller] sendPaidMessageStars in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let action: (Int64?) -> Void = { allowPaidStars in
|
||||
self.commitGiftBuyOffer(peer: peer, price: amount, duration: duration, allowPaidStars: allowPaidStars)
|
||||
}
|
||||
if let sendPaidMessageStars, sendPaidMessageStars.value > 0 {
|
||||
let alertController = chatMessagePaymentAlertController(
|
||||
context: nil,
|
||||
presentationData: presentationData,
|
||||
updatedPresentationData: nil,
|
||||
peers: [EngineRenderedPeer(peer: peer)],
|
||||
count: 1,
|
||||
amount: sendPaidMessageStars,
|
||||
totalAmount: nil,
|
||||
hasCheck: false,
|
||||
navigationController: controller?.navigationController as? NavigationController,
|
||||
completion: { _ in
|
||||
action(sendPaidMessageStars.value)
|
||||
}
|
||||
)
|
||||
controller?.present(alertController, in: .window(.root))
|
||||
} else {
|
||||
action(nil)
|
||||
}
|
||||
})
|
||||
}))
|
||||
controller.push(buyController)
|
||||
})
|
||||
}
|
||||
|
||||
func commitGiftBuyOffer(peer: EnginePeer, price: CurrencyAmount, duration: Int32) {
|
||||
func commitGiftBuyOffer(peer: EnginePeer, price: CurrencyAmount, duration: Int32, allowPaidStars: Int64?) {
|
||||
guard let gift = self.subject.arguments?.gift, case let .unique(uniqueGift) = gift, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
||||
return
|
||||
}
|
||||
@@ -2362,13 +2425,13 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.upgradeDisposable = (context.engine.payments.sendStarGiftOffer(peerId: peer.id, slug: uniqueGift.slug, amount: price, duration: duration, allowPaidStars: nil)
|
||||
self.upgradeDisposable = (context.engine.payments.sendStarGiftOffer(peerId: peer.id, slug: uniqueGift.slug, amount: price, duration: duration, allowPaidStars: allowPaidStars)
|
||||
|> deliverOnMainQueue).start(error: { _ in
|
||||
}, completed: { [weak self, weak starsContext] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
Queue.mainQueue().after(0.5) {
|
||||
Queue.mainQueue().after(2.5) {
|
||||
starsContext?.load(force: true)
|
||||
}
|
||||
self.openPeer(peer, dismiss: true)
|
||||
@@ -2383,11 +2446,15 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
guard let self, let controller = self.getController() else {
|
||||
return
|
||||
}
|
||||
var finalStars = price.amount.value
|
||||
if let allowPaidStars {
|
||||
finalStars += allowPaidStars
|
||||
}
|
||||
let purchaseController = context.sharedContext.makeStarsPurchaseScreen(
|
||||
context: context,
|
||||
starsContext: starsContext,
|
||||
options: options ?? [],
|
||||
purpose: .starGiftOffer(requiredStars: price.amount.value),
|
||||
purpose: .starGiftOffer(requiredStars: finalStars),
|
||||
targetPeerId: nil,
|
||||
customTheme: nil,
|
||||
completion: { [weak self, weak starsContext] stars in
|
||||
@@ -2411,7 +2478,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
self.inProgress = false
|
||||
self.updated()
|
||||
|
||||
self.commitGiftBuyOffer(peer: peer, price: price, duration: duration)
|
||||
self.commitGiftBuyOffer(peer: peer, price: price, duration: duration, allowPaidStars: allowPaidStars)
|
||||
} else {
|
||||
proceed()
|
||||
}
|
||||
@@ -2480,10 +2547,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
let upgradeNextButton = Child(PlainButtonComponent.self)
|
||||
|
||||
let upgradeTitle = Child(MultilineTextComponent.self)
|
||||
let upgradeDescription = Child(BalancedTextComponent.self)
|
||||
let upgradeDescription = Child(PlainButtonComponent.self)
|
||||
let upgradePerks = Child(List<Empty>.self)
|
||||
let upgradeKeepName = Child(PlainButtonComponent.self)
|
||||
let upgradePriceButton = Child(PlainButtonComponent.self)
|
||||
let variantsMeasureDescription = Child(MultilineTextComponent.self)
|
||||
|
||||
let spaceRegex = try? NSRegularExpression(pattern: "\\[(.*?)\\]", options: [])
|
||||
|
||||
@@ -2687,10 +2755,10 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
}
|
||||
headerSubject = .unique(state.justUpgraded ? state.upgradePreview?.attributes : nil, uniqueGift)
|
||||
} else if state.inUpgradePreview, let attributes = state.upgradePreview?.attributes {
|
||||
headerHeight = 258.0
|
||||
headerHeight = 246.0
|
||||
headerSubject = .preview(attributes)
|
||||
} else if case let .upgradePreview(attributes, _) = component.subject {
|
||||
headerHeight = 258.0
|
||||
headerHeight = 246.0
|
||||
headerSubject = .preview(attributes)
|
||||
} else if case let .wearPreview(_, attributes) = component.subject, let attributes {
|
||||
headerHeight = 200.0
|
||||
@@ -2944,9 +3012,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
originY += 16.0
|
||||
} else if showUpgradePreview {
|
||||
let title: String
|
||||
let description: String
|
||||
let uniqueText: String
|
||||
let transferableText: String
|
||||
let tradableText: String
|
||||
if !incoming, case let .profileGift(peerId, _) = subject, let peer = state.peerMap[peerId] {
|
||||
var peerName = peer.compactDisplayTitle
|
||||
@@ -2954,9 +3020,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
peerName = "\(peerName.prefix(22))…"
|
||||
}
|
||||
title = environment.strings.Gift_Upgrade_GiftTitle
|
||||
description = environment.strings.Gift_Upgrade_GiftDescription(peerName).string
|
||||
uniqueText = strings.Gift_Upgrade_Unique_GiftDescription(peerName).string
|
||||
transferableText = strings.Gift_Upgrade_Transferable_GiftDescription(peerName).string
|
||||
tradableText = strings.Gift_Upgrade_Tradable_GiftDescription(peerName).string
|
||||
} else if case let .upgradePreview(_, peerName) = component.subject {
|
||||
var peerName = peerName
|
||||
@@ -2964,15 +3028,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
peerName = "\(peerName.prefix(22))…"
|
||||
}
|
||||
title = environment.strings.Gift_Upgrade_IncludeTitle
|
||||
description = environment.strings.Gift_Upgrade_IncludeDescription(peerName).string
|
||||
uniqueText = strings.Gift_Upgrade_Unique_IncludeDescription
|
||||
transferableText = strings.Gift_Upgrade_Transferable_IncludeDescription
|
||||
tradableText = strings.Gift_Upgrade_Tradable_IncludeDescription
|
||||
} else {
|
||||
title = environment.strings.Gift_Upgrade_Title
|
||||
description = environment.strings.Gift_Upgrade_Description
|
||||
uniqueText = strings.Gift_Upgrade_Unique_Description
|
||||
transferableText = strings.Gift_Upgrade_Transferable_Description
|
||||
tradableText = strings.Gift_Upgrade_Tradable_Description
|
||||
}
|
||||
|
||||
@@ -2990,39 +3050,119 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
|
||||
transition: .immediate
|
||||
)
|
||||
let upgradeDescription = upgradeDescription.update(
|
||||
component: BalancedTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: description,
|
||||
font: Font.regular(13.0),
|
||||
textColor: .white,
|
||||
paragraphAlignment: .center
|
||||
)),
|
||||
horizontalAlignment: .center,
|
||||
maximumNumberOfLines: 5,
|
||||
lineSpacing: 0.2,
|
||||
tintColor: vibrantColor
|
||||
),
|
||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 50.0, height: CGFloat.greatestFiniteMagnitude),
|
||||
transition: context.transition
|
||||
)
|
||||
|
||||
let spacing: CGFloat = 6.0
|
||||
let totalHeight: CGFloat = upgradeTitle.size.height + spacing + upgradeDescription.size.height
|
||||
|
||||
headerComponents.append({
|
||||
context.add(upgradeTitle
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: floor(212.0 - totalHeight / 2.0 + upgradeTitle.size.height / 2.0)))
|
||||
.appear(.default(alpha: true))
|
||||
.disappear(.default(alpha: true))
|
||||
if case let .generic(gift) = component.subject.arguments?.gift, let upgradePreview = state.upgradePreview {
|
||||
var variant1: GiftItemComponent.Subject = .starGift(gift: gift, price: "")
|
||||
var variant2: GiftItemComponent.Subject = .starGift(gift: gift, price: "")
|
||||
var variant3: GiftItemComponent.Subject = .starGift(gift: gift, price: "")
|
||||
|
||||
var i = 0
|
||||
for attribute in upgradePreview.attributes {
|
||||
if case .model = attribute {
|
||||
switch i {
|
||||
case 0:
|
||||
variant1 = .preview(attributes: [attribute], rarity: 0)
|
||||
case 1:
|
||||
variant2 = .preview(attributes: [attribute], rarity: 0)
|
||||
case 2:
|
||||
variant3 = .preview(attributes: [attribute], rarity: 0)
|
||||
default:
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
|
||||
var buttonColor: UIColor = UIColor.white.withAlphaComponent(0.16)
|
||||
if let previewPatternColor = giftCompositionExternalState.previewPatternColor {
|
||||
buttonColor = previewPatternColor
|
||||
}
|
||||
|
||||
let variantsMeasureDescription = variantsMeasureDescription.update(
|
||||
component: MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Upgrade_ViewAllVariants, font: Font.semibold(13.0), textColor: .clear))),
|
||||
availableSize: context.availableSize,
|
||||
transition: .immediate
|
||||
)
|
||||
context.add(variantsMeasureDescription
|
||||
.position(CGPoint(x: -10000.0, y: -10000.0))
|
||||
)
|
||||
|
||||
context.add(upgradeDescription
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: floor(212.0 + totalHeight / 2.0 - upgradeDescription.size.height / 2.0)))
|
||||
.appear(.default(alpha: true))
|
||||
.disappear(.default(alpha: true))
|
||||
let upgradeDescription = upgradeDescription.update(
|
||||
component: PlainButtonComponent(
|
||||
content: AnyComponent(
|
||||
ZStack([
|
||||
AnyComponentWithIdentity(id: "background", component: AnyComponent(
|
||||
FilledRoundedRectangleComponent(color: buttonColor, cornerRadius: .minEdge, smoothCorners: false)
|
||||
)),
|
||||
AnyComponentWithIdentity(id: "label", component: AnyComponent(HStack([
|
||||
AnyComponentWithIdentity(id: "icon1", component: AnyComponent(
|
||||
GiftItemComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
peer: nil,
|
||||
subject: variant1,
|
||||
isPlaceholder: false,
|
||||
mode: .tableIcon
|
||||
)
|
||||
)),
|
||||
AnyComponentWithIdentity(id: "icon2", component: AnyComponent(
|
||||
GiftItemComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
peer: nil,
|
||||
subject: variant2,
|
||||
isPlaceholder: false,
|
||||
mode: .tableIcon
|
||||
)
|
||||
)),
|
||||
AnyComponentWithIdentity(id: "icon3", component: AnyComponent(
|
||||
GiftItemComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
peer: nil,
|
||||
subject: variant3,
|
||||
isPlaceholder: false,
|
||||
mode: .tableIcon
|
||||
)
|
||||
)),
|
||||
AnyComponentWithIdentity(id: "text", component: AnyComponent(
|
||||
MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Gift_Upgrade_ViewAllVariants, font: Font.semibold(13.0), textColor: .white)))
|
||||
)),
|
||||
AnyComponentWithIdentity(id: "arrow", component: AnyComponent(
|
||||
BundleIconComponent(name: "Item List/InlineTextRightArrow", tintColor: .white)
|
||||
))
|
||||
], spacing: 3.0)))
|
||||
])
|
||||
),
|
||||
action: { [weak state] in
|
||||
state?.openUpgradeVariants()
|
||||
},
|
||||
animateScale: false
|
||||
),
|
||||
availableSize: CGSize(width: variantsMeasureDescription.size.width + 87.0, height: 24.0),
|
||||
transition: context.transition
|
||||
)
|
||||
})
|
||||
|
||||
let spacing: CGFloat = 6.0
|
||||
let totalHeight: CGFloat = upgradeTitle.size.height + spacing + upgradeDescription.size.height
|
||||
|
||||
headerComponents.append({
|
||||
context.add(upgradeTitle
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: floor(194.0 - totalHeight / 2.0 + upgradeTitle.size.height / 2.0)))
|
||||
.appear(.default(alpha: true))
|
||||
.disappear(.default(alpha: true))
|
||||
)
|
||||
|
||||
context.add(upgradeDescription
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: floor(198.0 + totalHeight / 2.0 - upgradeDescription.size.height / 2.0)))
|
||||
.appear(.default(alpha: true))
|
||||
.disappear(.default(alpha: true))
|
||||
)
|
||||
})
|
||||
}
|
||||
originY += 24.0
|
||||
|
||||
let textColor = theme.actionSheet.primaryTextColor
|
||||
@@ -3044,20 +3184,6 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
))
|
||||
)
|
||||
)
|
||||
items.append(
|
||||
AnyComponentWithIdentity(
|
||||
id: "transferable",
|
||||
component: AnyComponent(InfoParagraphComponent(
|
||||
title: strings.Gift_Upgrade_Transferable_Title,
|
||||
titleColor: textColor,
|
||||
text: transferableText,
|
||||
textColor: secondaryTextColor,
|
||||
accentColor: linkColor,
|
||||
iconName: "Premium/Collectible/Transferable",
|
||||
iconColor: linkColor
|
||||
))
|
||||
)
|
||||
)
|
||||
items.append(
|
||||
AnyComponentWithIdentity(
|
||||
id: "tradable",
|
||||
@@ -3072,6 +3198,20 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
))
|
||||
)
|
||||
)
|
||||
items.append(
|
||||
AnyComponentWithIdentity(
|
||||
id: "wearable",
|
||||
component: AnyComponent(InfoParagraphComponent(
|
||||
title: strings.Gift_Upgrade_Wearable_Title,
|
||||
titleColor: textColor,
|
||||
text: strings.Gift_Upgrade_Wearable_Text,
|
||||
textColor: secondaryTextColor,
|
||||
accentColor: linkColor,
|
||||
iconName: "Premium/Collectible/Wearable",
|
||||
iconColor: linkColor
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
let perksSideInset = sideInset + 16.0
|
||||
let upgradePerks = upgradePerks.update(
|
||||
@@ -3564,7 +3704,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
id: AnyHashable(0),
|
||||
component: AnyComponent(Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
PeerTableCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
@@ -3597,7 +3737,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
} else {
|
||||
ownerComponent = AnyComponent(Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
PeerTableCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
@@ -3648,7 +3788,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
title: strings.Gift_Unique_Telegram,
|
||||
component: AnyComponent(Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
PeerTableCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
@@ -3678,7 +3818,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
id: AnyHashable(0),
|
||||
component: AnyComponent(Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
PeerTableCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
@@ -3708,7 +3848,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
} else {
|
||||
fromComponent = AnyComponent(Button(
|
||||
content: AnyComponent(
|
||||
PeerCellComponent(
|
||||
PeerTableCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
@@ -3733,7 +3873,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
id: "from_anon",
|
||||
title: strings.Gift_View_From,
|
||||
component: AnyComponent(
|
||||
PeerCellComponent(
|
||||
PeerTableCellComponent(
|
||||
context: component.context,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
@@ -4117,7 +4257,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
color: theme.list.itemAccentColor
|
||||
)),
|
||||
action: { [weak state] in
|
||||
state?.showAttributeInfo(tag: tag, text: strings.Gift_Unique_AttributeDescription(formatPercentage(percentage)).string)
|
||||
state?.openUpgradeVariants(attribute: attribute)
|
||||
}
|
||||
).tagged(tag))
|
||||
))
|
||||
@@ -5164,42 +5304,50 @@ final class GiftViewSheetComponent: CombinedComponent {
|
||||
|
||||
var headerContent: AnyComponent<Empty>?
|
||||
if let arguments = context.component.subject.arguments, case .unique = arguments.gift, let fromPeerId = arguments.fromPeerId, var fromPeerName = arguments.fromPeerName, arguments.fromPeerId != context.component.context.account.peerId && !(arguments.fromPeerId?.isTelegramNotifications ?? false) {
|
||||
let dateString = stringForMediumDate(timestamp: arguments.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat, withTime: false)
|
||||
|
||||
if fromPeerName.count > 25 {
|
||||
fromPeerName = "\(fromPeerName.prefix(25))…"
|
||||
var showSenderInfo = false
|
||||
if arguments.incoming {
|
||||
showSenderInfo = true
|
||||
} else if arguments.peerId == context.component.context.account.peerId {
|
||||
showSenderInfo = true
|
||||
}
|
||||
if showSenderInfo {
|
||||
let dateString = stringForMediumDate(timestamp: arguments.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat, withTime: false)
|
||||
|
||||
if fromPeerName.count > 25 {
|
||||
fromPeerName = "\(fromPeerName.prefix(25))…"
|
||||
}
|
||||
let rawString = environment.strings.Gift_View_SenderInfo(fromPeerName, dateString).string
|
||||
let attributedString = parseMarkdownIntoAttributedString(rawString, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: .white), bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: .white), link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: .white), linkAttribute: { _ in return nil }))
|
||||
|
||||
let context = context.component.context
|
||||
headerContent = AnyComponent(
|
||||
PlainButtonComponent(content: AnyComponent(HeaderContentComponent(attributedText: attributedString)), action: {
|
||||
if let controller = controller(), let navigationController = controller.navigationController as? NavigationController {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: fromPeerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak navigationController] peer in
|
||||
guard let peer, let navigationController else {
|
||||
return
|
||||
}
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
navigationController: navigationController,
|
||||
chatController: nil,
|
||||
context: context,
|
||||
chatLocation: .peer(peer),
|
||||
subject: nil,
|
||||
botStart: nil,
|
||||
updateTextInputState: nil,
|
||||
keepStack: .always,
|
||||
useExisting: true,
|
||||
purposefulAction: nil,
|
||||
scrollToEndIfExists: false,
|
||||
activateMessageSearch: nil,
|
||||
animated: true
|
||||
))
|
||||
})
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
let rawString = environment.strings.Gift_View_SenderInfo(fromPeerName, dateString).string
|
||||
let attributedString = parseMarkdownIntoAttributedString(rawString, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: .white), bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: .white), link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: .white), linkAttribute: { _ in return nil }))
|
||||
|
||||
let context = context.component.context
|
||||
headerContent = AnyComponent(
|
||||
PlainButtonComponent(content: AnyComponent(HeaderContentComponent(attributedText: attributedString)), action: {
|
||||
if let controller = controller(), let navigationController = controller.navigationController as? NavigationController {
|
||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: fromPeerId))
|
||||
|> deliverOnMainQueue).start(next: { [weak navigationController] peer in
|
||||
guard let peer, let navigationController else {
|
||||
return
|
||||
}
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
navigationController: navigationController,
|
||||
chatController: nil,
|
||||
context: context,
|
||||
chatLocation: .peer(peer),
|
||||
subject: nil,
|
||||
botStart: nil,
|
||||
updateTextInputState: nil,
|
||||
keepStack: .always,
|
||||
useExisting: true,
|
||||
purposefulAction: nil,
|
||||
scrollToEndIfExists: false,
|
||||
activateMessageSearch: nil,
|
||||
animated: true
|
||||
))
|
||||
})
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
let sheet = sheet.update(
|
||||
@@ -5742,115 +5890,6 @@ func formatPercentage(_ value: Float) -> String {
|
||||
return String(format: "%0.1f", value).replacingOccurrences(of: ".0", with: "").replacingOccurrences(of: ",0", with: "") + "%"
|
||||
}
|
||||
|
||||
final class PeerCellComponent: Component {
|
||||
let context: AccountContext
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let peer: EnginePeer?
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EnginePeer?) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.peer = peer
|
||||
}
|
||||
|
||||
static func ==(lhs: PeerCellComponent, rhs: PeerCellComponent) -> Bool {
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.peer != rhs.peer {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let avatarNode: AvatarNode
|
||||
private let text = ComponentView<Empty>()
|
||||
|
||||
private var component: PeerCellComponent?
|
||||
private weak var state: EmptyComponentState?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 8.0))
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubnode(self.avatarNode)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func update(component: PeerCellComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
let avatarSize = CGSize(width: 22.0, height: 22.0)
|
||||
let spacing: CGFloat = 6.0
|
||||
|
||||
var peerName: String
|
||||
let avatarOverride: AvatarNodeImageOverride?
|
||||
if let peerValue = component.peer {
|
||||
peerName = peerValue.compactDisplayTitle
|
||||
if peerName.count > 40 {
|
||||
peerName = "\(peerName.prefix(40))…"
|
||||
}
|
||||
avatarOverride = nil
|
||||
} else {
|
||||
peerName = component.strings.Gift_View_HiddenName
|
||||
avatarOverride = .anonymousSavedMessagesIcon(isColored: true)
|
||||
}
|
||||
|
||||
let avatarNaturalSize = CGSize(width: 40.0, height: 40.0)
|
||||
self.avatarNode.setPeer(context: component.context, theme: component.theme, peer: component.peer, overrideImage: avatarOverride)
|
||||
self.avatarNode.bounds = CGRect(origin: .zero, size: avatarNaturalSize)
|
||||
|
||||
let textSize = self.text.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: peerName, font: Font.regular(15.0), textColor: component.peer != nil ? component.theme.list.itemAccentColor : component.theme.list.itemPrimaryTextColor, paragraphAlignment: .left))
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - avatarSize.width - spacing, height: availableSize.height)
|
||||
)
|
||||
|
||||
let size = CGSize(width: avatarSize.width + textSize.width + spacing, height: textSize.height)
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((size.height - avatarSize.height) / 2.0)), size: avatarSize)
|
||||
self.avatarNode.frame = avatarFrame
|
||||
|
||||
if let view = self.text.view {
|
||||
if view.superview == nil {
|
||||
self.addSubview(view)
|
||||
}
|
||||
let textFrame = CGRect(origin: CGPoint(x: avatarSize.width + spacing, y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
|
||||
transition.setFrame(view: view, frame: textFrame)
|
||||
}
|
||||
|
||||
return size
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
final class HeaderContentComponent: Component {
|
||||
let attributedText: NSAttributedString
|
||||
|
||||
@@ -6165,73 +6204,6 @@ private final class HeaderButtonComponent: CombinedComponent {
|
||||
}
|
||||
}
|
||||
|
||||
final class AvatarComponent: Component {
|
||||
let context: AccountContext
|
||||
let theme: PresentationTheme
|
||||
let peer: EnginePeer
|
||||
|
||||
init(context: AccountContext, theme: PresentationTheme, peer: EnginePeer) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.peer = peer
|
||||
}
|
||||
|
||||
static func ==(lhs: AvatarComponent, rhs: AvatarComponent) -> Bool {
|
||||
if lhs.context !== rhs.context {
|
||||
return false
|
||||
}
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.peer != rhs.peer {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
final class View: UIView {
|
||||
private let avatarNode: AvatarNode
|
||||
|
||||
private var component: AvatarComponent?
|
||||
private weak var state: EmptyComponentState?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 42.0))
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubnode(self.avatarNode)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
func update(component: AvatarComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
self.component = component
|
||||
self.state = state
|
||||
|
||||
self.avatarNode.frame = CGRect(origin: .zero, size: availableSize)
|
||||
self.avatarNode.setPeer(
|
||||
context: component.context,
|
||||
theme: component.theme,
|
||||
peer: component.peer,
|
||||
synchronousLoad: true
|
||||
)
|
||||
|
||||
return availableSize
|
||||
}
|
||||
}
|
||||
|
||||
func makeView() -> View {
|
||||
return View(frame: CGRect())
|
||||
}
|
||||
|
||||
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private struct GiftViewConfiguration {
|
||||
public static var defaultValue: GiftViewConfiguration {
|
||||
return GiftViewConfiguration(explorerUrl: "https://tonviewer.com")
|
||||
|
||||
Reference in New Issue
Block a user