From 7a93320a5c777427fc718ec09234f25fee2a2c77 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 27 Jul 2025 22:12:32 +0200 Subject: [PATCH 1/2] Fix gift view tooltips on iPad --- .../Sources/GiftViewScreen.swift | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift index 2883863828..adebdb7823 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftViewScreen/Sources/GiftViewScreen.swift @@ -484,7 +484,6 @@ private final class GiftViewSheetContent: CombinedComponent { undoText: presentationData.strings.Gift_Displayed_View, customAction: nil ), - elevatedLayout: lastController is ChatController, action: { [weak navigationController] action in if case .undo = action, let navigationController, let giftsPeerId { let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: giftsPeerId)) @@ -508,7 +507,7 @@ private final class GiftViewSheetContent: CombinedComponent { return true } ) - lastController.present(resultController, in: .window(.root)) + lastController.present(resultController, in: .current) } } } @@ -608,10 +607,9 @@ private final class GiftViewSheetContent: CombinedComponent { customUndoText: nil, timeout: nil ), - elevatedLayout: lastController is ChatController, action: { _ in return true } ) - lastController.present(resultController, in: .window(.root)) + lastController.present(resultController, in: .current) } } } @@ -867,7 +865,7 @@ private final class GiftViewSheetContent: CombinedComponent { return false } ) - controller.present(tooltipController, in: .window(.root)) + controller.present(tooltipController, in: .current) }) }), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: { @@ -954,7 +952,7 @@ private final class GiftViewSheetContent: CombinedComponent { return false } ) - controller.present(tooltipController, in: .window(.root)) + controller.present(tooltipController, in: .current) }) }) controller.push(resellController) @@ -1323,12 +1321,11 @@ private final class GiftViewSheetContent: CombinedComponent { let resultController = UndoOverlayController( presentationData: presentationData, content: .sticker(context: context, file: animationFile, loop: false, title: presentationData.strings.Gift_View_Resale_SuccessYou_Title, text: presentationData.strings.Gift_View_Resale_SuccessYou_Text(giftTitle).string, undoText: nil, customAction: nil), - elevatedLayout: lastController is ChatController, action: { _ in return true } ) - lastController.present(resultController, in: .window(.root)) + lastController.present(resultController, in: .current) } }) } else { @@ -1345,12 +1342,11 @@ private final class GiftViewSheetContent: CombinedComponent { let resultController = UndoOverlayController( presentationData: presentationData, content: .sticker(context: context, file: animationFile, loop: false, title: presentationData.strings.Gift_View_Resale_Success_Title, text: presentationData.strings.Gift_View_Resale_Success_Text(peer.compactDisplayTitle).string, undoText: nil, customAction: nil), - elevatedLayout: lastController is ChatController, action: { _ in return true } ) - lastController.present(resultController, in: .window(.root)) + lastController.present(resultController, in: .current) } }) }) @@ -3404,7 +3400,7 @@ private final class GiftViewSheetContent: CombinedComponent { return false } ) - controller.present(tooltipController, in: .window(.root)) + controller.present(tooltipController, in: .current) } } else { state.commitWear(uniqueGift) @@ -3723,12 +3719,19 @@ final class GiftViewSheetComponent: CombinedComponent { ) if let controller = controller(), !controller.automaticallyControlPresentationContextLayout { + var sideInset: CGFloat = 0.0 + var bottomInset: CGFloat = max(environment.safeInsets.bottom, sheetExternalState.contentHeight) + if case .regular = environment.metrics.widthClass { + sideInset = floor((context.availableSize.width - 430.0) / 2.0) - 12.0 + bottomInset = (context.availableSize.height - sheetExternalState.contentHeight) / 2.0 + sheetExternalState.contentHeight + } + let layout = ContainerViewLayout( size: context.availableSize, metrics: environment.metrics, deviceMetrics: environment.deviceMetrics, - intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: max(environment.safeInsets.bottom, sheetExternalState.contentHeight), right: 0.0), - safeInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right), + intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomInset, right: 0.0), + safeInsets: UIEdgeInsets(top: 0.0, left: max(sideInset, environment.safeInsets.left), bottom: 0.0, right: max(sideInset, environment.safeInsets.right)), additionalInsets: .zero, statusBarHeight: environment.statusBarHeight, inputHeight: nil, From cf3bc1edbdbab6fecc24a4446a78cee8777ac2f6 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 27 Jul 2025 23:36:37 +0200 Subject: [PATCH 2/2] Various fixes --- .../Sources/TonFormat.swift | 12 ++++--- .../Sources/GiftViewScreen.swift | 31 ++++++++++++------- .../StarsBalanceOverlayComponent.swift | 11 +++++-- .../Sources/StarsTransactionScreen.swift | 25 ++++++++++----- .../Sources/StarsWithdrawalScreen.swift | 10 +++--- 5 files changed, 58 insertions(+), 31 deletions(-) diff --git a/submodules/TelegramStringFormatting/Sources/TonFormat.swift b/submodules/TelegramStringFormatting/Sources/TonFormat.swift index b5a3151174..dd2d735a11 100644 --- a/submodules/TelegramStringFormatting/Sources/TonFormat.swift +++ b/submodules/TelegramStringFormatting/Sources/TonFormat.swift @@ -28,7 +28,7 @@ public func formatTonUsdValue(_ value: Int64, divide: Bool = true, rate: Double return "$\(formattedValue)" } -public func formatTonAmountText(_ value: Int64, dateTimeFormat: PresentationDateTimeFormat, showPlus: Bool = false, maxDecimalPositions: Int = 2) -> String { +public func formatTonAmountText(_ value: Int64, dateTimeFormat: PresentationDateTimeFormat, showPlus: Bool = false, maxDecimalPositions: Int? = 2) -> String { var balanceText = "\(abs(value))" while balanceText.count < 10 { balanceText.insert("0", at: balanceText.startIndex) @@ -49,10 +49,12 @@ public func formatTonAmountText(_ value: Int64, dateTimeFormat: PresentationDate } if let dotIndex = balanceText.range(of: dateTimeFormat.decimalSeparator) { - if let endIndex = balanceText.index(dotIndex.upperBound, offsetBy: maxDecimalPositions, limitedBy: balanceText.endIndex) { - balanceText = String(balanceText[balanceText.startIndex..() + private var text = ComponentView() private let action = ComponentView() private var component: StarsBalanceOverlayComponent? @@ -89,6 +89,7 @@ public final class StarsBalanceOverlayComponent: Component { defer { self.isUpdating = false } + let previousComponent = self.component self.component = component self.state = state @@ -169,6 +170,13 @@ public final class StarsBalanceOverlayComponent: Component { attributedText.addAttribute(.baselineOffset, value: 1.0, range: tonRange) } + if previousComponent?.currency != component.currency { + if let textView = self.text.view { + textView.removeFromSuperview() + } + self.text = ComponentView() + } + let textSize = self.text.update( transition: .immediate, component: AnyComponent( @@ -222,7 +230,6 @@ public final class StarsBalanceOverlayComponent: Component { actionView.removeFromSuperview() } } - if let textView = self.text.view { if textView.superview == nil { diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift index 03ff9a4aee..f81d39c1cc 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift @@ -660,7 +660,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { case .stars: formattedAmount = formatStarsAmountText(absCount, dateTimeFormat: dateTimeFormat) case .ton: - formattedAmount = formatTonAmountText(absCount.value, dateTimeFormat: dateTimeFormat) + formattedAmount = formatTonAmountText(absCount.value, dateTimeFormat: dateTimeFormat, maxDecimalPositions: nil) } let countColor: UIColor var countFont: UIFont = isSubscription || isSubscriber ? Font.regular(17.0) : Font.semibold(17.0) @@ -1207,14 +1207,25 @@ private final class StarsTransactionSheetContent: CombinedComponent { if transaction.flags.contains(.isPaidMessage) || transaction.flags.contains(.isStarGiftResale) { var totalStars = transaction.count if let starrefCount = transaction.starrefAmount { - totalStars = CurrencyAmount(amount: totalStars.amount + starrefCount, currency: .stars) + totalStars = CurrencyAmount(amount: totalStars.amount + starrefCount, currency: totalStars.currency) + } + var valueString = formatCurrencyAmountText(totalStars, dateTimeFormat: dateTimeFormat) + switch totalStars.currency { + case .stars: + valueString = "\(valueString)⭐️" + case .ton: + valueString = "💎\(valueString)" } - let valueString = "\(presentationStringsFormattedNumber(abs(Int32(totalStars.amount.value)), dateTimeFormat.groupingSeparator))⭐️" let valueAttributedString = NSMutableAttributedString(string: valueString, font: tableBoldFont, textColor: theme.list.itemDisclosureActions.constructive.fillColor) - let range = (valueAttributedString.string as NSString).range(of: "⭐️") - if range.location != NSNotFound { - valueAttributedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: range) - valueAttributedString.addAttribute(.baselineOffset, value: 1.0, range: range) + let starRange = (valueAttributedString.string as NSString).range(of: "⭐️") + if starRange.location != NSNotFound { + valueAttributedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: starRange) + valueAttributedString.addAttribute(.baselineOffset, value: 1.0, range: starRange) + } + let tonRange = (valueAttributedString.string as NSString).range(of: "💎") + if tonRange.location != NSNotFound { + valueAttributedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .ton(tinted: true)), range: tonRange) + valueAttributedString.addAttribute(.baselineOffset, value: 1.0, range: tonRange) } tableItems.append(.init( id: "paid", diff --git a/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift b/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift index aae750f048..4b1c4a94be 100644 --- a/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsWithdrawalScreen/Sources/StarsWithdrawalScreen.swift @@ -467,7 +467,7 @@ private final class SheetContent: CombinedComponent { case .ton: if let value = state.amount?.value, value > 0 { let tonValue = Int64(Float(value) * Float(resaleConfiguration.starGiftCommissionTonPermille) / 1000.0) - let tonString = formatTonAmountText(tonValue, dateTimeFormat: environment.dateTimeFormat) + " TON" + let tonString = formatTonAmountText(tonValue, dateTimeFormat: environment.dateTimeFormat, maxDecimalPositions: nil) + " TON" amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString(environment.strings.Stars_SellGift_AmountInfo(tonString).string, attributes: amountMarkdownAttributes, textAlignment: .natural)) if let tonUsdRate = withdrawConfiguration.tonUsdRate { @@ -778,7 +778,7 @@ private final class SheetContent: CombinedComponent { currencyAmount = presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator) case .ton: currencySymbol = "$" - currencyAmount = formatTonAmountText(amount.value, dateTimeFormat: environment.dateTimeFormat) + currencyAmount = formatTonAmountText(amount.value, dateTimeFormat: environment.dateTimeFormat, maxDecimalPositions: nil) } buttonString = "\(environment.strings.Stars_SellGift_SellFor) \(currencySymbol) \(currencyAmount)" } else { @@ -798,7 +798,7 @@ private final class SheetContent: CombinedComponent { currencyAmount = presentationStringsFormattedNumber(amount, environment.dateTimeFormat.groupingSeparator) case .ton: currencySymbol = "$" - currencyAmount = formatTonAmountText(amount.value, dateTimeFormat: environment.dateTimeFormat) + currencyAmount = formatTonAmountText(amount.value, dateTimeFormat: environment.dateTimeFormat, maxDecimalPositions: nil) } buttonString = environment.strings.Chat_PostSuggestion_Suggest_OfferButtonPrice("\(currencySymbol) \(currencyAmount)").string } else { @@ -1423,7 +1423,7 @@ private final class AmountFieldStarsFormatter: NSObject, UITextFieldDelegate { case .stars: textField.text = "\(self.maxValue)" case .ton: - textField.text = "\(formatTonAmountText(self.maxValue, dateTimeFormat: PresentationDateTimeFormat(timeFormat: self.dateTimeFormat.timeFormat, dateFormat: self.dateTimeFormat.dateFormat, dateSeparator: "", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: "")))" + textField.text = "\(formatTonAmountText(self.maxValue, dateTimeFormat: PresentationDateTimeFormat(timeFormat: self.dateTimeFormat.timeFormat, dateFormat: self.dateTimeFormat.dateFormat, dateSeparator: "", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), maxDecimalPositions: nil))" } self.onTextChanged(text: self.textField.text ?? "") self.animateError() @@ -1592,7 +1592,7 @@ private final class AmountFieldComponent: Component { case .stars: text = "\(value)" case .ton: - text = "\(formatTonAmountText(value, dateTimeFormat: PresentationDateTimeFormat(timeFormat: component.dateTimeFormat.timeFormat, dateFormat: component.dateTimeFormat.dateFormat, dateSeparator: "", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: "")))" + text = "\(formatTonAmountText(value, dateTimeFormat: PresentationDateTimeFormat(timeFormat: component.dateTimeFormat.timeFormat, dateFormat: component.dateTimeFormat.dateFormat, dateSeparator: "", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), maxDecimalPositions: nil))" } self.textField.text = text self.didSetValueOnce = true