Various fixes

This commit is contained in:
Ilya Laktyushin 2025-03-07 21:58:30 +04:00
parent f75bea1002
commit edecdd7fec
24 changed files with 181 additions and 94 deletions

View File

@ -351,7 +351,7 @@ public final class AuthorizationSequenceController: NavigationController, ASAuth
|> deliverOnMainQueue).startStrict(error: { [weak self] error in |> deliverOnMainQueue).startStrict(error: { [weak self] error in
if let self, case .alreadyInProgress = error { if let self, case .alreadyInProgress = error {
let formattedNumber = formatPhoneNumber(number) let formattedNumber = formatPhoneNumber(number)
let title = NSAttributedString(string: self.presentationData.strings.Login_Email_PremiumRequiredTitle, font: Font.semibold(self.presentationData.listsFontSize.baseDisplaySize), textColor: self.presentationData.theme.actionSheet.primaryTextColor) let title = NSAttributedString(string: self.presentationData.strings.Login_Email_PremiumRequiredTitle, font: Font.semibold(self.presentationData.listsFontSize.baseDisplaySize), textColor: self.presentationData.theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
let text = parseMarkdownIntoAttributedString(self.presentationData.strings.Login_Email_PremiumRequiredText(formattedNumber).string, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center).mutableCopy() as! NSMutableAttributedString let text = parseMarkdownIntoAttributedString(self.presentationData.strings.Login_Email_PremiumRequiredText(formattedNumber).string, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center).mutableCopy() as! NSMutableAttributedString
let alertController = textWithEntitiesAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: title, text: text, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_OK, action: { })]) let alertController = textWithEntitiesAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: title, text: text, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_OK, action: { })])

View File

