Merge commit '74b761c53f' into beta

This commit is contained in:
Isaac 2025-11-16 13:53:18 +08:00
commit 0859e8594c
11 changed files with 140 additions and 81 deletions

View file

@ -1423,8 +1423,8 @@ public protocol SharedAccountContext: AnyObject {
func makeGiftViewScreen(context: AccountContext, gift: StarGift.UniqueGift, shareStory: ((StarGift.UniqueGift) -> Void)?, openChatTheme: (() -> Void)?, dismissed: (() -> Void)?) -> ViewController
func makeGiftWearPreviewScreen(context: AccountContext, gift: StarGift.UniqueGift) -> ViewController
func makeGiftAuctionInfoScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: (() -> Void)?) -> ViewController
func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: [GiftAuctionAcquiredGift]?) -> ViewController
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: @escaping ([GiftAuctionAcquiredGift]?) -> Void) -> ViewController
func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?) -> ViewController
func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: @escaping (Signal<[GiftAuctionAcquiredGift], NoError>) -> Void) -> ViewController
func makeGiftAuctionActiveBidsScreen(context: AccountContext) -> ViewController
func makeStorySharingScreen(context: AccountContext, subject: StorySharingSubject, parentController: ViewController) -> ViewController

View file

@ -78,7 +78,11 @@ public final class GiftAuctionContext {
public let gift: StarGift
public var isActive: Bool {
return myState?.bidAmount != nil
if case .finished = auctionState {
return false
} else {
return myState?.bidAmount != nil
}
}
private let disposable = MetaDisposable()
@ -268,7 +272,7 @@ extension GiftAuctionContext.State.MyState {
}
}
public struct GiftAuctionAcquiredGift {
public struct GiftAuctionAcquiredGift: Equatable {
public var nameHidden: Bool
public let peer: EnginePeer
public let date: Int32

View file

@ -46,7 +46,7 @@ let collageGrids: [Camera.CollageGrid] = [
Camera.CollageGrid(rows: [Camera.CollageGrid.Row(columns: 2), Camera.CollageGrid.Row(columns: 2), Camera.CollageGrid.Row(columns: 2)])
]
enum CameraMode: Equatable {
enum CameraMode: Int32, Equatable {
case photo
case video
case live
@ -318,6 +318,7 @@ private final class CameraScreenComponent: CombinedComponent {
fileprivate var sendAsPeerId: EnginePeer.Id?
fileprivate var isCustomTarget = false
fileprivate var canLivestream = true
private var privacy: EngineStoryPrivacy = EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: [])
private var allowComments = true
@ -388,6 +389,17 @@ private final class CameraScreenComponent: CombinedComponent {
if let customTarget = controller.customTarget {
self.sendAsPeerId = customTarget
self.isCustomTarget = true
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: customTarget))
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let self else {
return
}
if case let .channel(channel) = peer, case .group = channel.info {
self.canLivestream = false
self.updated()
}
})
}
let _ = (mediaEditorStoredState(engine: self.context.engine)
@ -2091,7 +2103,7 @@ private final class CameraScreenComponent: CombinedComponent {
}
var availableModes: [CameraMode] = [.photo, .video]
if !isTablet {
if !isTablet && state.canLivestream {
availableModes.append(.live)
}

View file

@ -115,7 +115,7 @@ final class ModeComponent: Component {
private var backgroundView = UIView()
private var glassContainerView = GlassBackgroundContainerView()
private var selectionView = GlassBackgroundView()
private var itemViews: [ItemView] = []
private var itemViews: [Int32: ItemView] = [:]
public func matches(tag: Any) -> Bool {
if let component = self.component, let componentTag = component.tag {
@ -179,14 +179,19 @@ final class ModeComponent: Component {
var itemFrame = CGRect(origin: isTablet ? .zero : CGPoint(x: inset, y: 0.0), size: buttonSize)
var selectedCenter = itemFrame.minX
var selectedFrame = itemFrame
var validKeys: Set<Int32> = Set()
for mode in component.availableModes.reversed() {
let id = mode.rawValue
validKeys.insert(id)
let itemView: ItemView
if self.itemViews.count == i {
if let current = self.itemViews[id] {
itemView = current
} else {
itemView = ItemView()
self.backgroundView.addSubview(itemView)
self.itemViews.append(itemView)
} else {
itemView = self.itemViews[i]
self.itemViews[id] = itemView
}
itemView.pressed = {
updatedMode(mode)
@ -216,6 +221,20 @@ final class ModeComponent: Component {
i += 1
}
var removeKeys: [Int32] = []
for (id, itemView) in self.itemViews {
if !validKeys.contains(id) {
removeKeys.append(id)
transition.setAlpha(view: itemView, alpha: 0.0, completion: { _ in
itemView.removeFromSuperview()
})
}
}
for id in removeKeys {
self.itemViews.removeValue(forKey: id)
}
let totalSize: CGSize
let size: CGSize
if isTablet {

View file

@ -1940,7 +1940,9 @@ private class QrContentNode: ASDisplayNode, ContentNode {
imageSide = 220.0
if size.width > 375.0 {
if textLength > 12 {
if textLength > 18 {
fontSize = 16.0
} else if textLength > 12 {
fontSize = 22.0
} else {
fontSize = 24.0

View file

@ -1058,7 +1058,7 @@ public class NewContactScreen: ViewControllerComponentContainer {
fileprivate func complete(result: NewContactScreenComponent.Result) {
let entities = generateChatInputTextEntities(result.note)
if let peer = result.peer {
let _ = self.context.engine.contacts.addContactInteractively(
let _ = (self.context.engine.contacts.addContactInteractively(
peerId: peer.id,
firstName: result.firstName,
lastName: result.lastName,
@ -1066,7 +1066,7 @@ public class NewContactScreen: ViewControllerComponentContainer {
noteText: result.note.string,
noteEntities: entities,
addToPrivacyExceptions: result.addToPrivacyExceptions
).startStandalone(completed: { [weak self] in
) |> deliverOnMainQueue).startStandalone(completed: { [weak self] in
if !result.syncContactToPhone {
self?.completion(result.peer, nil, nil)
}

View file

@ -46,14 +46,14 @@ private final class GiftSetupScreenComponent: Component {
let context: AccountContext
let peerId: EnginePeer.Id
let subject: GiftSetupScreen.Subject
let auctionAcquiredGifts: [GiftAuctionAcquiredGift]?
let auctionAcquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?
let completion: (() -> Void)?
init(
context: AccountContext,
peerId: EnginePeer.Id,
subject: GiftSetupScreen.Subject,
auctionAcquiredGifts: [GiftAuctionAcquiredGift]?,
auctionAcquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?,
completion: (() -> Void)? = nil
) {
self.context = context
@ -887,6 +887,8 @@ private final class GiftSetupScreenComponent: Component {
let environment = environment[ViewControllerComponentContainer.Environment.self].value
let themeUpdated = self.environment?.theme !== environment.theme
let theme = environment.theme.withModalBlocksBackground()
let resetScrolling = self.scrollView.bounds.width != availableSize.width
let fillingSize: CGFloat
@ -1093,7 +1095,7 @@ private final class GiftSetupScreenComponent: Component {
if themeUpdated {
self.dimView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
self.backgroundLayer.backgroundColor = environment.theme.list.blocksBackgroundColor.cgColor
self.backgroundLayer.backgroundColor = theme.list.blocksBackgroundColor.cgColor
}
transition.setFrame(view: self.dimView, frame: CGRect(origin: CGPoint(), size: availableSize))
@ -1382,18 +1384,18 @@ private final class GiftSetupScreenComponent: Component {
let resaleSectionSize = self.resaleSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
theme: theme,
style: .glass,
header: nil,
footer: nil,
items: [
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(
MultilineTextComponent(
text: .plain(NSAttributedString(string: environment.strings.Gift_Send_AvailableForResale, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor))
text: .plain(NSAttributedString(string: environment.strings.Gift_Send_AvailableForResale, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: theme.list.itemPrimaryTextColor))
)
)),
], alignment: .left, spacing: 2.0)),
@ -1401,7 +1403,7 @@ private final class GiftSetupScreenComponent: Component {
text: .plain(NSAttributedString(
string: presentationStringsFormattedNumber(Int32(availability.resale), environment.dateTimeFormat.groupingSeparator),
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemSecondaryTextColor
textColor: theme.list.itemSecondaryTextColor
)),
maximumNumberOfLines: 0
))), insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 16.0))),
@ -1444,7 +1446,7 @@ private final class GiftSetupScreenComponent: Component {
let starsFooterText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString(starsFooterRawString, attributes: footerAttributes))
if self.cachedChevronImage == nil || self.cachedChevronImage?.1 !== environment.theme {
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: environment.theme.list.itemAccentColor)!, environment.theme)
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: theme.list.itemAccentColor)!, environment.theme)
}
if let range = starsFooterText.string.range(of: "#") {
starsFooterText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: starsFooterText.string))
@ -1454,7 +1456,7 @@ private final class GiftSetupScreenComponent: Component {
}
let priceString = presentationStringsFormattedNumber(Int32(starsPrice), environment.dateTimeFormat.groupingSeparator)
let starsAttributedText = NSMutableAttributedString(string: environment.strings.Gift_Send_PayWithStars("#\(priceString)").string, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor)
let starsAttributedText = NSMutableAttributedString(string: environment.strings.Gift_Send_PayWithStars("#\(priceString)").string, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: theme.list.itemPrimaryTextColor)
let range = (starsAttributedText.string as NSString).range(of: "#")
if range.location != NSNotFound {
starsAttributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: range)
@ -1464,7 +1466,7 @@ private final class GiftSetupScreenComponent: Component {
let starsSectionSize = self.starsSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
theme: theme,
style: .glass,
header: nil,
footer: AnyComponent(MultilineTextWithEntitiesComponent(
@ -1474,7 +1476,7 @@ private final class GiftSetupScreenComponent: Component {
placeholderColor: .clear,
text: .plain(starsFooterText),
maximumNumberOfLines: 0,
highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.1),
highlightColor: theme.list.itemAccentColor.withAlphaComponent(0.1),
highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0),
highlightAction: { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
@ -1500,7 +1502,7 @@ private final class GiftSetupScreenComponent: Component {
)),
items: [
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(
@ -1508,7 +1510,7 @@ private final class GiftSetupScreenComponent: Component {
context: component.context,
animationCache: component.context.animationCache,
animationRenderer: component.context.animationRenderer,
placeholderColor: environment.theme.list.mediaPlaceholderColor,
placeholderColor: theme.list.mediaPlaceholderColor,
text: .plain(starsAttributedText)
)
)),
@ -1554,13 +1556,13 @@ private final class GiftSetupScreenComponent: Component {
let upgradeFooterText = NSMutableAttributedString(attributedString: parsedString)
if self.cachedChevronImage == nil || self.cachedChevronImage?.1 !== environment.theme {
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: environment.theme.list.itemAccentColor)!, environment.theme)
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: theme.list.itemAccentColor)!, environment.theme)
}
if let range = upgradeFooterText.string.range(of: ">"), let chevronImage = self.cachedChevronImage?.0 {
upgradeFooterText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: upgradeFooterText.string))
}
let upgradeAttributedText = NSMutableAttributedString(string: environment.strings.Gift_Send_Upgrade("#\(upgradeStars)").string, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor)
let upgradeAttributedText = NSMutableAttributedString(string: environment.strings.Gift_Send_Upgrade("#\(upgradeStars)").string, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: theme.list.itemPrimaryTextColor)
let range = (upgradeAttributedText.string as NSString).range(of: "#")
if range.location != NSNotFound {
upgradeAttributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: range)
@ -1570,13 +1572,13 @@ private final class GiftSetupScreenComponent: Component {
let upgradeSectionSize = self.upgradeSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
theme: theme,
style: .glass,
header: nil,
footer: AnyComponent(MultilineTextComponent(
text: .plain(upgradeFooterText),
maximumNumberOfLines: 0,
highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.1),
highlightColor: theme.list.itemAccentColor.withAlphaComponent(0.1),
highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0),
highlightAction: { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
@ -1605,7 +1607,7 @@ private final class GiftSetupScreenComponent: Component {
)),
items: [
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(
@ -1613,7 +1615,7 @@ private final class GiftSetupScreenComponent: Component {
context: component.context,
animationCache: component.context.animationCache,
animationRenderer: component.context.animationRenderer,
placeholderColor: environment.theme.list.mediaPlaceholderColor,
placeholderColor: theme.list.mediaPlaceholderColor,
text: .plain(upgradeAttributedText)
)
)),
@ -1654,27 +1656,27 @@ private final class GiftSetupScreenComponent: Component {
let hideSectionSize = self.hideSection.update(
transition: transition,
component: AnyComponent(ListSectionComponent(
theme: environment.theme,
theme: theme,
style: .glass,
header: nil,
footer: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: hideSectionFooterString,
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
textColor: environment.theme.list.freeTextColor
textColor: theme.list.freeTextColor
)),
maximumNumberOfLines: 0
)),
items: [
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
theme: environment.theme,
theme: theme,
style: .glass,
title: AnyComponent(VStack([
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(
string: isSelfGift ? environment.strings.Gift_SendSelf_HideMyName : environment.strings.Gift_Send_HideMyName,
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
textColor: environment.theme.list.itemPrimaryTextColor
textColor: theme.list.itemPrimaryTextColor
)),
maximumNumberOfLines: 1
))),
@ -1708,18 +1710,26 @@ private final class GiftSetupScreenComponent: Component {
contentHeight -= 77.0
contentHeight += 16.0
let remains: Int32 = availability.remains
var remains: Int32 = availability.remains
if let auctionState = self.giftAuctionState {
switch auctionState.auctionState {
case let .ongoing(_, _, _, _, _, _, _, giftsLeft, _, _):
remains = giftsLeft
case .finished:
remains = 0
}
}
let total: Int32 = availability.total
let position = CGFloat(remains) / CGFloat(total)
let sold = total - remains
let remainingCountSize = self.remainingCount.update(
transition: transition,
component: AnyComponent(RemainingCountComponent(
inactiveColor: environment.theme.list.itemBlocksBackgroundColor,
inactiveColor: theme.list.itemBlocksBackgroundColor,
activeColors: [UIColor(rgb: 0x72d6ff), UIColor(rgb: 0x32a0f9)],
inactiveTitle: environment.strings.Gift_Send_Remains(remains),
inactiveValue: "",
inactiveTitleColor: environment.theme.list.itemSecondaryTextColor,
inactiveTitleColor: theme.list.itemSecondaryTextColor,
activeTitle: "",
activeValue: environment.strings.Gift_Send_Sold(sold),
activeTitleColor: .white,
@ -1748,7 +1758,7 @@ private final class GiftSetupScreenComponent: Component {
let auctionFooterText = NSMutableAttributedString(attributedString: parsedString)
if self.cachedChevronImage == nil || self.cachedChevronImage?.1 !== environment.theme {
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: environment.theme.list.itemAccentColor)!, environment.theme)
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: theme.list.itemAccentColor)!, environment.theme)
}
if let range = auctionFooterText.string.range(of: ">"), let chevronImage = self.cachedChevronImage?.0 {
auctionFooterText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: auctionFooterText.string))
@ -1759,7 +1769,7 @@ private final class GiftSetupScreenComponent: Component {
component: AnyComponent(MultilineTextComponent(
text: .plain(auctionFooterText),
maximumNumberOfLines: 0,
highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.1),
highlightColor: theme.list.itemAccentColor.withAlphaComponent(0.1),
highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0),
highlightAction: { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
@ -1824,7 +1834,7 @@ private final class GiftSetupScreenComponent: Component {
var buttonTitleItems: [AnyComponentWithIdentity<Empty>] = []
if let _ = self.giftAuction {
let buttonAttributedString = NSMutableAttributedString(string: environment.strings.Gift_Setup_PlaceBid, font: Font.semibold(17.0), textColor: environment.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
let buttonAttributedString = NSMutableAttributedString(string: environment.strings.Gift_Setup_PlaceBid, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
buttonTitleItems.append(AnyComponentWithIdentity(id: "bid", component: AnyComponent(
MultilineTextComponent(text: .plain(buttonAttributedString))
)))
@ -1880,10 +1890,10 @@ private final class GiftSetupScreenComponent: Component {
}
}
} else {
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: environment.theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
let buttonAttributedString = NSMutableAttributedString(string: buttonString, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
if let range = buttonAttributedString.string.range(of: "#"), let starImage = self.cachedStarImage?.0 {
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
buttonAttributedString.addAttribute(.foregroundColor, value: environment.theme.list.itemCheckColors.foregroundColor, range: NSRange(range, in: buttonAttributedString.string))
buttonAttributedString.addAttribute(.foregroundColor, value: theme.list.itemCheckColors.foregroundColor, range: NSRange(range, in: buttonAttributedString.string))
buttonAttributedString.addAttribute(.baselineOffset, value: 1.5, range: NSRange(range, in: buttonAttributedString.string))
buttonAttributedString.addAttribute(.kern, value: 2.0, range: NSRange(range, in: buttonAttributedString.string))
}
@ -1900,9 +1910,9 @@ private final class GiftSetupScreenComponent: Component {
component: AnyComponent(ButtonComponent(
background: ButtonComponent.Background(
style: .glass,
color: environment.theme.list.itemCheckColors.fillColor,
foreground: environment.theme.list.itemCheckColors.foregroundColor,
pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9),
color: theme.list.itemCheckColors.fillColor,
foreground: theme.list.itemCheckColors.foregroundColor,
pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9),
isShimmering: true
),
content: AnyComponentWithIdentity(
@ -1923,7 +1933,7 @@ private final class GiftSetupScreenComponent: Component {
let bottomEdgeEffectHeight: CGFloat = bottomPanelHeight
let bottomEdgeEffectFrame = CGRect(origin: CGPoint(x: rawSideInset, y: availableSize.height - bottomEdgeEffectHeight), size: CGSize(width: fillingSize, height: bottomEdgeEffectHeight))
transition.setFrame(view: self.bottomEdgeEffectView, frame: bottomEdgeEffectFrame)
self.bottomEdgeEffectView.update(content: environment.theme.actionSheet.opaqueItemBackgroundColor, blur: true, alpha: 1.0, rect: bottomEdgeEffectFrame, edge: .bottom, edgeSize: bottomEdgeEffectFrame.height, transition: transition)
self.bottomEdgeEffectView.update(content: theme.list.blocksBackgroundColor, blur: true, alpha: 1.0, rect: bottomEdgeEffectFrame, edge: .bottom, edgeSize: bottomEdgeEffectFrame.height, transition: transition)
if self.bottomEdgeEffectView.superview == nil {
self.containerView.addSubview(self.bottomEdgeEffectView)
}
@ -2024,7 +2034,7 @@ public class GiftSetupScreen: ViewControllerComponentContainer {
context: AccountContext,
peerId: EnginePeer.Id,
subject: Subject,
auctionAcquiredGifts: [GiftAuctionAcquiredGift]? = nil,
auctionAcquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>? = nil,
completion: (() -> Void)? = nil
) {
self.context = context

View file

@ -681,7 +681,7 @@ private final class PeerComponent: Component {
}
if let icon = self.amountStar.image {
self.amountStar.frame = CGRect(origin: CGPoint(x: amountFrame.minX - icon.size.width, y: floorToScreenPixels((size.height - icon.size.height) / 2.0) - UIScreenPixel), size: icon.size)
self.amountStar.frame = CGRect(origin: CGPoint(x: amountFrame.minX - icon.size.width - 2.0, y: floorToScreenPixels((size.height - icon.size.height) / 2.0) - UIScreenPixel), size: icon.size)
}
self.separator.backgroundColor = component.theme.list.itemPlainSeparatorColor.cgColor
@ -957,7 +957,7 @@ private final class GiftAuctionBidScreenComponent: Component {
let hideName: Bool
let gift: StarGift
let auctionContext: GiftAuctionContext
let acquiredGifts: [GiftAuctionAcquiredGift]?
let acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?
init(
context: AccountContext,
@ -967,7 +967,7 @@ private final class GiftAuctionBidScreenComponent: Component {
hideName: Bool,
gift: StarGift,
auctionContext: GiftAuctionContext,
acquiredGifts: [GiftAuctionAcquiredGift]?
acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?
) {
self.context = context
self.toPeerId = toPeerId
@ -1332,13 +1332,7 @@ private final class GiftAuctionBidScreenComponent: Component {
guard let self else {
return
}
let previous = self.giftAuctionAcquiredGifts
self.giftAuctionAcquiredGifts = acquiredGifts
if let previous, previous.count < acquiredGifts.count {
self.resetSliderValue()
self.addSubview(ConfettiView(frame: self.bounds))
}
self.state?.updated(transition: .easeInOut(duration: 0.25))
}))
}
@ -1928,8 +1922,6 @@ private final class GiftAuctionBidScreenComponent: Component {
}
if self.component == nil {
self.giftAuctionAcquiredGifts = component.acquiredGifts
if let starsContext = component.context.starsContext {
self.balanceDisposable = (starsContext.state
|> deliverOnMainQueue).startStrict(next: { [weak self] state in
@ -1963,6 +1955,18 @@ private final class GiftAuctionBidScreenComponent: Component {
peerIds.append(context.account.peerId)
self.resetSliderValue(component: component)
transition = .immediate
if let acquiredGifts = component.acquiredGifts {
self.giftAuctionAcquiredGiftsDisposable.set((acquiredGifts
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] acquiredGifts in
self?.giftAuctionAcquiredGifts = acquiredGifts
}))
} else if let acquiredCount = auctionState?.myState.acquiredCount, acquiredCount > 0 {
Queue.mainQueue().justDispatch {
self.loadAcquiredGifts()
}
}
}
if !peerIds.isEmpty {
@ -1987,16 +1991,14 @@ private final class GiftAuctionBidScreenComponent: Component {
}
self.state?.updated(transition: transition)
let previousAcquiredCount: Int32
if let previousState {
previousAcquiredCount = previousState.myState.acquiredCount
} else {
previousAcquiredCount = Int32(component.acquiredGifts?.count ?? 0)
}
if let acquiredCount = auctionState?.myState.acquiredCount, acquiredCount > previousAcquiredCount {
if let acquiredCount = auctionState?.myState.acquiredCount, let previousAcquiredCount = previousState?.myState.acquiredCount, acquiredCount > previousAcquiredCount {
Queue.mainQueue().justDispatch {
self.loadAcquiredGifts()
}
if !isFirstTime {
self.resetSliderValue()
self.addSubview(ConfettiView(frame: self.bounds))
}
}
if case .finished = auctionState?.auctionState, let controller = self.environment?.controller() {
@ -2299,7 +2301,7 @@ private final class GiftAuctionBidScreenComponent: Component {
break
}
}
topBidsComponents.append((peer.id, AnyComponent(PeerComponent(context: component.context, theme: environment.theme, groupingSeparator: environment.dateTimeFormat.groupingSeparator, peer: peer, place: i, amount: bid, isLast: i == topBidders.count, action: peer.id != component.context.account.peerId ? { [weak self] in self?.openPeer(peer, dismiss: false) } : nil))))
topBidsComponents.append((peer.id, AnyComponent(PeerComponent(context: component.context, theme: environment.theme, groupingSeparator: environment.dateTimeFormat.groupingSeparator, peer: peer, place: i, amount: bid, isLast: i == topBidders.count, action: nil))))
i += 1
}
@ -2312,7 +2314,6 @@ private final class GiftAuctionBidScreenComponent: Component {
var perks: [([AnimatedTextComponent.Item], String)] = []
var minBidIsSmall = false
var minBidAnimatedItems: [AnimatedTextComponent.Item] = []
var untilNextDropAnimatedItems: [AnimatedTextComponent.Item] = []
var dropsLeftAnimatedItems: [AnimatedTextComponent.Item] = []
@ -2323,11 +2324,13 @@ private final class GiftAuctionBidScreenComponent: Component {
if let myMinBidAmmount = self.giftAuctionState?.myState.minBidAmount {
minBidAmount = myMinBidAmmount
}
var minBidString = "# \(presentationStringsFormattedNumber(Int32(clamping: minBidAmount), environment.dateTimeFormat.groupingSeparator))"
if minBidAmount > 999999 {
minBidString = "# \(minBidAmount)"
minBidIsSmall = true
var minBidString: String
if minBidAmount > 99999 {
minBidString = compactNumericCountString(Int(minBidAmount), decimalSeparator: environment.dateTimeFormat.decimalSeparator, showDecimalPart: false)
} else {
minBidString = presentationStringsFormattedNumber(Int32(clamping: minBidAmount), environment.dateTimeFormat.groupingSeparator)
}
minBidString = "# \(minBidString)"
if let hashIndex = minBidString.firstIndex(of: "#") {
var prefix = String(minBidString[..<hashIndex])
if !prefix.isEmpty {
@ -2442,7 +2445,7 @@ private final class GiftAuctionBidScreenComponent: Component {
gift: i == perks.count - 1 ? component.auctionContext.gift : nil,
title: perk.0,
subtitle: perk.1,
small: i == 0 && minBidIsSmall,
small: false,
theme: environment.theme
)),
environment: {},
@ -2941,7 +2944,7 @@ public class GiftAuctionBidScreen: ViewControllerComponentContainer {
private var didPlayAppearAnimation: Bool = false
private var isDismissed: Bool = false
public init(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: [GiftAuctionAcquiredGift]?) {
public init(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?) {
self.context = context
super.init(context: context, component: GiftAuctionBidScreenComponent(

View file

@ -69,6 +69,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
private var giftAuctionTimer: SwiftSignalKit.Timer?
fileprivate var giftAuctionAcquiredGifts: [GiftAuctionAcquiredGift] = []
private var giftAuctionAcquiredGiftsPromise = ValuePromise<[GiftAuctionAcquiredGift]>()
private var giftAuctionAcquiredGiftsDisposable = MetaDisposable()
var cachedStarImage: (UIImage, PresentationTheme)?
@ -122,6 +123,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
return
}
self.giftAuctionAcquiredGifts = acquiredGifts
self.giftAuctionAcquiredGiftsPromise.set(acquiredGifts)
self.updated(transition: .easeInOut(duration: 0.25))
}))
}
@ -169,7 +171,7 @@ private final class GiftAuctionViewSheetContent: CombinedComponent {
}
self.dismiss(animated: true)
controller.completion(self.giftAuctionAcquiredGifts)
controller.completion(self.giftAuctionAcquiredGiftsPromise.get())
}
func openPeer(_ peer: EnginePeer, dismiss: Bool = true) {
@ -975,12 +977,12 @@ final class GiftAuctionViewSheetComponent: CombinedComponent {
}
public final class GiftAuctionViewScreen: ViewControllerComponentContainer {
fileprivate let completion: ([GiftAuctionAcquiredGift]?) -> Void
fileprivate let completion: (Signal<[GiftAuctionAcquiredGift], NoError>) -> Void
public init(
context: AccountContext,
auctionContext: GiftAuctionContext,
completion: @escaping ([GiftAuctionAcquiredGift]?) -> Void
completion: @escaping (Signal<[GiftAuctionAcquiredGift], NoError>) -> Void
) {
self.completion = completion

View file

@ -101,6 +101,13 @@ public extension ShareWithPeersScreen {
switch subject {
case let .peers(peers, _):
let peers = peers.filter { peer in
if liveStream, case let .channel(channel) = peer, case .group = channel.info {
return false
} else {
return true
}
}
self.stateDisposable = (.single(peers)
|> mapToSignal { peers -> Signal<([EnginePeer], [EnginePeer.Id: Optional<Int>]), NoError> in
return context.engine.data.subscribe(

View file

@ -3846,11 +3846,11 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return GiftAuctionInfoScreen(context: context, auctionContext: auctionContext, completion: completion)
}
public func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: [GiftAuctionAcquiredGift]?) -> ViewController {
public func makeGiftAuctionBidScreen(context: AccountContext, toPeerId: EnginePeer.Id, text: String?, entities: [MessageTextEntity]?, hideName: Bool, auctionContext: GiftAuctionContext, acquiredGifts: Signal<[GiftAuctionAcquiredGift], NoError>?) -> ViewController {
return GiftAuctionBidScreen(context: context, toPeerId: toPeerId, text: text, entities: entities, hideName: hideName, auctionContext: auctionContext, acquiredGifts: acquiredGifts)
}
public func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: @escaping ([GiftAuctionAcquiredGift]?) -> Void) -> ViewController {
public func makeGiftAuctionViewScreen(context: AccountContext, auctionContext: GiftAuctionContext, completion: @escaping (Signal<[GiftAuctionAcquiredGift], NoError>) -> Void) -> ViewController {
return GiftAuctionViewScreen(context: context, auctionContext: auctionContext, completion: completion)
}