mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-15 13:35:19 +00:00
[WIP] Post suggestions
This commit is contained in:
parent
d6334b9748
commit
084bb5bcd5
@ -996,8 +996,13 @@ public enum SendInviteLinkScreenSubject {
|
||||
}
|
||||
|
||||
public enum StarsWithdrawalScreenSubject {
|
||||
public enum PaidMessageKind {
|
||||
case privacy
|
||||
case postSuggestion
|
||||
}
|
||||
|
||||
case withdraw
|
||||
case enterAmount(current: StarsAmount)
|
||||
case enterAmount(current: StarsAmount, minValue: StarsAmount, fractionAfterCommission: Int, kind: PaidMessageKind)
|
||||
}
|
||||
|
||||
public protocol SharedAccountContext: AnyObject {
|
||||
|
@ -376,7 +376,7 @@ public func incomingMessagePrivacyScreen(context: AccountContext, value: GlobalP
|
||||
if case let .paidMessages(value) = stateValue.with({ $0 }).updatedValue {
|
||||
currentAmount = value
|
||||
}
|
||||
let starsScreen = context.sharedContext.makeStarsWithdrawalScreen(context: context, subject: .enterAmount(current: currentAmount), completion: { amount in
|
||||
let starsScreen = context.sharedContext.makeStarsWithdrawalScreen(context: context, subject: .enterAmount(current: currentAmount, minValue: StarsAmount(value: 1, nanos: 0), fractionAfterCommission: 80, kind: .privacy), completion: { amount in
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.updatedValue = .paidMessages(StarsAmount(value: amount, nanos: 0))
|
||||
|
@ -321,48 +321,88 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
|
||||
return self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: transition, interfaceState: interfaceState, metrics: metrics, force: false)
|
||||
}
|
||||
|
||||
private var displayedGiftTooltip = false
|
||||
private func presentGiftTooltip() {
|
||||
guard let context = self.context, !self.displayedGiftTooltip, let parentController = self.interfaceInteraction?.chatController() else {
|
||||
private var displayedGiftOrSuggestTooltip = false
|
||||
private func presentGiftOrSuggestTooltip() {
|
||||
guard let context = self.context, !self.displayedGiftOrSuggestTooltip, let parentController = self.interfaceInteraction?.chatController() else {
|
||||
return
|
||||
}
|
||||
self.displayedGiftTooltip = true
|
||||
self.displayedGiftOrSuggestTooltip = true
|
||||
|
||||
let _ = (ApplicationSpecificNotice.getChannelSendGiftTooltip(accountManager: context.sharedContext.accountManager)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] count in
|
||||
let _ = (combineLatest(queue: .mainQueue(),
|
||||
ApplicationSpecificNotice.getChannelSendGiftTooltip(accountManager: context.sharedContext.accountManager),
|
||||
ApplicationSpecificNotice.getChannelSuggestTooltip(accountManager: context.sharedContext.accountManager)
|
||||
|> deliverOnMainQueue)).start(next: { [weak self] giftCount, suggestCount in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard count < 2 else {
|
||||
return
|
||||
|
||||
/*#if DEBUG
|
||||
var giftCount = giftCount
|
||||
var suggestCount = suggestCount
|
||||
if "".isEmpty {
|
||||
giftCount = 2
|
||||
suggestCount = 0
|
||||
}
|
||||
#endif*/
|
||||
|
||||
let _ = ApplicationSpecificNotice.incrementChannelSendGiftTooltip(accountManager: context.sharedContext.accountManager).start()
|
||||
|
||||
Queue.mainQueue().after(0.4, {
|
||||
let absoluteFrame = self.giftButton.view.convert(self.giftButton.bounds, to: parentController.view)
|
||||
let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.minY + 11.0), size: CGSize())
|
||||
if giftCount < 2 && !self.giftButton.isHidden {
|
||||
let _ = ApplicationSpecificNotice.incrementChannelSendGiftTooltip(accountManager: context.sharedContext.accountManager).start()
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String = presentationData.strings.Chat_SendGiftTooltip
|
||||
|
||||
let tooltipController = TooltipScreen(
|
||||
account: context.account,
|
||||
sharedContext: context.sharedContext,
|
||||
text: .plain(text: text),
|
||||
balancedTextLayout: false,
|
||||
style: .wide,
|
||||
arrowStyle: .small,
|
||||
icon: nil,
|
||||
location: .point(location, .bottom),
|
||||
displayDuration: .default,
|
||||
inset: 8.0,
|
||||
shouldDismissOnTouch: { _, _ in
|
||||
return .ignore
|
||||
}
|
||||
)
|
||||
self.interfaceInteraction?.presentControllerInCurrent(tooltipController, nil)
|
||||
})
|
||||
Queue.mainQueue().after(0.4, {
|
||||
let absoluteFrame = self.giftButton.view.convert(self.giftButton.bounds, to: parentController.view)
|
||||
let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.minY + 11.0), size: CGSize())
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String = presentationData.strings.Chat_SendGiftTooltip
|
||||
|
||||
let tooltipController = TooltipScreen(
|
||||
account: context.account,
|
||||
sharedContext: context.sharedContext,
|
||||
text: .plain(text: text),
|
||||
balancedTextLayout: false,
|
||||
style: .wide,
|
||||
arrowStyle: .small,
|
||||
icon: nil,
|
||||
location: .point(location, .bottom),
|
||||
displayDuration: .default,
|
||||
inset: 8.0,
|
||||
shouldDismissOnTouch: { _, _ in
|
||||
return .ignore
|
||||
}
|
||||
)
|
||||
self.interfaceInteraction?.presentControllerInCurrent(tooltipController, nil)
|
||||
})
|
||||
} else if suggestCount < 2 && !self.suggestedPostButton.isHidden {
|
||||
let _ = ApplicationSpecificNotice.incrementChannelSuggestTooltip(accountManager: context.sharedContext.accountManager).start()
|
||||
|
||||
Queue.mainQueue().after(0.4, {
|
||||
let absoluteFrame = self.suggestedPostButton.view.convert(self.suggestedPostButton.bounds, to: parentController.view)
|
||||
let location = CGRect(origin: CGPoint(x: absoluteFrame.midX, y: absoluteFrame.minY + 11.0), size: CGSize())
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let _ = presentationData
|
||||
//TODO:localize
|
||||
let text: String = "Tap here to suggest a message"
|
||||
|
||||
let tooltipController = TooltipScreen(
|
||||
account: context.account,
|
||||
sharedContext: context.sharedContext,
|
||||
text: .plain(text: text),
|
||||
textBadge: "NEW",
|
||||
balancedTextLayout: false,
|
||||
style: .wide,
|
||||
arrowStyle: .small,
|
||||
icon: nil,
|
||||
location: .point(location, .bottom),
|
||||
displayDuration: .default,
|
||||
inset: 8.0,
|
||||
shouldDismissOnTouch: { _, _ in
|
||||
return .ignore
|
||||
}
|
||||
)
|
||||
self.interfaceInteraction?.presentControllerInCurrent(tooltipController, nil)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -377,7 +417,7 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
|
||||
if previousState?.theme !== interfaceState.theme {
|
||||
self.badgeBackground.image = PresentationResourcesChatList.badgeBackgroundActive(interfaceState.theme, diameter: 20.0)
|
||||
self.helpButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/Help"), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor), for: .normal)
|
||||
self.suggestedPostButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/Gift"), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor), for: .normal)
|
||||
self.suggestedPostButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/SuggestPost"), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor), for: .normal)
|
||||
self.giftButton.setImage(generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Accessory Panels/Gift"), color: interfaceState.theme.chat.inputPanel.panelControlAccentColor), for: .normal)
|
||||
}
|
||||
|
||||
@ -431,11 +471,12 @@ public final class ChatChannelSubscriberInputPanelNode: ChatInputPanelNode {
|
||||
self.helpButton.isHidden = true
|
||||
//TODO:release
|
||||
self.suggestedPostButton.isHidden = false
|
||||
self.presentGiftTooltip()
|
||||
self.presentGiftOrSuggestTooltip()
|
||||
} else if case .broadcast = peer.info {
|
||||
self.giftButton.isHidden = true
|
||||
self.helpButton.isHidden = true
|
||||
self.suggestedPostButton.isHidden = false
|
||||
self.presentGiftOrSuggestTooltip()
|
||||
} else if peer.flags.contains(.isGigagroup), self.action == .muteNotifications || self.action == .unmuteNotifications {
|
||||
self.giftButton.isHidden = true
|
||||
self.helpButton.isHidden = false
|
||||
|
@ -32,6 +32,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Chat/ChatMediaInputStickerGridItem",
|
||||
"//submodules/PremiumUI",
|
||||
"//submodules/TelegramUI/Components/LottieComponent",
|
||||
"//submodules/Components/BundleIconComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -23,6 +23,7 @@ import ChatMediaInputStickerGridItem
|
||||
import UndoUI
|
||||
import PremiumUI
|
||||
import LottieComponent
|
||||
import BundleIconComponent
|
||||
|
||||
private protocol ChatEmptyNodeContent {
|
||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, subject: ChatEmptyNode.Subject, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize
|
||||
@ -1367,16 +1368,27 @@ public final class ChatEmptyNodePremiumRequiredChatContent: ASDisplayNode, ChatE
|
||||
contentsHeight += iconBackgroundSize
|
||||
contentsHeight += iconTextSpacing
|
||||
|
||||
let iconSize = self.icon.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
let iconComponent: AnyComponent<Empty>
|
||||
if case let .customChatContents(customChatContents) = interfaceState.subject, case .postSuggestions = customChatContents.kind {
|
||||
iconComponent = AnyComponent(
|
||||
BundleIconComponent(
|
||||
name: "Chat/Empty Chat/PostSuggestions",
|
||||
tintColor: serviceColor.primaryText
|
||||
)
|
||||
)
|
||||
} else {
|
||||
iconComponent = AnyComponent(
|
||||
LottieComponent(
|
||||
content: LottieComponent.AppBundleContent(name: "PremiumRequired"),
|
||||
color: serviceColor.primaryText,
|
||||
size: CGSize(width: 120.0, height: 120.0),
|
||||
loop: true
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
let iconSize = self.icon.update(
|
||||
transition: .immediate,
|
||||
component: iconComponent,
|
||||
environment: {},
|
||||
containerSize: CGSize(width: maxWidth - sideInset * 2.0, height: 500.0)
|
||||
)
|
||||
|
@ -26,6 +26,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let contentBackgroundNode: ASDisplayNode
|
||||
private let titleNode: ASTextNode
|
||||
private let textNode: ASTextNode?
|
||||
private let cancelButton: HighlightableButtonNode
|
||||
private let doneButton: SolidRoundedButtonNode
|
||||
private let onlineButton: SolidRoundedButtonNode
|
||||
@ -93,6 +94,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
self.contentBackgroundNode.backgroundColor = backgroundColor
|
||||
|
||||
let title: String
|
||||
var text: String?
|
||||
switch mode {
|
||||
case .scheduledMessages:
|
||||
title = self.presentationData.strings.Conversation_ScheduleMessage_Title
|
||||
@ -101,6 +103,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
case .suggestPost:
|
||||
//TODO:localize
|
||||
title = "Time"
|
||||
text = "Set the date and time you want\nyour message to be published."
|
||||
}
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
@ -108,6 +111,19 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
self.titleNode.accessibilityLabel = title
|
||||
self.titleNode.accessibilityTraits = [.staticText]
|
||||
|
||||
if let text {
|
||||
let textNode = ASTextNode()
|
||||
textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: textColor)
|
||||
textNode.maximumNumberOfLines = 0
|
||||
textNode.textAlignment = .center
|
||||
textNode.lineSpacing = 0.2
|
||||
textNode.accessibilityLabel = text
|
||||
textNode.accessibilityTraits = [.staticText]
|
||||
self.textNode = textNode
|
||||
} else {
|
||||
self.textNode = nil
|
||||
}
|
||||
|
||||
self.cancelButton = HighlightableButtonNode()
|
||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: accentColor, for: .normal)
|
||||
self.cancelButton.accessibilityLabel = self.presentationData.strings.Common_Cancel
|
||||
@ -146,6 +162,9 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
self.backgroundNode.addSubnode(self.effectNode)
|
||||
self.backgroundNode.addSubnode(self.contentBackgroundNode)
|
||||
self.contentContainerNode.addSubnode(self.titleNode)
|
||||
if let textNode = self.textNode {
|
||||
self.contentContainerNode.addSubnode(textNode)
|
||||
}
|
||||
self.contentContainerNode.addSubnode(self.cancelButton)
|
||||
self.contentContainerNode.addSubnode(self.doneButton)
|
||||
if case .scheduledMessages(true) = self.mode {
|
||||
@ -422,6 +441,13 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
}
|
||||
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 0.0)
|
||||
|
||||
let textControlSpacing: CGFloat = -8.0
|
||||
let textDoneSpacing: CGFloat = 21.0
|
||||
let textSize = self.textNode?.measure(CGSize(width: width, height: 1000.0))
|
||||
if let textSize {
|
||||
contentHeight += textSize.height + textControlSpacing + textDoneSpacing
|
||||
}
|
||||
|
||||
let sideInset = floor((layout.size.width - width) / 2.0)
|
||||
let contentContainerFrame = CGRect(origin: CGPoint(x: sideInset, y: layout.size.height - contentHeight), size: CGSize(width: width, height: contentHeight))
|
||||
let contentFrame = contentContainerFrame
|
||||
@ -446,7 +472,13 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, ASScrollViewDel
|
||||
|
||||
let buttonInset: CGFloat = 16.0
|
||||
let doneButtonHeight = self.doneButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
|
||||
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 16.0 - buttonOffset, width: contentFrame.width, height: doneButtonHeight))
|
||||
let doneButtonFrame = CGRect(x: buttonInset, y: contentHeight - doneButtonHeight - insets.bottom - 16.0 - buttonOffset, width: contentFrame.width, height: doneButtonHeight)
|
||||
transition.updateFrame(node: self.doneButton, frame: doneButtonFrame)
|
||||
|
||||
if let textNode = self.textNode, let textSize {
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((contentFrame.width - textSize.width) / 2.0), y: doneButtonFrame.minY - textDoneSpacing - textSize.height), size: textSize)
|
||||
transition.updateFrame(node: textNode, frame: textFrame)
|
||||
}
|
||||
|
||||
let onlineButtonHeight = self.onlineButton.updateLayout(width: contentFrame.width - buttonInset * 2.0, transition: transition)
|
||||
transition.updateFrame(node: self.onlineButton, frame: CGRect(x: buttonInset, y: contentHeight - onlineButtonHeight - cleanInsets.bottom - 16.0, width: contentFrame.width, height: onlineButtonHeight))
|
||||
|
@ -23,6 +23,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/ButtonComponent",
|
||||
"//submodules/Components/BundleIconComponent",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/TelegramUI/Components/ListItemComponentAdaptor",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -12,11 +12,12 @@ import ComponentFlow
|
||||
import ButtonComponent
|
||||
import BundleIconComponent
|
||||
import MultilineTextComponent
|
||||
import ListItemComponentAdaptor
|
||||
|
||||
private let textFont = Font.with(size: 17.0, traits: .monospacedNumbers)
|
||||
private let smallTextFont = Font.with(size: 13.0, traits: .monospacedNumbers)
|
||||
|
||||
public final class MessagePriceItem: ListViewItem, ItemListItem {
|
||||
public final class MessagePriceItem: Equatable, ListViewItem, ItemListItem, ListItemComponentAdaptor.ItemGenerator {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let isEnabled: Bool
|
||||
@ -75,11 +76,46 @@ public final class MessagePriceItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func item() -> ListViewItem {
|
||||
return self
|
||||
}
|
||||
|
||||
public static func ==(lhs: MessagePriceItem, rhs: MessagePriceItem) -> Bool {
|
||||
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.isEnabled != rhs.isEnabled {
|
||||
return false
|
||||
}
|
||||
if lhs.minValue != rhs.minValue {
|
||||
return false
|
||||
}
|
||||
if lhs.value != rhs.value {
|
||||
return false
|
||||
}
|
||||
if lhs.price != rhs.price {
|
||||
return false
|
||||
}
|
||||
if (lhs.openSetCustom == nil) != (rhs.openSetCustom == nil) {
|
||||
return false
|
||||
}
|
||||
if (lhs.openPremiumInfo == nil) != (rhs.openPremiumInfo == nil) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private class MessagePriceItemNode: ListViewItemNode {
|
||||
private struct Amount: Equatable {
|
||||
private let sliderSteps: [Int]
|
||||
private let minRealValue: Int
|
||||
private let maxRealValue: Int
|
||||
let maxSliderValue: Int
|
||||
private let isLogarithmic: Bool
|
||||
@ -87,9 +123,9 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
private(set) var realValue: Int
|
||||
private(set) var sliderValue: Int
|
||||
|
||||
private static func makeSliderSteps(maxRealValue: Int, isLogarithmic: Bool) -> [Int] {
|
||||
private static func makeSliderSteps(minRealValue: Int, maxRealValue: Int, isLogarithmic: Bool) -> [Int] {
|
||||
if isLogarithmic {
|
||||
var sliderSteps: [Int] = [ 1, 10, 50, 100, 500, 1_000, 2_000, 5_000, 7_500, 10_000 ]
|
||||
var sliderSteps: [Int] = [ minRealValue, 10, 50, 100, 500, 1_000, 2_000, 5_000, 7_500, 10_000 ]
|
||||
sliderSteps.removeAll(where: { $0 >= maxRealValue })
|
||||
sliderSteps.append(maxRealValue)
|
||||
return sliderSteps
|
||||
@ -126,8 +162,9 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
init(realValue: Int, maxRealValue: Int, maxSliderValue: Int, isLogarithmic: Bool) {
|
||||
self.sliderSteps = Amount.makeSliderSteps(maxRealValue: maxRealValue, isLogarithmic: isLogarithmic)
|
||||
init(realValue: Int, minRealValue: Int, maxRealValue: Int, maxSliderValue: Int, isLogarithmic: Bool) {
|
||||
self.sliderSteps = Amount.makeSliderSteps(minRealValue: minRealValue, maxRealValue: maxRealValue, isLogarithmic: isLogarithmic)
|
||||
self.minRealValue = minRealValue
|
||||
self.maxRealValue = maxRealValue
|
||||
self.maxSliderValue = maxSliderValue
|
||||
self.isLogarithmic = isLogarithmic
|
||||
@ -136,8 +173,9 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
self.sliderValue = Amount.remapValueToSlider(realValue: self.realValue, maxSliderValue: self.maxSliderValue, steps: self.sliderSteps)
|
||||
}
|
||||
|
||||
init(sliderValue: Int, maxRealValue: Int, maxSliderValue: Int, isLogarithmic: Bool) {
|
||||
self.sliderSteps = Amount.makeSliderSteps(maxRealValue: maxRealValue, isLogarithmic: isLogarithmic)
|
||||
init(sliderValue: Int, minRealValue: Int, maxRealValue: Int, maxSliderValue: Int, isLogarithmic: Bool) {
|
||||
self.sliderSteps = Amount.makeSliderSteps(minRealValue: minRealValue, maxRealValue: maxRealValue, isLogarithmic: isLogarithmic)
|
||||
self.minRealValue = minRealValue
|
||||
self.maxRealValue = maxRealValue
|
||||
self.maxSliderValue = maxSliderValue
|
||||
self.isLogarithmic = isLogarithmic
|
||||
@ -147,11 +185,11 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
}
|
||||
|
||||
func withRealValue(_ realValue: Int) -> Amount {
|
||||
return Amount(realValue: realValue, maxRealValue: self.maxRealValue, maxSliderValue: self.maxSliderValue, isLogarithmic: self.isLogarithmic)
|
||||
return Amount(realValue: realValue, minRealValue: self.minRealValue, maxRealValue: self.maxRealValue, maxSliderValue: self.maxSliderValue, isLogarithmic: self.isLogarithmic)
|
||||
}
|
||||
|
||||
func withSliderValue(_ sliderValue: Int) -> Amount {
|
||||
return Amount(sliderValue: sliderValue, maxRealValue: self.maxRealValue, maxSliderValue: self.maxSliderValue, isLogarithmic: self.isLogarithmic)
|
||||
return Amount(sliderValue: sliderValue, minRealValue: self.minRealValue, maxRealValue: self.maxRealValue, maxSliderValue: self.maxSliderValue, isLogarithmic: self.isLogarithmic)
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +209,7 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
|
||||
private let button: ComponentView<Empty>
|
||||
|
||||
private var amount: Amount = Amount(realValue: 1, maxRealValue: 1000, maxSliderValue: 1000, isLogarithmic: true)
|
||||
private var amount: Amount = Amount(realValue: 1, minRealValue: 1, maxRealValue: 1000, maxSliderValue: 1000, isLogarithmic: true)
|
||||
|
||||
private var item: MessagePriceItem?
|
||||
private var layoutParams: ListViewItemLayoutParams?
|
||||
@ -195,7 +233,9 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
self.centerTextButtonBackground = UIImageView()
|
||||
self.centerLeftTextNode = ImmediateTextNode()
|
||||
self.centerLeftTextNode.isUserInteractionEnabled = false
|
||||
self.centerLeftTextNode.displaysAsynchronously = false
|
||||
self.centerRightTextNode = ImmediateTextNode()
|
||||
self.centerRightTextNode.displaysAsynchronously = false
|
||||
self.centerRightTextNode.isUserInteractionEnabled = false
|
||||
|
||||
self.lockIconNode = ASImageNode()
|
||||
@ -226,7 +266,7 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
sliderView.lineSize = 4.0
|
||||
sliderView.disablesInteractiveTransitionGestureRecognizer = true
|
||||
if let item = self.item, let params = self.layoutParams {
|
||||
self.amount = Amount(realValue: Int(item.value), maxRealValue: Int(item.maxValue), maxSliderValue: 999, isLogarithmic: true)
|
||||
self.amount = Amount(realValue: Int(item.value), minRealValue: Int(item.minValue), maxRealValue: Int(item.maxValue), maxSliderValue: 999, isLogarithmic: true)
|
||||
|
||||
sliderView.minimumValue = 0
|
||||
sliderView.startValue = 0
|
||||
@ -328,7 +368,9 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
strongSelf.leftTextNode.attributedText = NSAttributedString(string: "\(item.minValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||
strongSelf.rightTextNode.attributedText = NSAttributedString(string: "\(item.maxValue)", font: Font.regular(13.0), textColor: item.theme.list.itemSecondaryTextColor)
|
||||
|
||||
let centralLeftText = item.strings.Privacy_Messages_Stars(Int32(item.value))
|
||||
//TODO:localize
|
||||
let centralLeftText = item.value == 0 ? "Free" : item.strings.Privacy_Messages_Stars(Int32(item.value))
|
||||
|
||||
strongSelf.centerLeftTextNode.attributedText = NSAttributedString(string: centralLeftText, font: textFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.centerRightTextNode.attributedText = NSAttributedString(string: item.price, font: smallTextFont, textColor: item.openSetCustom != nil ? item.theme.list.itemAccentColor.withMultipliedAlpha(0.5) : item.theme.list.itemSecondaryTextColor)
|
||||
|
||||
@ -336,7 +378,7 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
let rightTextSize = strongSelf.rightTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
|
||||
let centerLeftTextSize = strongSelf.centerLeftTextNode.updateLayout(CGSize(width: 200.0, height: 100.0))
|
||||
let centerRightTextSize = strongSelf.centerRightTextNode.updateLayout(CGSize(width: 200.0, height: 100.0))
|
||||
let centerSpacing: CGFloat = 6.0
|
||||
let centerSpacing: CGFloat = item.price.isEmpty ? 0.0 : 6.0
|
||||
|
||||
let sideInset: CGFloat = 18.0
|
||||
|
||||
@ -386,7 +428,7 @@ private class MessagePriceItemNode: ListViewItemNode {
|
||||
}
|
||||
|
||||
if !sliderView.isTracking {
|
||||
strongSelf.amount = Amount(realValue: Int(item.value), maxRealValue: Int(item.maxValue), maxSliderValue: 999, isLogarithmic: true)
|
||||
strongSelf.amount = Amount(realValue: Int(item.value), minRealValue: Int(item.minValue), maxRealValue: Int(item.maxValue), maxSliderValue: 999, isLogarithmic: true)
|
||||
sliderView.value = CGFloat(strongSelf.amount.sliderValue)
|
||||
}
|
||||
}
|
||||
|
@ -2207,7 +2207,7 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
}))
|
||||
|
||||
//TODO:localize
|
||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPostSuggestionsSettings, label: .text("Off"), additionalBadgeLabel: presentationData.strings.Settings_New, text: "Post Suggestions", icon: UIImage(bundleImageName: "Chat/Info/GroupDiscussionIcon"), action: {
|
||||
items[.peerSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemPostSuggestionsSettings, label: .text("Off"), additionalBadgeLabel: presentationData.strings.Settings_New, text: "Post Suggestions", icon: UIImage(bundleImageName: "Chat/Info/PostSuggestionsIcon"), action: {
|
||||
interaction.editingOpenPostSuggestionsSetup()
|
||||
}))
|
||||
}
|
||||
|
@ -27,10 +27,11 @@ swift_library(
|
||||
"//submodules/Components/BundleIconComponent",
|
||||
"//submodules/TextFormat",
|
||||
"//submodules/TelegramUI/Components/ListSectionComponent",
|
||||
"//submodules/TelegramUI/Components/ListItemSliderSelectorComponent",
|
||||
"//submodules/TelegramUI/Components/ListSwitchItemComponent",
|
||||
"//submodules/TelegramUI/Components/ListActionItemComponent",
|
||||
"//submodules/TelegramStringFormatting",
|
||||
"//submodules/TelegramUI/Components/ListItemComponentAdaptor",
|
||||
"//submodules/TelegramUI/Components/PeerInfo/MessagePriceItem",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -17,23 +17,27 @@ import ListSectionComponent
|
||||
import BundleIconComponent
|
||||
import LottieComponent
|
||||
import ListSwitchItemComponent
|
||||
import ListItemSliderSelectorComponent
|
||||
import ListSwitchItemComponent
|
||||
import ListActionItemComponent
|
||||
import Markdown
|
||||
import TelegramStringFormatting
|
||||
import MessagePriceItem
|
||||
import ListItemComponentAdaptor
|
||||
|
||||
final class PostSuggestionsSettingsScreenComponent: Component {
|
||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||
|
||||
let context: AccountContext
|
||||
let usdWithdrawRate: Int64
|
||||
let completion: () -> Void
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
usdWithdrawRate: Int64,
|
||||
completion: @escaping () -> Void
|
||||
) {
|
||||
self.context = context
|
||||
self.usdWithdrawRate = usdWithdrawRate
|
||||
self.completion = completion
|
||||
}
|
||||
|
||||
@ -315,26 +319,50 @@ final class PostSuggestionsSettingsScreenComponent: Component {
|
||||
|
||||
var contentSectionItems: [AnyComponentWithIdentity<Empty>] = []
|
||||
|
||||
let sliderValueList = (0 ... 10000).map { i -> String in
|
||||
return "\(i)"
|
||||
}
|
||||
//TODO:localize
|
||||
let sliderTitle: String
|
||||
let sliderSecondaryTitle: String?
|
||||
let usdAmount = Double(self.starCount) * 0.013
|
||||
let usdAmountString = formatCurrencyAmount(Int64(usdAmount * 100.0), currency: "USD")
|
||||
if self.starCount == 0 {
|
||||
sliderTitle = "Free"
|
||||
sliderSecondaryTitle = nil
|
||||
} else if self.starCount == 1 {
|
||||
sliderTitle = "\(self.starCount) Star"
|
||||
sliderSecondaryTitle = "~\(usdAmountString)"
|
||||
} else {
|
||||
sliderTitle = "\(self.starCount) Stars"
|
||||
sliderSecondaryTitle = "~\(usdAmountString)"
|
||||
}
|
||||
let usdRate = Double(component.usdWithdrawRate) / 1000.0 / 100.0
|
||||
let price = self.starCount == 0 ? "" : "≈\(formatTonUsdValue(Int64(self.starCount), divide: false, rate: usdRate, dateTimeFormat: presentationData.dateTimeFormat))"
|
||||
|
||||
contentSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemSliderSelectorComponent(
|
||||
contentSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemComponentAdaptor(
|
||||
itemGenerator: MessagePriceItem(
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
isEnabled: true, minValue: 0, maxValue: 10000,
|
||||
value: Int64(self.starCount),
|
||||
price: price,
|
||||
sectionId: 0,
|
||||
updated: { [weak self] value, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.starCount = Int(value)
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
},
|
||||
openSetCustom: { [weak self] in
|
||||
guard let self, let component = self.component, let environment = self.environment else {
|
||||
return
|
||||
}
|
||||
|
||||
let currentAmount: StarsAmount = StarsAmount(value: Int64(self.starCount), nanos: 0)
|
||||
let starsScreen = component.context.sharedContext.makeStarsWithdrawalScreen(context: component.context, subject: .enterAmount(current: currentAmount, minValue: StarsAmount(value: 0, nanos: 0), fractionAfterCommission: 85, kind: .postSuggestion), completion: { [weak self] amount in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
self.starCount = Int(amount)
|
||||
if !self.isUpdating {
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
})
|
||||
environment.controller()?.push(starsScreen)
|
||||
},
|
||||
openPremiumInfo: nil
|
||||
),
|
||||
params: ListViewItemLayoutParams(width: availableSize.width - sideInset * 2.0, leftInset: 0.0, rightInset: 0.0, availableHeight: 10000.0, isStandalone: true)
|
||||
))))
|
||||
/*contentSectionItems.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemSliderSelectorComponent(
|
||||
theme: environment.theme,
|
||||
content: .discrete(ListItemSliderSelectorComponent.Discrete(
|
||||
values: sliderValueList.map { item in
|
||||
@ -353,7 +381,7 @@ final class PostSuggestionsSettingsScreenComponent: Component {
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
))
|
||||
))))
|
||||
))))*/
|
||||
|
||||
let contentSectionSize = self.contentSection.update(
|
||||
transition: transition,
|
||||
@ -445,8 +473,11 @@ public final class PostSuggestionsSettingsScreen: ViewControllerComponentContain
|
||||
) {
|
||||
self.context = context
|
||||
|
||||
let configuration = StarsSubscriptionConfiguration.with(appConfiguration: context.currentAppConfiguration.with({ $0 }))
|
||||
|
||||
super.init(context: context, component: PostSuggestionsSettingsScreenComponent(
|
||||
context: context,
|
||||
usdWithdrawRate: configuration.usdWithdrawRate,
|
||||
completion: completion
|
||||
), navigationBarAppearance: .default, theme: .default, updatedPresentationData: nil)
|
||||
|
||||
|
@ -156,13 +156,18 @@ private final class SheetContent: CombinedComponent {
|
||||
minAmount = StarsAmount(value: resaleConfiguration.starGiftResaleMinAmount, nanos: 0)
|
||||
maxAmount = StarsAmount(value: resaleConfiguration.starGiftResaleMaxAmount, nanos: 0)
|
||||
amountLabel = nil
|
||||
case .paidMessages:
|
||||
case let .paidMessages(_, minAmountValue, _, kind):
|
||||
//TODO:localize
|
||||
titleString = "Price per Message"
|
||||
switch kind {
|
||||
case .privacy:
|
||||
titleString = "Price per Message"
|
||||
case .postSuggestion:
|
||||
titleString = "Price for each Suggestion"
|
||||
}
|
||||
amountTitle = "PRICE IN STARS"
|
||||
amountPlaceholder = "Enter Price"
|
||||
|
||||
minAmount = StarsAmount(value: 1, nanos: 0)
|
||||
minAmount = StarsAmount(value: minAmountValue, nanos: 0)
|
||||
maxAmount = StarsAmount(value: resaleConfiguration.paidMessageMaxAmount, nanos: 0)
|
||||
amountLabel = nil
|
||||
}
|
||||
@ -289,10 +294,10 @@ private final class SheetContent: CombinedComponent {
|
||||
text: .plain(amountInfoString),
|
||||
maximumNumberOfLines: 0
|
||||
))
|
||||
case .paidMessages:
|
||||
case let .paidMessages(_, _, fractionAfterCommission, _):
|
||||
let amountInfoString: NSAttributedString
|
||||
if let value = state.amount?.value, value > 0 {
|
||||
let fullValue: Int64 = Int64(value) * 1_000_000_000 * 80 / 100
|
||||
let fullValue: Int64 = Int64(value) * 1_000_000_000 * Int64(fractionAfterCommission) / 100
|
||||
let amountValue = StarsAmount(value: fullValue / 1_000_000_000, nanos: Int32(fullValue % 1_000_000_000))
|
||||
amountInfoString = NSAttributedString(attributedString: parseMarkdownIntoAttributedString("You will receive **\(amountValue) Stars**.", attributes: amountMarkdownAttributes, textAlignment: .natural))
|
||||
} else {
|
||||
@ -457,7 +462,7 @@ private final class SheetContent: CombinedComponent {
|
||||
amount = nil
|
||||
case .starGiftResell:
|
||||
amount = nil
|
||||
case let .paidMessages(initialValue):
|
||||
case let .paidMessages(initialValue, _, _, _):
|
||||
amount = StarsAmount(value: initialValue, nanos: 0)
|
||||
}
|
||||
|
||||
@ -580,7 +585,7 @@ public final class StarsWithdrawScreen: ViewControllerComponentContainer {
|
||||
case paidMedia(Int64?)
|
||||
case reaction(Int64?)
|
||||
case starGiftResell(Bool)
|
||||
case paidMessages(Int64)
|
||||
case paidMessages(current: Int64, minValue: Int64, fractionAfterCommission: Int, kind: StarsWithdrawalScreenSubject.PaidMessageKind)
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PostSuggestions.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PostSuggestions.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "postsuggestions.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PostSuggestions.imageset/postsuggestions.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Empty Chat/PostSuggestions.imageset/postsuggestions.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Info/PostSuggestionsIcon.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Info/PostSuggestionsIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "ic_discussion.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Info/PostSuggestionsIcon.imageset/ic_discussion.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Info/PostSuggestionsIcon.imageset/ic_discussion.pdf
vendored
Normal file
Binary file not shown.
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "postsuggestionsbutton.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
@ -2111,6 +2111,36 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
case .postSuggestions:
|
||||
//TODO:release
|
||||
actions.removeAll()
|
||||
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_MessageDialogEdit, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Edit"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { c, f in
|
||||
interfaceInteraction.setupEditMessage(messages[0].id, { transition in
|
||||
f(.custom(transition))
|
||||
})
|
||||
})))
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.ScheduledMessages_EditTime, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Schedule"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
controllerInteraction.editScheduledMessagesTime(messages.map { $0.id })
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
actions.append(.action(ContextMenuActionItem(text: "Edit Price", icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Tag"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
f(.dismissWithoutContent)
|
||||
})))
|
||||
actions.append(.action(ContextMenuActionItem(text: "Delete", textColor: .destructive, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.actionSheet.destructiveActionTextColor)
|
||||
}, action: { controller, f in
|
||||
interfaceInteraction.deleteMessages(messages, controller, f)
|
||||
})))
|
||||
actions.append(.separator)
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let action: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)? = nil
|
||||
actions.append(.action(ContextMenuActionItem(text: "Deleting suggested post will auto-refund your order.", textColor: .primary, textLayout: .multiline, textFont: .custom(font: Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 0.8)), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
||||
return nil
|
||||
}, iconSource: nil, action: action)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Stories/AvatarStoryIndicatorComponent",
|
||||
"//submodules/Components/BalancedTextComponent",
|
||||
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/ShimmerEffect",
|
||||
],
|
||||
visibility = [
|
||||
|
@ -17,6 +17,7 @@ import AvatarStoryIndicatorComponent
|
||||
import AccountContext
|
||||
import Markdown
|
||||
import BalancedTextComponent
|
||||
import MultilineTextComponent
|
||||
import MultilineTextWithEntitiesComponent
|
||||
import ShimmerEffect
|
||||
|
||||
@ -113,6 +114,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
private let context: AccountContext?
|
||||
|
||||
private let text: TooltipScreen.Text
|
||||
private let textBadge: String?
|
||||
private let textAlignment: TooltipScreen.Alignment
|
||||
private let balancedTextLayout: Bool
|
||||
private let constrainWidth: CGFloat?
|
||||
@ -148,6 +150,8 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
private var avatarNode: AvatarNode?
|
||||
private var avatarStoryIndicator: ComponentView<Empty>?
|
||||
private let textView = ComponentView<Empty>()
|
||||
private var textBadgeView: ComponentView<Empty>?
|
||||
private var textBadgeBackgroundView: ComponentView<Empty>?
|
||||
private var closeButtonNode: HighlightableButtonNode?
|
||||
private var actionButtonNode: HighlightableButtonNode?
|
||||
|
||||
@ -166,6 +170,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
account: Account,
|
||||
sharedContext: SharedAccountContext,
|
||||
text: TooltipScreen.Text,
|
||||
textBadge: String?,
|
||||
textAlignment: TooltipScreen.Alignment,
|
||||
balancedTextLayout: Bool,
|
||||
constrainWidth: CGFloat?,
|
||||
@ -390,6 +395,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
|
||||
self.fontSize = fontSize
|
||||
self.text = text
|
||||
self.textBadge = textBadge
|
||||
self.textAlignment = textAlignment
|
||||
self.balancedTextLayout = balancedTextLayout
|
||||
self.constrainWidth = constrainWidth
|
||||
@ -658,18 +664,48 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
)
|
||||
}
|
||||
|
||||
let textBadgeSpacing: CGFloat = 9.0
|
||||
let textBadgeRightInset: CGFloat = 5.0
|
||||
|
||||
var textContentSize = textSize
|
||||
var textBadgeSize: CGSize?
|
||||
if let textBadge = self.textBadge {
|
||||
let textBadgeView: ComponentView<Empty>
|
||||
if let current = self.textBadgeView {
|
||||
textBadgeView = current
|
||||
} else {
|
||||
textBadgeView = ComponentView()
|
||||
self.textBadgeView = textBadgeView
|
||||
}
|
||||
let textBadgeSizeValue = textBadgeView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: textBadge, font: Font.semibold(floor(self.fontSize * 0.8)), textColor: textColor))
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 100.0, height: 100.0)
|
||||
)
|
||||
textBadgeSize = textBadgeSizeValue
|
||||
textContentSize.width += textBadgeSpacing + textBadgeSizeValue.width + textBadgeRightInset
|
||||
} else {
|
||||
if let textBadgeView = self.textBadgeView {
|
||||
self.textBadgeView = nil
|
||||
textBadgeView.view?.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
var backgroundFrame: CGRect
|
||||
|
||||
var backgroundHeight: CGFloat
|
||||
switch self.tooltipStyle {
|
||||
case .default, .gradient:
|
||||
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0
|
||||
backgroundHeight = max(animationSize.height, textContentSize.height) + contentVerticalInset * 2.0
|
||||
case .wide:
|
||||
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0 + 4.0
|
||||
backgroundHeight = max(animationSize.height, textContentSize.height) + contentVerticalInset * 2.0 + 4.0
|
||||
case let .customBlur(_, inset):
|
||||
backgroundHeight = max(animationSize.height, textSize.height) + contentVerticalInset * 2.0 + inset * 2.0
|
||||
backgroundHeight = max(animationSize.height, textContentSize.height) + contentVerticalInset * 2.0 + inset * 2.0
|
||||
case .light:
|
||||
backgroundHeight = max(28.0, max(animationSize.height, textSize.height) + 4.0 * 2.0)
|
||||
backgroundHeight = max(28.0, max(animationSize.height, textContentSize.height) + 4.0 * 2.0)
|
||||
}
|
||||
if self.actionButtonNode != nil {
|
||||
backgroundHeight += 4.0
|
||||
@ -678,7 +714,7 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
var invertArrow = false
|
||||
switch self.location {
|
||||
case let .point(rect, arrowPosition):
|
||||
var backgroundWidth = textSize.width + contentInset * 2.0 + animationSize.width + animationSpacing
|
||||
var backgroundWidth = textContentSize.width + contentInset * 2.0 + animationSize.width + animationSpacing
|
||||
if self.closeButtonNode != nil || self.actionButtonNode != nil {
|
||||
backgroundWidth += buttonInset
|
||||
}
|
||||
@ -769,7 +805,6 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
}
|
||||
|
||||
let textFrame = CGRect(origin: CGPoint(x: contentInset + animationSize.width + animationSpacing, y: floor((backgroundHeight - textSize.height) / 2.0)), size: textSize)
|
||||
|
||||
if let textComponentView = self.textView.view {
|
||||
if textComponentView.superview == nil {
|
||||
textComponentView.layer.anchorPoint = CGPoint()
|
||||
@ -779,6 +814,49 @@ private final class TooltipScreenNode: ViewControllerTracingNode {
|
||||
transition.updateBounds(layer: textComponentView.layer, bounds: CGRect(origin: CGPoint(), size: textFrame.size))
|
||||
}
|
||||
|
||||
if let textBadgeView = self.textBadgeView, let textBadgeSize {
|
||||
let textBadgeFrame = CGRect(origin: CGPoint(x: textFrame.maxX + textBadgeSpacing, y: textFrame.minY + 2.0), size: textBadgeSize)
|
||||
if let textBadgeComponentView = textBadgeView.view {
|
||||
if textBadgeComponentView.superview == nil {
|
||||
textBadgeComponentView.layer.anchorPoint = CGPoint()
|
||||
self.containerNode.view.addSubview(textBadgeComponentView)
|
||||
}
|
||||
transition.updatePosition(layer: textBadgeComponentView.layer, position: textBadgeFrame.origin)
|
||||
transition.updateBounds(layer: textBadgeComponentView.layer, bounds: CGRect(origin: CGPoint(), size: textBadgeFrame.size))
|
||||
}
|
||||
|
||||
var textBadgeBackgroundFrame = textBadgeFrame.insetBy(dx: -4.0, dy: -3.0)
|
||||
textBadgeBackgroundFrame.size.height -= UIScreenPixel
|
||||
textBadgeBackgroundFrame.size.width -= UIScreenPixel
|
||||
|
||||
let textBadgeBackgroundView: ComponentView<Empty>
|
||||
if let current = self.textBadgeBackgroundView {
|
||||
textBadgeBackgroundView = current
|
||||
} else {
|
||||
textBadgeBackgroundView = ComponentView()
|
||||
self.textBadgeBackgroundView = textBadgeBackgroundView
|
||||
}
|
||||
let _ = textBadgeBackgroundView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(FilledRoundedRectangleComponent(
|
||||
color: UIColor(white: 1.0, alpha: 0.1),
|
||||
cornerRadius: .value(5.0),
|
||||
smoothCorners: true
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: textBadgeBackgroundFrame.size
|
||||
)
|
||||
if let textBadgeBackgroundComponentView = textBadgeBackgroundView.view {
|
||||
if textBadgeBackgroundComponentView.superview == nil, let textBadgeComponentView = textBadgeView.view {
|
||||
self.containerNode.view.insertSubview(textBadgeBackgroundComponentView, belowSubview: textBadgeComponentView)
|
||||
}
|
||||
textBadgeBackgroundComponentView.frame = textBadgeBackgroundFrame
|
||||
}
|
||||
} else if let textBadgeBackgroundView = self.textBadgeBackgroundView {
|
||||
self.textBadgeBackgroundView = nil
|
||||
textBadgeBackgroundView.view?.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let closeButtonNode = self.closeButtonNode {
|
||||
let closeSize = CGSize(width: 44.0, height: 44.0)
|
||||
transition.updateFrame(node: closeButtonNode, frame: CGRect(origin: CGPoint(x: textFrame.maxX - 6.0, y: floor((backgroundHeight - closeSize.height) / 2.0)), size: closeSize))
|
||||
@ -1120,6 +1198,7 @@ public final class TooltipScreen: ViewController {
|
||||
private let account: Account
|
||||
private let sharedContext: SharedAccountContext
|
||||
public let text: TooltipScreen.Text
|
||||
private let textBadge: String?
|
||||
public let textAlignment: TooltipScreen.Alignment
|
||||
private let balancedTextLayout: Bool
|
||||
private let constrainWidth: CGFloat?
|
||||
@ -1160,6 +1239,7 @@ public final class TooltipScreen: ViewController {
|
||||
account: Account,
|
||||
sharedContext: SharedAccountContext,
|
||||
text: TooltipScreen.Text,
|
||||
textBadge: String? = nil,
|
||||
textAlignment: TooltipScreen.Alignment = .natural,
|
||||
balancedTextLayout: Bool = false,
|
||||
constrainWidth: CGFloat? = nil,
|
||||
@ -1179,6 +1259,7 @@ public final class TooltipScreen: ViewController {
|
||||
self.account = account
|
||||
self.sharedContext = sharedContext
|
||||
self.text = text
|
||||
self.textBadge = textBadge
|
||||
self.textAlignment = textAlignment
|
||||
self.balancedTextLayout = balancedTextLayout
|
||||
self.constrainWidth = constrainWidth
|
||||
@ -1250,7 +1331,7 @@ public final class TooltipScreen: ViewController {
|
||||
}
|
||||
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = TooltipScreenNode(context: self.context, account: self.account, sharedContext: self.sharedContext, text: self.text, textAlignment: self.textAlignment, balancedTextLayout: self.balancedTextLayout, constrainWidth: self.constrainWidth, style: self.style, arrowStyle: self.arrowStyle, icon: self.icon, action: self.action, location: self.location, displayDuration: self.displayDuration, inset: self.inset, cornerRadius: self.cornerRadius, isShimmering: self.isShimmering, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||
self.displayNode = TooltipScreenNode(context: self.context, account: self.account, sharedContext: self.sharedContext, text: self.text, textBadge: self.textBadge, textAlignment: self.textAlignment, balancedTextLayout: self.balancedTextLayout, constrainWidth: self.constrainWidth, style: self.style, arrowStyle: self.arrowStyle, icon: self.icon, action: self.action, location: self.location, displayDuration: self.displayDuration, inset: self.inset, cornerRadius: self.cornerRadius, isShimmering: self.isShimmering, shouldDismissOnTouch: self.shouldDismissOnTouch, requestDismiss: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user