@ -1722,10 +1722,10 @@ function tgBrowserHandleMutations(mutations) {
if (mutation.addedNodes && mutation.addedNodes.length > 0) { if (mutation.addedNodes && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((newNode) => { mutation.addedNodes.forEach((newNode) => {
if (newNode.tagName === 'VIDEO') { if (newNode.tagName === 'VIDEO') {
disableWebkitEnterFullscreen(newNode); tgBrowserDisableWebkitEnterFullscreen(newNode);
} }
if (newNode.querySelectorAll) { if (newNode.querySelectorAll) {
newNode.querySelectorAll('video').forEach(disableWebkitEnterFullscreen); newNode.querySelectorAll('video').forEach(tgBrowserDisableWebkitEnterFullscreen);
} }
}); });
} }

View File

@ -37,10 +37,10 @@ private final class ChannelPermissionsControllerArguments {
let openChannelExample: () -> Void let openChannelExample: () -> Void
let updateSlowmode: (Int32) -> Void let updateSlowmode: (Int32) -> Void
let updateUnrestrictBoosters: (Int32) -> Void let updateUnrestrictBoosters: (Int32) -> Void
let updateStarsAmount: (StarsAmount?) -> Void let updateStarsAmount: (StarsAmount?, Bool) -> Void
let toggleIsOptionExpanded: (TelegramChatBannedRightsFlags) -> Void let toggleIsOptionExpanded: (TelegramChatBannedRightsFlags) -> Void
init(context: AccountContext, updatePermission: @escaping (TelegramChatBannedRightsFlags, Bool) -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, addPeer: @escaping () -> Void, removePeer: @escaping (EnginePeer.Id) -> Void, openPeer: @escaping (ChannelParticipant) -> Void, openPeerInfo: @escaping (EnginePeer) -> Void, openKicked: @escaping () -> Void, presentRestrictedPermissionAlert: @escaping (TelegramChatBannedRightsFlags) -> Void, presentConversionToBroadcastGroup: @escaping () -> Void, openChannelExample: @escaping () -> Void, updateSlowmode: @escaping (Int32) -> Void, updateUnrestrictBoosters: @escaping (Int32) -> Void, updateStarsAmount: @escaping (StarsAmount?) -> Void, toggleIsOptionExpanded: @escaping (TelegramChatBannedRightsFlags) -> Void) { init(context: AccountContext, updatePermission: @escaping (TelegramChatBannedRightsFlags, Bool) -> Void, setPeerIdWithRevealedOptions: @escaping (EnginePeer.Id?, EnginePeer.Id?) -> Void, addPeer: @escaping () -> Void, removePeer: @escaping (EnginePeer.Id) -> Void, openPeer: @escaping (ChannelParticipant) -> Void, openPeerInfo: @escaping (EnginePeer) -> Void, openKicked: @escaping () -> Void, presentRestrictedPermissionAlert: @escaping (TelegramChatBannedRightsFlags) -> Void, presentConversionToBroadcastGroup: @escaping () -> Void, openChannelExample: @escaping () -> Void, updateSlowmode: @escaping (Int32) -> Void, updateUnrestrictBoosters: @escaping (Int32) -> Void, updateStarsAmount: @escaping (StarsAmount?, Bool) -> Void, toggleIsOptionExpanded: @escaping (TelegramChatBannedRightsFlags) -> Void) {
self.context = context self.context = context
self.updatePermission = updatePermission self.updatePermission = updatePermission
self.addPeer = addPeer self.addPeer = addPeer
@ -418,15 +418,15 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
} }
case let .chargeForMessages(_, title, value): case let .chargeForMessages(_, title, value):
return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { value in return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, sectionId: self.section, style: .blocks, updated: { value in
arguments.updateStarsAmount(value ? StarsAmount(value: 400, nanos: 0) : nil) arguments.updateStarsAmount(value ? StarsAmount(value: 400, nanos: 0) : nil, true)
}) })
case let .chargeForMessagesInfo(_, value): case let .chargeForMessagesInfo(_, value):
return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section) return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section)
case let .messagePriceHeader(_, value): case let .messagePriceHeader(_, value):
return ItemListSectionHeaderItem(presentationData: presentationData, text: value, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: value, sectionId: self.section)
case let .messagePrice(_, value, maxValue, price): case let .messagePrice(_, value, maxValue, price):
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: true, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value in return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: true, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value, apply in
arguments.updateStarsAmount(StarsAmount(value: value, nanos: 0)) arguments.updateStarsAmount(StarsAmount(value: value, nanos: 0), apply)
}) })
case let .messagePriceInfo(_, value): case let .messagePriceInfo(_, value):
return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section) return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section)
@ -1248,23 +1248,25 @@ public func channelPermissionsController(context: AccountContext, updatedPresent
updateUnrestrictBoostersDisposable.set((context.engine.peers.updateChannelBoostsToUnlockRestrictions(peerId: view.peerId, boosts: value) updateUnrestrictBoostersDisposable.set((context.engine.peers.updateChannelBoostsToUnlockRestrictions(peerId: view.peerId, boosts: value)
|> deliverOnMainQueue).start()) |> deliverOnMainQueue).start())
}) })
}, updateStarsAmount: { value in }, updateStarsAmount: { value, apply in
updateState { state in updateState { state in
var state = state var state = state
state.modifiedStarsAmount = value state.modifiedStarsAmount = value
return state return state
} }
let _ = (peerView.get() if apply {
|> take(1) let _ = (peerView.get()
|> deliverOnMainQueue).start(next: { view in |> take(1)
var effectiveValue = value |> deliverOnMainQueue).start(next: { view in
if value?.value == 0 { var effectiveValue = value
effectiveValue = nil if value?.value == 0 {
} effectiveValue = nil
updateSendPaidMessageStarsDisposable.set((context.engine.peers.updateChannelPaidMessagesStars(peerId: view.peerId, stars: effectiveValue) }
|> deliverOnMainQueue).start()) updateSendPaidMessageStarsDisposable.set((context.engine.peers.updateChannelPaidMessagesStars(peerId: view.peerId, stars: effectiveValue)
}) |> deliverOnMainQueue).start())
})
}
}, toggleIsOptionExpanded: { flags in }, toggleIsOptionExpanded: { flags in
updateState { state in updateState { state in
var state = state var state = state

View File

@ -149,7 +149,7 @@ private enum GlobalAutoremoveEntry: ItemListNodeEntry {
case .priceHeader: case .priceHeader:
return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.Privacy_Messages_MessagePrice, sectionId: self.section) return ItemListSectionHeaderItem(presentationData: presentationData, text: presentationData.strings.Privacy_Messages_MessagePrice, sectionId: self.section)
case let .price(value, maxValue, price, isEnabled): case let .price(value, maxValue, price, isEnabled):
return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: isEnabled, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value in return MessagePriceItem(theme: presentationData.theme, strings: presentationData.strings, isEnabled: isEnabled, minValue: 1, maxValue: maxValue, value: value, price: price, sectionId: self.section, updated: { value, _ in
arguments.updateValue(.paidMessages(StarsAmount(value: value, nanos: 0))) arguments.updateValue(.paidMessages(StarsAmount(value: value, nanos: 0)))
}, openPremiumInfo: { }, openPremiumInfo: {
arguments.openPremiumInfo() arguments.openPremiumInfo()

View File

@ -1016,7 +1016,10 @@ private final class ProfileGiftsContextImpl {
let sorting = self.sorting let sorting = self.sorting
let isFiltered = self.filter != .All || self.sorting != .date let isFiltered = self.filter != .All || self.sorting != .date
if !isFiltered {
self.filteredGifts = []
self.filteredCount = nil
}
let dataState = isFiltered ? self.filteredDataState : self.dataState let dataState = isFiltered ? self.filteredDataState : self.dataState
if case let .ready(true, initialNextOffset) = dataState { if case let .ready(true, initialNextOffset) = dataState {
@ -1202,7 +1205,6 @@ private final class ProfileGiftsContextImpl {
} }
} }
let existingGifts = Set(pinnedGifts.compactMap { $0.reference }) let existingGifts = Set(pinnedGifts.compactMap { $0.reference })
var updatedGifts: [ProfileGiftsContext.State.StarGift] = [] var updatedGifts: [ProfileGiftsContext.State.StarGift] = []
for gift in self.gifts { for gift in self.gifts {
if let reference = gift.reference, existingGifts.contains(reference) { if let reference = gift.reference, existingGifts.contains(reference) {
@ -1216,18 +1218,44 @@ private final class ProfileGiftsContextImpl {
updatedGifts.insert(contentsOf: pinnedGifts, at: 0) updatedGifts.insert(contentsOf: pinnedGifts, at: 0)
self.gifts = updatedGifts self.gifts = updatedGifts
if let index = self.filteredGifts.firstIndex(where: { $0.reference == reference }) { var effectiveReferences = pinnedGifts.compactMap { $0.reference }
self.filteredGifts[index] = self.filteredGifts[index].withPinnedToTop(pinnedToTop) if !self.filteredGifts.isEmpty {
var filteredPinnedGifts = self.filteredGifts.filter { $0.pinnedToTop }
if var gift = self.filteredGifts.first(where: { $0.reference == reference }) {
gift = gift.withPinnedToTop(pinnedToTop)
if pinnedToTop {
if !gift.savedToProfile {
gift = gift.withSavedToProfile(true)
}
filteredPinnedGifts.append(gift)
} else {
filteredPinnedGifts.removeAll(where: { $0.reference == reference })
}
}
let existingFilteredGifts = Set(filteredPinnedGifts.compactMap { $0.reference })
var updatedFilteredGifts: [ProfileGiftsContext.State.StarGift] = []
for gift in self.filteredGifts {
if let reference = gift.reference, existingFilteredGifts.contains(reference) {
continue
}
updatedFilteredGifts.append(gift)
}
updatedFilteredGifts.sort { lhs, rhs in
lhs.date > rhs.date
}
updatedFilteredGifts.insert(contentsOf: filteredPinnedGifts, at: 0)
self.filteredGifts = updatedFilteredGifts
effectiveReferences = filteredPinnedGifts.compactMap { $0.reference }
} }
self.pushState() self.pushState()
var signal = _internal_updateStarGiftsPinnedToTop(account: self.account, peerId: self.peerId, references: pinnedGifts.compactMap { $0.reference }) var signal = _internal_updateStarGiftsPinnedToTop(account: self.account, peerId: self.peerId, references: effectiveReferences)
if saveToProfile { if saveToProfile {
signal = _internal_updateStarGiftAddedToProfile(account: self.account, reference: reference, added: true) signal = _internal_updateStarGiftAddedToProfile(account: self.account, reference: reference, added: true)
|> then(signal) |> then(signal)
} }
self.actionDisposable.set( self.actionDisposable.set(
(signal |> deliverOn(self.queue)).startStrict(completed: { [weak self] in (signal |> deliverOn(self.queue)).startStrict(completed: { [weak self] in
self?.reload() self?.reload()
@ -1279,7 +1307,6 @@ private final class ProfileGiftsContextImpl {
|> ignoreValues |> ignoreValues
|> then(signal) |> then(signal)
} }
self.actionDisposable.set( self.actionDisposable.set(
(signal |> deliverOn(self.queue)).startStrict(completed: { [weak self] in (signal |> deliverOn(self.queue)).startStrict(completed: { [weak self] in
self?.reload() self?.reload()
@ -1349,6 +1376,9 @@ private final class ProfileGiftsContextImpl {
} }
func updateFilter(_ filter: ProfileGiftsContext.Filters) { func updateFilter(_ filter: ProfileGiftsContext.Filters) {
guard self.filter != filter else {
return
}
self.filter = filter self.filter = filter
self.filteredDataState = .ready(canLoadMore: true, nextOffset: nil) self.filteredDataState = .ready(canLoadMore: true, nextOffset: nil)
self.pushState() self.pushState()
@ -1357,6 +1387,9 @@ private final class ProfileGiftsContextImpl {
} }
func updateSorting(_ sorting: ProfileGiftsContext.Sorting) { func updateSorting(_ sorting: ProfileGiftsContext.Sorting) {
guard self.sorting != sorting else {
return
}
self.sorting = sorting self.sorting = sorting
self.filteredDataState = .ready(canLoadMore: true, nextOffset: nil) self.filteredDataState = .ready(canLoadMore: true, nextOffset: nil)
self.pushState() self.pushState()

View File

@ -1148,7 +1148,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, peerId, senderId, _): case let .starGiftUnique(gift, isUpgrade, _, _, _, _, _, peerId, senderId, _):
if case let .unique(gift) = gift { if case let .unique(gift) = gift {
if !forAdditionalServiceMessage && !"".isEmpty { if !forAdditionalServiceMessage && !"".isEmpty {
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor) attributedString = NSAttributedString(string: "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, dateTimeFormat.groupingSeparator))", font: titleFont, textColor: primaryTextColor)
} else if let messagePeer = message.peers[message.id.peerId] { } else if let messagePeer = message.peers[message.id.peerId] {
var peerName = EnginePeer(messagePeer).compactDisplayTitle var peerName = EnginePeer(messagePeer).compactDisplayTitle
var peerIds: [(Int, EnginePeer.Id?)] = [(0, messagePeer.id)] var peerIds: [(Int, EnginePeer.Id?)] = [(0, messagePeer.id)]

View File

@ -2968,7 +2968,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
} else { } else {
let contentProperties = contentPropertiesAndLayouts[i].3 let contentProperties = contentPropertiesAndLayouts[i].3
if i == 0 && !headerSize.height.isZero { if (i == 0 || (i == 1 && detachedContentNodesHeight > 0)) && !headerSize.height.isZero {
if contentGroupId == nil { if contentGroupId == nil {
contentNodesHeight += properties.headerSpacing contentNodesHeight += properties.headerSpacing
} }
@ -2981,7 +2981,15 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
if !contentContainerNodeFrames.isEmpty { if !contentContainerNodeFrames.isEmpty {
overlapOffset = currentContainerGroupOverlap overlapOffset = currentContainerGroupOverlap
} }
let containerFrame = CGRect(x: 0.0, y: headerSize.height + totalContentNodesHeight - contentNodesHeight - overlapOffset, width: maxContentWidth, height: contentNodesHeight) var containerContentNodesOrigin = contentNodesHeight
var containerContentNodesHeight = contentNodesHeight
if detachedContentNodesHeight > 0 {
if contentContainerNodeFrames.isEmpty {
containerContentNodesHeight -= detachedContentNodesHeight - 4.0
containerContentNodesOrigin -= detachedContentNodesHeight - 4.0
}
}
let containerFrame = CGRect(x: 0.0, y: headerSize.height + totalContentNodesHeight - containerContentNodesOrigin - overlapOffset, width: maxContentWidth, height: containerContentNodesHeight)
contentContainerNodeFrames.append((containerGroupId, containerFrame, currentItemSelection, currentContainerGroupOverlap)) contentContainerNodeFrames.append((containerGroupId, containerFrame, currentItemSelection, currentContainerGroupOverlap))
if !overlapOffset.isZero { if !overlapOffset.isZero {
@ -2997,7 +3005,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
} }
var contentNodeOriginY = contentNodesHeight var contentNodeOriginY = contentNodesHeight
if detachedContentNodesHeight > 0 { if detachedContentNodesHeight > 0, contentContainerNodeFrames.isEmpty {
contentNodeOriginY -= detachedContentNodesHeight - 4.0 contentNodeOriginY -= detachedContentNodesHeight - 4.0
} }
@ -3025,7 +3033,15 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
if !contentContainerNodeFrames.isEmpty { if !contentContainerNodeFrames.isEmpty {
overlapOffset = currentContainerGroupOverlap overlapOffset = currentContainerGroupOverlap
} }
contentContainerNodeFrames.append((containerGroupId, CGRect(x: 0.0, y: headerSize.height + totalContentNodesHeight - contentNodesHeight - overlapOffset, width: maxContentWidth, height: contentNodesHeight), currentItemSelection, currentContainerGroupOverlap)) var containerContentNodesOrigin = contentNodesHeight
var containerContentNodesHeight = contentNodesHeight
if detachedContentNodesHeight > 0 {
if contentContainerNodeFrames.isEmpty {
containerContentNodesHeight -= detachedContentNodesHeight - 4.0
containerContentNodesOrigin -= detachedContentNodesHeight - 4.0
}
}
contentContainerNodeFrames.append((containerGroupId, CGRect(x: 0.0, y: headerSize.height + totalContentNodesHeight - containerContentNodesOrigin - overlapOffset, width: maxContentWidth, height: containerContentNodesHeight), currentItemSelection, currentContainerGroupOverlap))
if !overlapOffset.isZero { if !overlapOffset.isZero {
totalContentNodesHeight -= currentContainerGroupOverlap totalContentNodesHeight -= currentContainerGroupOverlap
} }

View File

@ -213,7 +213,7 @@ public final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContent
} else { } else {
textLeftInset = 15.0 + imageSize * min(1.0, CGFloat(replyPeers.count)) + (imageSpacing) * max(0.0, min(2.0, CGFloat(replyPeers.count - 1))) textLeftInset = 15.0 + imageSize * min(1.0, CGFloat(replyPeers.count)) + (imageSpacing) * max(0.0, min(2.0, CGFloat(replyPeers.count - 1)))
} }
let textRightInset: CGFloat = 36.0 let textRightInset: CGFloat = 24.0
let textConstrainedSize = CGSize(width: min(maxTextWidth, constrainedSize.width - horizontalInset - textLeftInset - textRightInset), height: constrainedSize.height) let textConstrainedSize = CGSize(width: min(maxTextWidth, constrainedSize.width - horizontalInset - textLeftInset - textRightInset), height: constrainedSize.height)

View File

@ -354,8 +354,8 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
let attributedString = attributedServiceMessageString(theme: item.presentationData.theme, strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, message: EngineMessage(item.message), accountPeerId: item.context.account.peerId) let attributedString = attributedServiceMessageString(theme: item.presentationData.theme, strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, message: EngineMessage(item.message), accountPeerId: item.context.account.peerId)
let primaryTextColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText var primaryTextColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText
var months: Int32 = 3 var months: Int32 = 3
var animationName: String = "" var animationName: String = ""
var animationFile: TelegramMediaFile? var animationFile: TelegramMediaFile?
@ -582,7 +582,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
} else { } else {
title = isStoryEntity ? uniqueGift.title : item.presentationData.strings.Notification_StarGift_Title(authorName).string title = isStoryEntity ? uniqueGift.title : item.presentationData.strings.Notification_StarGift_Title(authorName).string
} }
text = isStoryEntity ? "**\(item.presentationData.strings.Notification_StarGift_Collectible) #\(uniqueGift.number)**" : "**\(uniqueGift.title) #\(uniqueGift.number)**" text = isStoryEntity ? "**\(item.presentationData.strings.Notification_StarGift_Collectible) #\(presentationStringsFormattedNumber(uniqueGift.number, item.presentationData.dateTimeFormat.groupingSeparator))**" : "**\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, item.presentationData.dateTimeFormat.groupingSeparator))**"
ribbonTitle = isStoryEntity ? "" : item.presentationData.strings.Notification_StarGift_Gift ribbonTitle = isStoryEntity ? "" : item.presentationData.strings.Notification_StarGift_Gift
buttonTitle = isStoryEntity ? "" : item.presentationData.strings.Notification_StarGift_View buttonTitle = isStoryEntity ? "" : item.presentationData.strings.Notification_StarGift_View
modelTitle = item.presentationData.strings.Notification_StarGift_Model modelTitle = item.presentationData.strings.Notification_StarGift_Model
@ -599,6 +599,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
uniqueSecondBackgroundColor = UIColor(rgb: UInt32(bitPattern: innerColor)) uniqueSecondBackgroundColor = UIColor(rgb: UInt32(bitPattern: innerColor))
uniquePatternColor = UIColor(rgb: UInt32(bitPattern: patternColor)) uniquePatternColor = UIColor(rgb: UInt32(bitPattern: patternColor))
backdropValue = name backdropValue = name
primaryTextColor = UIColor(rgb: 0xffffff)
subtitleColor = UIColor(rgb: UInt32(bitPattern: innerColor)).withMultiplied(hue: 1.0, saturation: 1.02, brightness: 1.25).mixedWith(UIColor.white, alpha: 0.3) subtitleColor = UIColor(rgb: UInt32(bitPattern: innerColor)).withMultiplied(hue: 1.0, saturation: 1.02, brightness: 1.25).mixedWith(UIColor.white, alpha: 0.3)
case let .pattern(name, file, _): case let .pattern(name, file, _):
symbolValue = name symbolValue = name

View File

@ -1441,14 +1441,31 @@ private final class ChatSendStarsScreenComponent: Component {
} }
let sideInset: CGFloat = floor((availableSize.width - fillingSize) * 0.5) + 16.0 let sideInset: CGFloat = floor((availableSize.width - fillingSize) * 0.5) + 16.0
let context = component.context
let balanceSize = self.balanceOverlay.update( let balanceSize = self.balanceOverlay.update(
transition: .immediate, transition: .immediate,
component: AnyComponent( component: AnyComponent(
StarsBalanceOverlayComponent( StarsBalanceOverlayComponent(
context: component.context, context: component.context,
theme: environment.theme, theme: environment.theme,
action: { action: { [weak self] in
guard let self, let starsContext = context.starsContext, let navigationController = self.environment?.controller()?.navigationController as? NavigationController else {
return
}
self.environment?.controller()?.dismiss()
let _ = (context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { options in
let controller = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options,
purpose: .generic,
completion: { _ in }
)
navigationController.pushViewController(controller)
})
} }
) )
), ),

View File

@ -259,10 +259,10 @@ public func giftTransferAlertController(context: AccountContext, gift: StarGift.
let text: String let text: String
let buttonText: String let buttonText: String
if transferStars > 0 { if transferStars > 0 {
text = strings.Gift_Transfer_Confirmation_Text("\(gift.title) #\(gift.number)", peer.displayTitle(strings: strings, displayOrder: presentationData.nameDisplayOrder), strings.Gift_Transfer_Confirmation_Text_Stars(Int32(transferStars))).string text = strings.Gift_Transfer_Confirmation_Text("\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))", peer.displayTitle(strings: strings, displayOrder: presentationData.nameDisplayOrder), strings.Gift_Transfer_Confirmation_Text_Stars(Int32(transferStars))).string
buttonText = "\(strings.Gift_Transfer_Confirmation_Transfer) $ \(transferStars)" buttonText = "\(strings.Gift_Transfer_Confirmation_Transfer) $ \(transferStars)"
} else { } else {
text = strings.Gift_Transfer_Confirmation_TextFree("\(gift.title) #\(gift.number)", peer.displayTitle(strings: strings, displayOrder: presentationData.nameDisplayOrder)).string text = strings.Gift_Transfer_Confirmation_TextFree("\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))", peer.displayTitle(strings: strings, displayOrder: presentationData.nameDisplayOrder)).string
buttonText = strings.Gift_Transfer_Confirmation_TransferFree buttonText = strings.Gift_Transfer_Confirmation_TransferFree
} }

View File

@ -635,7 +635,8 @@ private final class GiftViewSheetContent: CombinedComponent {
if case .wearPreview = component.subject { if case .wearPreview = component.subject {
giftTitle = uniqueGift.title giftTitle = uniqueGift.title
} else { } else {
giftTitle = "\(uniqueGift.title) #\(uniqueGift.number)"
giftTitle = "\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))"
} }
let wearTitle = wearTitle.update( let wearTitle = wearTitle.update(
@ -1018,7 +1019,7 @@ private final class GiftViewSheetContent: CombinedComponent {
var descriptionText: String var descriptionText: String
if let uniqueGift { if let uniqueGift {
titleString = uniqueGift.title titleString = uniqueGift.title
descriptionText = "\(strings.Gift_Unique_Collectible) #\(uniqueGift.number)" descriptionText = "\(strings.Gift_Unique_Collectible) #\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))"
} else if soldOut { } else if soldOut {
descriptionText = strings.Gift_View_UnavailableDescription descriptionText = strings.Gift_View_UnavailableDescription
} else if upgraded { } else if upgraded {
@ -1480,7 +1481,7 @@ private final class GiftViewSheetContent: CombinedComponent {
if isWearing { if isWearing {
state.commitTakeOff() state.commitTakeOff()
component.showAttributeInfo(statusTag, strings.Gift_View_TookOff("\(uniqueGift.title) #\(uniqueGift.number)").string) component.showAttributeInfo(statusTag, strings.Gift_View_TookOff("\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))").string)
} else { } else {
if let controller = controller() as? GiftViewScreen { if let controller = controller() as? GiftViewScreen {
controller.dismissAllTooltips() controller.dismissAllTooltips()
@ -1507,7 +1508,7 @@ private final class GiftViewSheetContent: CombinedComponent {
state.requestWearPreview() state.requestWearPreview()
} else { } else {
state.commitWear(uniqueGift) state.commitWear(uniqueGift)
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string) component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))").string)
} }
}) })
} }
@ -2090,7 +2091,7 @@ private final class GiftViewSheetContent: CombinedComponent {
component.cancel(true) component.cancel(true)
} else { } else {
Queue.mainQueue().after(0.2) { Queue.mainQueue().after(0.2) {
component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(uniqueGift.number)").string) component.showAttributeInfo(statusTag, strings.Gift_View_PutOn("\(uniqueGift.title) #\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))").string)
} }
} }
} }
@ -3091,15 +3092,32 @@ public class GiftViewScreen: ViewControllerComponentContainer {
super.containerLayoutUpdated(layout, transition: transition) super.containerLayoutUpdated(layout, transition: transition)
if self.showBalance { if self.showBalance {
let context = self.context
let insets = layout.insets(options: .statusBar) let insets = layout.insets(options: .statusBar)
let balanceSize = self.balanceOverlay.update( let balanceSize = self.balanceOverlay.update(
transition: .immediate, transition: .immediate,
component: AnyComponent( component: AnyComponent(
StarsBalanceOverlayComponent( StarsBalanceOverlayComponent(
context: self.context, context: context,
theme: self.context.sharedContext.currentPresentationData.with { $0 }.theme, theme: context.sharedContext.currentPresentationData.with { $0 }.theme,
action: { action: { [weak self] in
guard let self, let starsContext = context.starsContext, let navigationController = self.navigationController as? NavigationController else {
return
}
self.dismissAnimated()
let _ = (context.engine.payments.starsTopUpOptions()
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { options in
let controller = context.sharedContext.makeStarsPurchaseScreen(
context: context,
starsContext: starsContext,
options: options,
purpose: .generic,
completion: { _ in }
)
navigationController.pushViewController(controller)
})
} }
) )
), ),

View File

@ -274,7 +274,7 @@ public func giftWithdrawAlertController(context: AccountContext, gift: StarGift.
let strings = presentationData.strings let strings = presentationData.strings
let title = strings.Gift_Withdraw_Title let title = strings.Gift_Withdraw_Title
let text = strings.Gift_Withdraw_Text("\(gift.title) #\(gift.number)").string let text = strings.Gift_Withdraw_Text("\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))").string
let buttonText = strings.Gift_Withdraw_Proceed let buttonText = strings.Gift_Withdraw_Proceed
var dismissImpl: ((Bool) -> Void)? var dismissImpl: ((Bool) -> Void)?

View File

@ -681,7 +681,7 @@ public final class MessageInputPanelComponent: Component {
if self.contextQueryPeer == nil, let peerId = component.chatLocation?.peerId { if self.contextQueryPeer == nil, let peerId = component.chatLocation?.peerId {
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> deliverOnMainQueue).start(next: { [weak self] peer in |> deliverOnMainQueue).start(next: { [weak self] peer in
guard let self, peer?.addressName != nil else { guard let self, let peer, case .channel = peer, peer.addressName != nil else {
return return
} }
self.contextQueryPeer = peer self.contextQueryPeer = peer

View File

@ -25,10 +25,10 @@ public final class MessagePriceItem: ListViewItem, ItemListItem {
let value: Int64 let value: Int64
let price: String let price: String
public let sectionId: ItemListSectionId public let sectionId: ItemListSectionId
let updated: (Int64) -> Void let updated: (Int64, Bool) -> Void
let openPremiumInfo: (() -> Void)? let openPremiumInfo: (() -> Void)?
public init(theme: PresentationTheme, strings: PresentationStrings, isEnabled: Bool, minValue: Int64, maxValue: Int64, value: Int64, price: String, sectionId: ItemListSectionId, updated: @escaping (Int64) -> Void, openPremiumInfo: (() -> Void)? = nil) { public init(theme: PresentationTheme, strings: PresentationStrings, isEnabled: Bool, minValue: Int64, maxValue: Int64, value: Int64, price: String, sectionId: ItemListSectionId, updated: @escaping (Int64, Bool) -> Void, openPremiumInfo: (() -> Void)? = nil) {
self.theme = theme self.theme = theme
self.strings = strings self.strings = strings
self.isEnabled = isEnabled self.isEnabled = isEnabled
@ -259,7 +259,7 @@ private class MessagePriceItemNode: ListViewItemNode {
if let strongSelf = self { if let strongSelf = self {
strongSelf.item = item strongSelf.item = item
strongSelf.layoutParams = params strongSelf.layoutParams = params
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
@ -342,6 +342,13 @@ private class MessagePriceItemNode: ListViewItemNode {
} }
sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0)) sliderView.frame = CGRect(origin: CGPoint(x: params.leftInset + 18.0, y: 36.0), size: CGSize(width: params.width - params.leftInset - params.rightInset - 18.0 * 2.0, height: 44.0))
sliderView.interactionEnded = { [weak self] in
guard let self else {
return
}
self.item?.updated(Int64(self.amount.realValue), true)
}
} }
strongSelf.lockIconNode.isHidden = item.isEnabled strongSelf.lockIconNode.isHidden = item.isEnabled
@ -436,7 +443,7 @@ private class MessagePriceItemNode: ListViewItemNode {
} }
self.amount = updatedAmount self.amount = updatedAmount
self.item?.updated(Int64(self.amount.realValue)) self.item?.updated(Int64(self.amount.realValue), false)
} }
} }

View File

@ -579,7 +579,7 @@ private class GiftIconLayer: SimpleLayer {
} }
override func layoutSublayers() { override func layoutSublayers() {
self.shadowLayer.frame = CGRect(origin: .zero, size: self.bounds.size).insetBy(dx: -4.0, dy: -4.0) self.shadowLayer.frame = CGRect(origin: .zero, size: self.bounds.size).insetBy(dx: -8.0, dy: -8.0)
self.animationLayer.frame = CGRect(origin: .zero, size: self.bounds.size) self.animationLayer.frame = CGRect(origin: .zero, size: self.bounds.size)
} }

View File

@ -255,6 +255,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.buttonsContainerNode.clipsToBounds = true self.buttonsContainerNode.clipsToBounds = true
self.buttonsBackgroundNode = NavigationBackgroundNode(color: .clear, enableBlur: true, enableSaturation: false) self.buttonsBackgroundNode = NavigationBackgroundNode(color: .clear, enableBlur: true, enableSaturation: false)
self.buttonsBackgroundNode.isUserInteractionEnabled = false
self.buttonsContainerNode.addSubnode(self.buttonsBackgroundNode) self.buttonsContainerNode.addSubnode(self.buttonsBackgroundNode)
self.buttonsMaskView = UIView() self.buttonsMaskView = UIView()
self.buttonsBackgroundNode.view.mask = self.buttonsMaskView self.buttonsBackgroundNode.view.mask = self.buttonsMaskView

View File

@ -3728,7 +3728,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, openAgeRestrictedMessageMedia: { _, _ in }, openAgeRestrictedMessageMedia: { _, _ in
}, playMessageEffect: { _ in }, playMessageEffect: { _ in
}, editMessageFactCheck: { _ in }, editMessageFactCheck: { _ in
}, sendGift: { _ in }, sendGift: { [weak self] _ in
guard let self else {
return
}
self.openPremiumGift()
}, openUniqueGift: { _ in }, openUniqueGift: { _ in
}, openMessageFeeException: { }, openMessageFeeException: {
}, requestMessageUpdate: { _, _ in }, requestMessageUpdate: { _, _ in

View File

@ -120,7 +120,7 @@ private final class GiftContextPreviewComponent: Component {
let subtitleSize = self.subtitle.update( let subtitleSize = self.subtitle.update(
transition: .immediate, transition: .immediate,
component: AnyComponent(MultilineTextComponent(text: .plain( component: AnyComponent(MultilineTextComponent(text: .plain(
NSAttributedString(string: "\(environment.strings.Gift_Unique_Collectible) #\(uniqueGift.number)", font: Font.regular(13.0), textColor: vibrantColor) NSAttributedString(string: "\(environment.strings.Gift_Unique_Collectible) #\(presentationStringsFormattedNumber(uniqueGift.number, environment.dateTimeFormat.groupingSeparator))", font: Font.regular(13.0), textColor: vibrantColor)
))), ))),
environment: {}, environment: {},
containerSize: availableSize containerSize: availableSize

View File

@ -240,6 +240,9 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
public func beginReordering() { public func beginReordering() {
self.profileGifts.updateFilter(.All)
self.profileGifts.updateSorting(.date)
if let parentController = self.parentController as? PeerInfoScreen { if let parentController = self.parentController as? PeerInfoScreen {
parentController.togglePaneIsReordering(isReordering: true) parentController.togglePaneIsReordering(isReordering: true)
} else { } else {
@ -469,7 +472,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
return return
} }
if self.isReordering { if self.isReordering {
if !product.pinnedToTop, let reference = product.reference, let items = self.starsProducts { if case .unique = product.gift, !product.pinnedToTop, let reference = product.reference, let items = self.starsProducts {
if self.pinnedReferences.count >= self.maxPinnedCount { if self.pinnedReferences.count >= self.maxPinnedCount {
self.parentController?.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.PeerInfo_Gifts_ToastPinLimit_Text(Int32(self.maxPinnedCount)), timeout: nil, customUndoText: nil), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) self.parentController?.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.PeerInfo_Gifts_ToastPinLimit_Text(Int32(self.maxPinnedCount)), timeout: nil, customUndoText: nil), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root))
return return
@ -564,7 +567,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
itemFrame = itemFrame.size.centered(around: reorderingItem.position) itemFrame = itemFrame.size.centered(around: reorderingItem.position)
isReordering = true isReordering = true
} }
if itemView.layer.animation(forKey: "position") != nil && !isReordering { if self.isReordering, itemView.layer.animation(forKey: "position") != nil && !isReordering {
} else { } else {
itemTransition.setFrame(view: itemView, frame: itemFrame) itemTransition.setFrame(view: itemView, frame: itemFrame)
} }
@ -612,8 +615,6 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
var bottomScrollInset: CGFloat = 0.0 var bottomScrollInset: CGFloat = 0.0
var contentHeight = ceil(CGFloat(starsProducts.count) / 3.0) * (starsOptionSize.height + optionSpacing) - optionSpacing + topInset + 16.0 var contentHeight = ceil(CGFloat(starsProducts.count) / 3.0) * (starsOptionSize.height + optionSpacing) - optionSpacing + topInset + 16.0
let transition = ComponentTransition.immediate
let size = params.size let size = params.size
let sideInset = params.sideInset let sideInset = params.sideInset
let bottomInset = params.bottomInset let bottomInset = params.bottomInset
@ -681,8 +682,9 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
scrollOffset -= bottomPanelHeight scrollOffset -= bottomPanelHeight
} }
transition.setFrame(view: panelButton.view, frame: CGRect(origin: CGPoint(x: buttonSideInset, y: size.height - bottomInset - buttonSize.height - scrollOffset), size: buttonSize)) let panelTransition = ComponentTransition.immediate
transition.setAlpha(view: panelButton.view, alpha: panelAlpha) panelTransition.setFrame(view: panelButton.view, frame: CGRect(origin: CGPoint(x: buttonSideInset, y: size.height - bottomInset - buttonSize.height - scrollOffset), size: buttonSize))
panelTransition.setAlpha(view: panelButton.view, alpha: panelAlpha)
let _ = panelButton.updateLayout(width: buttonSize.width, transition: .immediate) let _ = panelButton.updateLayout(width: buttonSize.width, transition: .immediate)
if self.canManage { if self.canManage {
@ -753,16 +755,16 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.view.addSubview(panelCheckView) self.view.addSubview(panelCheckView)
} }
panelCheckView.frame = CGRect(origin: CGPoint(x: floor((size.width - panelCheckSize.width) / 2.0), y: size.height - bottomInset - panelCheckSize.height - 11.0 - scrollOffset), size: panelCheckSize) panelCheckView.frame = CGRect(origin: CGPoint(x: floor((size.width - panelCheckSize.width) / 2.0), y: size.height - bottomInset - panelCheckSize.height - 11.0 - scrollOffset), size: panelCheckSize)
transition.setAlpha(view: panelCheckView, alpha: panelAlpha) panelTransition.setAlpha(view: panelCheckView, alpha: panelAlpha)
} }
panelButton.isHidden = true panelButton.isHidden = true
} }
transition.setFrame(view: panelBackground.view, frame: CGRect(x: 0.0, y: size.height - bottomPanelHeight - scrollOffset, width: size.width, height: bottomPanelHeight)) panelTransition.setFrame(view: panelBackground.view, frame: CGRect(x: 0.0, y: size.height - bottomPanelHeight - scrollOffset, width: size.width, height: bottomPanelHeight))
transition.setAlpha(view: panelBackground.view, alpha: panelAlpha) panelTransition.setAlpha(view: panelBackground.view, alpha: panelAlpha)
panelBackground.update(size: CGSize(width: size.width, height: bottomPanelHeight), transition: transition.containedViewLayoutTransition) panelBackground.update(size: CGSize(width: size.width, height: bottomPanelHeight), transition: transition.containedViewLayoutTransition)
transition.setFrame(view: panelSeparator.view, frame: CGRect(x: 0.0, y: size.height - bottomPanelHeight - scrollOffset, width: size.width, height: UIScreenPixel)) panelTransition.setFrame(view: panelSeparator.view, frame: CGRect(x: 0.0, y: size.height - bottomPanelHeight - scrollOffset, width: size.width, height: UIScreenPixel))
transition.setAlpha(view: panelSeparator.view, alpha: panelAlpha) panelTransition.setAlpha(view: panelSeparator.view, alpha: panelAlpha)
let fadeTransition = ComponentTransition.easeInOut(duration: 0.25) let fadeTransition = ComponentTransition.easeInOut(duration: 0.25)
if self.resultsAreEmpty { if self.resultsAreEmpty {
@ -776,8 +778,8 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.emptyResultsClippingView.isHidden = false self.emptyResultsClippingView.isHidden = false
transition.setFrame(view: self.emptyResultsClippingView, frame: CGRect(origin: CGPoint(x: 0.0, y: 48.0), size: self.scrollNode.frame.size)) panelTransition.setFrame(view: self.emptyResultsClippingView, frame: CGRect(origin: CGPoint(x: 0.0, y: 48.0), size: self.scrollNode.frame.size))
transition.setBounds(view: self.emptyResultsClippingView, bounds: CGRect(origin: CGPoint(x: 0.0, y: 48.0), size: self.scrollNode.frame.size)) panelTransition.setBounds(view: self.emptyResultsClippingView, bounds: CGRect(origin: CGPoint(x: 0.0, y: 48.0), size: self.scrollNode.frame.size))
let emptyResultsTitleSize = self.emptyResultsTitle.update( let emptyResultsTitleSize = self.emptyResultsTitle.update(
transition: .immediate, transition: .immediate,
@ -840,7 +842,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
view.playOnce() view.playOnce()
} }
view.bounds = CGRect(origin: .zero, size: emptyResultsAnimationFrame.size) view.bounds = CGRect(origin: .zero, size: emptyResultsAnimationFrame.size)
transition.setPosition(view: view, position: emptyResultsAnimationFrame.center) panelTransition.setPosition(view: view, position: emptyResultsAnimationFrame.center)
} }
if let view = self.emptyResultsTitle.view { if let view = self.emptyResultsTitle.view {
if view.superview == nil { if view.superview == nil {
@ -849,7 +851,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.emptyResultsClippingView.addSubview(view) self.emptyResultsClippingView.addSubview(view)
} }
view.bounds = CGRect(origin: .zero, size: emptyResultsTitleFrame.size) view.bounds = CGRect(origin: .zero, size: emptyResultsTitleFrame.size)
transition.setPosition(view: view, position: emptyResultsTitleFrame.center) panelTransition.setPosition(view: view, position: emptyResultsTitleFrame.center)
} }
if let view = self.emptyResultsAction.view { if let view = self.emptyResultsAction.view {
if view.superview == nil { if view.superview == nil {
@ -858,7 +860,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.emptyResultsClippingView.addSubview(view) self.emptyResultsClippingView.addSubview(view)
} }
view.bounds = CGRect(origin: .zero, size: emptyResultsActionFrame.size) view.bounds = CGRect(origin: .zero, size: emptyResultsActionFrame.size)
transition.setPosition(view: view, position: emptyResultsActionFrame.center) panelTransition.setPosition(view: view, position: emptyResultsActionFrame.center)
} }
} else { } else {
if let view = self.emptyResultsAnimation.view { if let view = self.emptyResultsAnimation.view {
@ -879,7 +881,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
} }
} }
if self.peerId == self.context.account.peerId { if self.peerId == self.context.account.peerId, !self.resultsAreEmpty {
let footerText: ComponentView<Empty> let footerText: ComponentView<Empty>
if let current = self.footerText { if let current = self.footerText {
footerText = current footerText = current
@ -941,21 +943,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
self.chatControllerInteraction.navigationController()?.pushViewController(controller) self.chatControllerInteraction.navigationController()?.pushViewController(controller)
}) })
} else { } else {
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Birthday(id: self.peerId)) self.chatControllerInteraction.sendGift(self.peerId)
|> deliverOnMainQueue).start(next: { birthday in
var hasBirthday = false
if let birthday {
hasBirthday = hasBirthdayToday(birthday: birthday)
}
let controller = self.context.sharedContext.makeGiftOptionsController(
context: self.context,
peerId: self.peerId,
premiumOptions: [],
hasBirthday: hasBirthday,
completion: nil
)
self.chatControllerInteraction.navigationController()?.pushViewController(controller)
})
} }
} }

View File

@ -424,7 +424,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
isPaidMessage = true isPaidMessage = true
titleText = strings.Stars_Transaction_PaidMessage(transaction.paidMessageCount ?? 1) titleText = strings.Stars_Transaction_PaidMessage(transaction.paidMessageCount ?? 1)
countOnTop = true countOnTop = true
descriptionText = strings.Stars_Transaction_PaidMessage_Text(formatPermille(starrefCommissionPermille)).string descriptionText = strings.Stars_Transaction_PaidMessage_Text(formatPermille(1000 - starrefCommissionPermille)).string
} else if transaction.starrefPeerId == nil { } else if transaction.starrefPeerId == nil {
titleText = strings.StarsTransaction_TitleCommission(formatPermille(starrefCommissionPermille)).string titleText = strings.StarsTransaction_TitleCommission(formatPermille(starrefCommissionPermille)).string
countOnTop = false countOnTop = false

View File

@ -312,7 +312,7 @@ final class StarsTransactionsListPanelComponent: Component {
itemSubtitle = environment.strings.Stars_Intro_Transaction_PaidMessage(item.paidMessageCount ?? 1) itemSubtitle = environment.strings.Stars_Intro_Transaction_PaidMessage(item.paidMessageCount ?? 1)
} else if let starGift = item.starGift { } else if let starGift = item.starGift {
if item.flags.contains(.isStarGiftUpgrade), case let .unique(gift) = starGift { if item.flags.contains(.isStarGiftUpgrade), case let .unique(gift) = starGift {
itemTitle = "\(gift.title) #\(gift.number)" itemTitle = "\(gift.title) #\(presentationStringsFormattedNumber(gift.number, environment.dateTimeFormat.groupingSeparator))"
itemSubtitle = environment.strings.Stars_Intro_Transaction_GiftUpgrade itemSubtitle = environment.strings.Stars_Intro_Transaction_GiftUpgrade
uniqueGift = gift uniqueGift = gift
} else { } else {

View File

@ -2905,7 +2905,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
Queue.mainQueue().after(0.3) { Queue.mainQueue().after(0.3) {
let tooltipController = UndoOverlayController( let tooltipController = UndoOverlayController(
presentationData: presentationData, presentationData: presentationData,
content: .forward(savedMessages: false, text: presentationData.strings.Gift_Transfer_Success("\(gift.title) #\(gift.number)", peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string), content: .forward(savedMessages: false, text: presentationData.strings.Gift_Transfer_Success("\(gift.title) #\(presentationStringsFormattedNumber(gift.number, presentationData.dateTimeFormat.groupingSeparator))", peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).string),
elevatedLayout: false, elevatedLayout: false,
action: { _ in return true } action: { _ in return true }
) )

View File

@ -65,10 +65,10 @@ function tgBrowserHandleMutations(mutations) {
if (mutation.addedNodes && mutation.addedNodes.length > 0) { if (mutation.addedNodes && mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((newNode) => { mutation.addedNodes.forEach((newNode) => {
if (newNode.tagName === 'VIDEO') { if (newNode.tagName === 'VIDEO') {
disableWebkitEnterFullscreen(newNode); tgBrowserDisableWebkitEnterFullscreen(newNode);
} }
if (newNode.querySelectorAll) { if (newNode.querySelectorAll) {
newNode.querySelectorAll('video').forEach(disableWebkitEnterFullscreen); newNode.querySelectorAll('video').forEach(tgBrowserDisableWebkitEnterFullscreen);
} }
}); });
} }