mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various improvements
This commit is contained in:
parent
5470ba80ec
commit
1cc27e2a20
@ -4,6 +4,7 @@ public enum ContextMenuActionContent {
|
||||
case text(title: String, accessibilityLabel: String)
|
||||
case icon(UIImage)
|
||||
case textWithIcon(title: String, icon: UIImage?)
|
||||
case textWithSubtitleAndIcon(title: String, subtitle: String, icon: UIImage?)
|
||||
}
|
||||
|
||||
public struct ContextMenuAction {
|
||||
|
@ -697,6 +697,10 @@ public class DrawingStickerEntityView: DrawingEntityView {
|
||||
|
||||
override func selectedTapAction() -> Bool {
|
||||
if case let .link(url, name, positionBelowText, largeMedia, size, compactSize, style) = self.stickerEntity.content {
|
||||
let values = [self.entity.scale, self.entity.scale * 0.93, self.entity.scale]
|
||||
let keyTimes = [0.0, 0.33, 1.0]
|
||||
self.layer.animateKeyframes(values: values as [NSNumber], keyTimes: keyTimes as [NSNumber], duration: 0.3, keyPath: "transform.scale")
|
||||
|
||||
let updatedStyle: DrawingStickerEntity.Content.LinkStyle
|
||||
switch style {
|
||||
case .white:
|
||||
|
@ -216,6 +216,7 @@ private var declaredEncodables: Void = {
|
||||
declareEncodable(SynchronizeViewStoriesOperation.self, f: { SynchronizeViewStoriesOperation(decoder: $0) })
|
||||
declareEncodable(SynchronizePeerStoriesOperation.self, f: { SynchronizePeerStoriesOperation(decoder: $0) })
|
||||
declareEncodable(MapVenue.self, f: { MapVenue(decoder: $0) })
|
||||
declareEncodable(MapGeoAddress.self, f: { MapGeoAddress(decoder: $0) })
|
||||
declareEncodable(TelegramMediaGiveaway.self, f: { TelegramMediaGiveaway(decoder: $0) })
|
||||
declareEncodable(TelegramMediaGiveawayResults.self, f: { TelegramMediaGiveawayResults(decoder: $0) })
|
||||
declareEncodable(WebpagePreviewMessageAttribute.self, f: { WebpagePreviewMessageAttribute(decoder: $0) })
|
||||
|
@ -15,7 +15,9 @@ final private class ContextMenuActionButton: HighlightTrackingButton {
|
||||
|
||||
final class ContextMenuActionNode: ASDisplayNode {
|
||||
private let textNode: ImmediateTextNode?
|
||||
private let subtitleNode: ImmediateTextNode?
|
||||
private var textSize: CGSize?
|
||||
private var subtitleSize: CGSize?
|
||||
private let iconView: UIImageView?
|
||||
private let action: () -> Void
|
||||
private let button: ContextMenuActionButton
|
||||
@ -28,37 +30,60 @@ final class ContextMenuActionNode: ASDisplayNode {
|
||||
self.actionArea.accessibilityTraits = .button
|
||||
|
||||
switch action.content {
|
||||
case let .text(title, accessibilityLabel):
|
||||
self.actionArea.accessibilityLabel = accessibilityLabel
|
||||
|
||||
let textNode = ImmediateTextNode()
|
||||
textNode.isUserInteractionEnabled = false
|
||||
textNode.displaysAsynchronously = false
|
||||
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: isDark ? .white : .black)
|
||||
textNode.isAccessibilityElement = false
|
||||
|
||||
self.textNode = textNode
|
||||
self.iconView = nil
|
||||
case let .textWithIcon(title, icon):
|
||||
let textNode = ImmediateTextNode()
|
||||
textNode.isUserInteractionEnabled = false
|
||||
textNode.displaysAsynchronously = false
|
||||
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black)
|
||||
textNode.isAccessibilityElement = false
|
||||
case let .text(title, accessibilityLabel):
|
||||
self.actionArea.accessibilityLabel = accessibilityLabel
|
||||
|
||||
let iconView = UIImageView()
|
||||
iconView.tintColor = isDark ? .white : .black
|
||||
iconView.image = icon
|
||||
|
||||
self.textNode = textNode
|
||||
self.iconView = iconView
|
||||
case let .icon(image):
|
||||
let iconView = UIImageView()
|
||||
iconView.tintColor = isDark ? .white : .black
|
||||
iconView.image = image
|
||||
|
||||
self.iconView = iconView
|
||||
self.textNode = nil
|
||||
let textNode = ImmediateTextNode()
|
||||
textNode.isUserInteractionEnabled = false
|
||||
textNode.displaysAsynchronously = false
|
||||
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: isDark ? .white : .black)
|
||||
textNode.isAccessibilityElement = false
|
||||
|
||||
self.textNode = textNode
|
||||
self.subtitleNode = nil
|
||||
self.iconView = nil
|
||||
case let .textWithIcon(title, icon):
|
||||
let textNode = ImmediateTextNode()
|
||||
textNode.isUserInteractionEnabled = false
|
||||
textNode.displaysAsynchronously = false
|
||||
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black)
|
||||
textNode.isAccessibilityElement = false
|
||||
|
||||
let iconView = UIImageView()
|
||||
iconView.tintColor = isDark ? .white : .black
|
||||
iconView.image = icon
|
||||
|
||||
self.textNode = textNode
|
||||
self.subtitleNode = nil
|
||||
self.iconView = iconView
|
||||
case let .textWithSubtitleAndIcon(title, subtitle, icon):
|
||||
let textNode = ImmediateTextNode()
|
||||
textNode.isUserInteractionEnabled = false
|
||||
textNode.displaysAsynchronously = false
|
||||
textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black)
|
||||
textNode.isAccessibilityElement = false
|
||||
|
||||
let subtitleNode = ImmediateTextNode()
|
||||
subtitleNode.isUserInteractionEnabled = false
|
||||
subtitleNode.displaysAsynchronously = false
|
||||
subtitleNode.attributedText = NSAttributedString(string: subtitle, font: Font.regular(12.0), textColor: (isDark ? UIColor.white : UIColor.black).withAlphaComponent(0.5))
|
||||
subtitleNode.isAccessibilityElement = false
|
||||
|
||||
let iconView = UIImageView()
|
||||
iconView.tintColor = isDark ? .white : .black
|
||||
iconView.image = icon
|
||||
|
||||
self.textNode = textNode
|
||||
self.subtitleNode = subtitleNode
|
||||
self.iconView = iconView
|
||||
case let .icon(image):
|
||||
let iconView = UIImageView()
|
||||
iconView.tintColor = isDark ? .white : .black
|
||||
iconView.image = image
|
||||
|
||||
self.iconView = iconView
|
||||
self.textNode = nil
|
||||
self.subtitleNode = nil
|
||||
}
|
||||
self.action = action.action
|
||||
|
||||
@ -74,6 +99,9 @@ final class ContextMenuActionNode: ASDisplayNode {
|
||||
if let textNode = self.textNode {
|
||||
self.addSubnode(textNode)
|
||||
}
|
||||
if let subtitleNode = self.subtitleNode {
|
||||
self.addSubnode(subtitleNode)
|
||||
}
|
||||
if let iconView = self.iconView {
|
||||
self.view.addSubview(iconView)
|
||||
}
|
||||
@ -119,7 +147,16 @@ final class ContextMenuActionNode: ASDisplayNode {
|
||||
self.textSize = textSize
|
||||
|
||||
var totalWidth = 0.0
|
||||
var totalHeight: CGFloat = 54.0
|
||||
totalWidth += textSize.width
|
||||
|
||||
if let subtitleNode = self.subtitleNode {
|
||||
let subtitleSize = subtitleNode.updateLayout(constrainedSize)
|
||||
self.subtitleSize = subtitleSize
|
||||
totalWidth = max(totalWidth, subtitleSize.width)
|
||||
totalHeight += 14.0
|
||||
}
|
||||
|
||||
if let image = self.iconView?.image {
|
||||
if totalWidth > 0.0 {
|
||||
totalWidth += 11.0
|
||||
@ -130,7 +167,7 @@ final class ContextMenuActionNode: ASDisplayNode {
|
||||
totalWidth += 36.0
|
||||
}
|
||||
|
||||
return CGSize(width: totalWidth, height: 54.0)
|
||||
return CGSize(width: totalWidth, height: totalHeight)
|
||||
} else if let iconView = self.iconView, let image = iconView.image {
|
||||
return CGSize(width: image.size.width + 36.0, height: 54.0)
|
||||
} else {
|
||||
@ -148,6 +185,9 @@ final class ContextMenuActionNode: ASDisplayNode {
|
||||
if let textSize = self.textSize {
|
||||
totalWidth += textSize.width
|
||||
}
|
||||
if let subtitleSize = self.subtitleSize {
|
||||
totalWidth = max(totalWidth, subtitleSize.width)
|
||||
}
|
||||
if let image = self.iconView?.image {
|
||||
if totalWidth > 0.0 {
|
||||
totalWidth += 11.0
|
||||
@ -155,8 +195,18 @@ final class ContextMenuActionNode: ASDisplayNode {
|
||||
totalWidth += image.size.width
|
||||
}
|
||||
|
||||
var totalTextHeight: CGFloat = 0.0
|
||||
if let textSize = self.textSize {
|
||||
totalTextHeight += textSize.height
|
||||
}
|
||||
if let subtitleSize = self.subtitleSize {
|
||||
totalTextHeight += subtitleSize.height
|
||||
}
|
||||
if let textNode = self.textNode, let textSize = self.textSize {
|
||||
textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - textSize.height) / 2.0)), size: textSize)
|
||||
textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - totalTextHeight) / 2.0)), size: textSize)
|
||||
}
|
||||
if let subtitleNode = self.subtitleNode, let subtitleSize = self.subtitleSize {
|
||||
subtitleNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - totalTextHeight) / 2.0) + totalTextHeight - subtitleSize.height), size: subtitleSize)
|
||||
}
|
||||
if let iconView = self.iconView, let image = iconView.image {
|
||||
let iconSize = image.size
|
||||
|
@ -175,12 +175,11 @@ final class ContextMenuNode: ASDisplayNode {
|
||||
|
||||
let separatorColor = self.isDark ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0xDCE3DC)
|
||||
|
||||
let height: CGFloat = 54.0
|
||||
var height: CGFloat = 54.0
|
||||
|
||||
let pageLeftSize = self.pageLeftNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height)
|
||||
let pageRightSize = self.pageRightNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height)
|
||||
|
||||
let maxPageWidth = layout.size.width - 20.0 - pageLeftSize.width - pageRightSize.width
|
||||
let handleWidth: CGFloat = 33.0
|
||||
|
||||
let maxPageWidth = layout.size.width - 20.0 - handleWidth * 2.0
|
||||
var absoluteActionOffsetX: CGFloat = 0.0
|
||||
|
||||
var pages: [Page] = []
|
||||
@ -188,7 +187,8 @@ final class ContextMenuNode: ASDisplayNode {
|
||||
if i != 0 {
|
||||
absoluteActionOffsetX += UIScreenPixel
|
||||
}
|
||||
let actionSize = self.actionNodes[i].measure(CGSize(width: layout.size.width, height: height))
|
||||
let actionSize = self.actionNodes[i].measure(CGSize(width: layout.size.width, height: 100.0))
|
||||
height = max(height, actionSize.height)
|
||||
if pages.isEmpty || (pages[pages.count - 1].width + actionSize.width) > maxPageWidth {
|
||||
pages.append(Page(range: i ..< (i + 1), width: actionSize.width, offsetX: absoluteActionOffsetX))
|
||||
} else {
|
||||
@ -212,6 +212,9 @@ final class ContextMenuNode: ASDisplayNode {
|
||||
separatorNode.isHidden = i == self.actionNodes.count - 1
|
||||
}
|
||||
|
||||
let pageLeftSize = self.pageLeftNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height)
|
||||
let pageRightSize = self.pageRightNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height)
|
||||
|
||||
self.pageCount = pages.count
|
||||
|
||||
if !pages.isEmpty {
|
||||
|
@ -123,6 +123,10 @@ public enum CodableDrawingEntity: Equatable {
|
||||
)
|
||||
case let .sticker(entity):
|
||||
if case let .link(url, _, _, _, _, _, _) = entity.content {
|
||||
var url = url
|
||||
if !url.hasPrefix("http://") && !url.hasPrefix("https://") {
|
||||
url = "https://\(url)"
|
||||
}
|
||||
return .link(
|
||||
coordinates: coordinates,
|
||||
url: url
|
||||
|
@ -319,7 +319,9 @@ private final class CreateLinkSheetComponent: CombinedComponent {
|
||||
|
||||
self.link = link?.url ?? ""
|
||||
self.name = link?.name ?? ""
|
||||
|
||||
self.positionBelowText = link?.positionBelowText ?? true
|
||||
self.largeMedia = link?.largeMedia
|
||||
|
||||
super.init()
|
||||
|
||||
self.linkDisposable.set((self.linkPromise.get()
|
||||
@ -463,10 +465,10 @@ private final class CreateLinkSheetComponent: CombinedComponent {
|
||||
let renderer = DrawingMessageRenderer(context: self.context, messages: [message], parentView: controller.view, isLink: true)
|
||||
renderer.render(completion: { result in
|
||||
completion(
|
||||
link,
|
||||
CreateLinkScreen.Result(
|
||||
url: link,
|
||||
url: self.link,
|
||||
name: self.name,
|
||||
webpage: !self.dismissed ? self.webpage : nil,
|
||||
positionBelowText: self.positionBelowText,
|
||||
largeMedia: self.largeMedia,
|
||||
image: !media.isEmpty ? result.dayImage : nil,
|
||||
@ -556,16 +558,26 @@ public final class CreateLinkScreen: ViewControllerComponentContainer {
|
||||
public struct Link: Equatable {
|
||||
let url: String
|
||||
let name: String?
|
||||
let positionBelowText: Bool
|
||||
let largeMedia: Bool?
|
||||
|
||||
init(url: String, name: String?) {
|
||||
init(
|
||||
url: String,
|
||||
name: String?,
|
||||
positionBelowText: Bool,
|
||||
largeMedia: Bool?
|
||||
) {
|
||||
self.url = url
|
||||
self.name = name
|
||||
self.positionBelowText = positionBelowText
|
||||
self.largeMedia = largeMedia
|
||||
}
|
||||
}
|
||||
|
||||
public struct Result {
|
||||
let url: String
|
||||
let name: String
|
||||
let webpage: TelegramMediaWebpage?
|
||||
let positionBelowText: Bool
|
||||
let largeMedia: Bool?
|
||||
let image: UIImage?
|
||||
@ -575,12 +587,12 @@ public final class CreateLinkScreen: ViewControllerComponentContainer {
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
fileprivate let completion: (String, CreateLinkScreen.Result) -> Void
|
||||
fileprivate let completion: (CreateLinkScreen.Result) -> Void
|
||||
|
||||
public init(
|
||||
context: AccountContext,
|
||||
link: CreateLinkScreen.Link?,
|
||||
completion: @escaping (String, CreateLinkScreen.Result) -> Void
|
||||
completion: @escaping (CreateLinkScreen.Result) -> Void
|
||||
) {
|
||||
self.context = context
|
||||
self.completion = completion
|
||||
|
@ -3300,6 +3300,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
if let self {
|
||||
if let location = entity as? DrawingLocationEntity {
|
||||
self.presentLocationPicker(location)
|
||||
} else if let sticker = entity as? DrawingStickerEntity, case .link = sticker.content {
|
||||
self.addOrEditLink(sticker)
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4478,34 +4480,66 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
self.controller?.present(contextController, in: .window(.root))
|
||||
}
|
||||
|
||||
func addLink() {
|
||||
func addOrEditLink(_ existingEntity: DrawingStickerEntity? = nil) {
|
||||
guard let controller = self.controller else {
|
||||
return
|
||||
}
|
||||
|
||||
var link: CreateLinkScreen.Link?
|
||||
if let existingEntity, case let .link(url, name, positionBelowText, largeMedia, _, _, _) = existingEntity.content {
|
||||
link = CreateLinkScreen.Link(
|
||||
url: url,
|
||||
name: name,
|
||||
positionBelowText: positionBelowText,
|
||||
largeMedia: largeMedia
|
||||
)
|
||||
}
|
||||
|
||||
let linkController = CreateLinkScreen(context: controller.context, link: nil, completion: { [weak self] url, result in
|
||||
let linkController = CreateLinkScreen(context: controller.context, link: link, completion: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
var linkStyle: DrawingStickerEntity.Content.LinkStyle
|
||||
if let existingEntity, case let .link(_, _, _, _, _, _, existingStyle) = existingEntity.content {
|
||||
if [.white, .black].contains(existingStyle), result.image == nil {
|
||||
switch existingStyle {
|
||||
case .white:
|
||||
linkStyle = .whiteCompact
|
||||
case .black:
|
||||
linkStyle = .blackCompact
|
||||
default:
|
||||
linkStyle = existingStyle
|
||||
}
|
||||
} else {
|
||||
linkStyle = existingStyle
|
||||
}
|
||||
} else {
|
||||
linkStyle = result.image != nil ? .white : .whiteCompact
|
||||
}
|
||||
|
||||
let entity = DrawingStickerEntity(
|
||||
content: .link(url, result.name, result.positionBelowText, result.largeMedia, result.image?.size, result.compactLightImage.size, result.image != nil ? .white : .whiteCompact)
|
||||
content: .link(result.url, result.name, result.positionBelowText, result.largeMedia, result.image?.size, result.compactLightImage.size, linkStyle)
|
||||
)
|
||||
entity.renderImage = result.image
|
||||
entity.secondaryRenderImage = result.nightImage
|
||||
entity.tertiaryRenderImage = result.compactLightImage
|
||||
entity.quaternaryRenderImage = result.compactDarkImage
|
||||
|
||||
|
||||
let fraction: CGFloat
|
||||
if let image = result.image {
|
||||
fraction = max(image.size.width, image.size.height) / 353.0
|
||||
} else {
|
||||
fraction = 1.0
|
||||
fraction = max(result.compactLightImage.size.width, result.compactLightImage.size.height) / 353.0
|
||||
}
|
||||
|
||||
if let existingEntity {
|
||||
self.entitiesView.remove(uuid: existingEntity.uuid, animated: true)
|
||||
}
|
||||
self.interaction?.insertEntity(
|
||||
entity,
|
||||
scale: min(6.0, 3.3 * fraction) * 0.5,
|
||||
position: nil
|
||||
scale: existingEntity?.scale ?? min(6.0, 3.3 * fraction) * 0.5,
|
||||
position: existingEntity?.position
|
||||
)
|
||||
})
|
||||
controller.push(linkController)
|
||||
@ -4786,7 +4820,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
}
|
||||
controller.addLink = { [weak self, weak controller] in
|
||||
if let self {
|
||||
self.addLink()
|
||||
self.addOrEditLink()
|
||||
|
||||
self.stickerScreen = nil
|
||||
controller?.dismiss(animated: true)
|
||||
@ -5724,7 +5758,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
||||
}, action: { [weak self] _, a in
|
||||
a(.default)
|
||||
|
||||
self?.node.addLink()
|
||||
self?.node.addOrEditLink()
|
||||
})))
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaEditor_Shortcut_Location, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Media Editor/LocationSmall"), color: theme.contextMenu.primaryColor)
|
||||
|
@ -1728,12 +1728,13 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL
|
||||
let ItemBotInfo = 10
|
||||
|
||||
if let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) {
|
||||
items[.peerDataSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text("@\(user.addressName ?? "")"), text: presentationData.strings.PeerInfo_BotLinks, icon: PresentationResourcesSettings.bot, action: {
|
||||
//TODO:localize
|
||||
items[.peerDataSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text("@\(user.addressName ?? "")"), text: "Username", icon: PresentationResourcesSettings.bot, action: {
|
||||
interaction.editingOpenPublicLinkSetup()
|
||||
}))
|
||||
|
||||
if "".isEmpty {
|
||||
let balance: Int64 = 1000
|
||||
let balance: Int64 = 2275
|
||||
items[.peerDataSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStars, label: .text(presentationData.strings.PeerInfo_Bot_Balance_Stars(Int32(balance))), text: presentationData.strings.PeerInfo_Bot_Balance, icon: PresentationResourcesSettings.stars, action: {
|
||||
interaction.editingOpenStars()
|
||||
}))
|
||||
|
@ -15,6 +15,7 @@ final class StarsBalanceComponent: Component {
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let count: Int64
|
||||
let rate: Double?
|
||||
let actionTitle: String
|
||||
let actionAvailable: Bool
|
||||
let buy: () -> Void
|
||||
|
||||
@ -24,6 +25,7 @@ final class StarsBalanceComponent: Component {
|
||||
dateTimeFormat: PresentationDateTimeFormat,
|
||||
count: Int64,
|
||||
rate: Double?,
|
||||
actionTitle: String,
|
||||
actionAvailable: Bool,
|
||||
buy: @escaping () -> Void
|
||||
) {
|
||||
@ -32,6 +34,7 @@ final class StarsBalanceComponent: Component {
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.count = count
|
||||
self.rate = rate
|
||||
self.actionTitle = actionTitle
|
||||
self.actionAvailable = actionAvailable
|
||||
self.buy = buy
|
||||
}
|
||||
@ -46,6 +49,9 @@ final class StarsBalanceComponent: Component {
|
||||
if lhs.dateTimeFormat != rhs.dateTimeFormat {
|
||||
return false
|
||||
}
|
||||
if lhs.actionTitle != rhs.actionTitle {
|
||||
return false
|
||||
}
|
||||
if lhs.actionAvailable != rhs.actionAvailable {
|
||||
return false
|
||||
}
|
||||
@ -111,11 +117,18 @@ final class StarsBalanceComponent: Component {
|
||||
}
|
||||
contentHeight += titleSize.height
|
||||
|
||||
let subtitleText: String
|
||||
if let rate = component.rate {
|
||||
subtitleText = "≈\(formatUsdValue(component.count, rate: rate))"
|
||||
} else {
|
||||
subtitleText = component.strings.Stars_Intro_YourBalance
|
||||
}
|
||||
|
||||
let subtitleSize = self.subtitle.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: component.strings.Stars_Intro_YourBalance, font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)),
|
||||
text: .plain(NSAttributedString(string: subtitleText, font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)),
|
||||
horizontalAlignment: .center
|
||||
)
|
||||
),
|
||||
@ -138,7 +151,7 @@ final class StarsBalanceComponent: Component {
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
SolidRoundedButtonComponent(
|
||||
title: component.strings.Stars_Intro_Buy,
|
||||
title: component.actionTitle,
|
||||
theme: SolidRoundedButtonComponent.Theme(theme: component.theme),
|
||||
height: 50.0,
|
||||
cornerRadius: 11.0,
|
||||
|
@ -13,7 +13,6 @@ import Postbox
|
||||
import MultilineTextComponent
|
||||
import BalancedTextComponent
|
||||
import Markdown
|
||||
import PremiumStarComponent
|
||||
import ListSectionComponent
|
||||
import BundleIconComponent
|
||||
import TextFormat
|
||||
@ -84,18 +83,12 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
|
||||
private let scrollContainerView: UIView
|
||||
|
||||
private let overscroll = ComponentView<Empty>()
|
||||
private let fade = ComponentView<Empty>()
|
||||
private let starView = ComponentView<Empty>()
|
||||
private let titleView = ComponentView<Empty>()
|
||||
private let descriptionView = ComponentView<Empty>()
|
||||
|
||||
private let chartView = ComponentView<Empty>()
|
||||
private let proceedsView = ComponentView<Empty>()
|
||||
private let balanceView = ComponentView<Empty>()
|
||||
|
||||
private let topBalanceTitleView = ComponentView<Empty>()
|
||||
private let topBalanceValueView = ComponentView<Empty>()
|
||||
private let topBalanceIconView = ComponentView<Empty>()
|
||||
|
||||
|
||||
private let panelContainer = ComponentView<StarsTransactionsPanelContainerEnvironment>()
|
||||
|
||||
private var component: StarsStatisticsScreenComponent?
|
||||
@ -115,8 +108,8 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
private var previousBalance: Int64?
|
||||
|
||||
private var allTransactionsContext: StarsTransactionsContext?
|
||||
private var incomingTransactionsContext: StarsTransactionsContext?
|
||||
private var outgoingTransactionsContext: StarsTransactionsContext?
|
||||
|
||||
private var cachedChevronImage: (UIImage, PresentationTheme)?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.headerOffsetContainer = UIView()
|
||||
@ -206,61 +199,21 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
let scrollBounds = self.scrollView.bounds
|
||||
|
||||
let isLockedAtPanels = scrollBounds.maxY == self.scrollView.contentSize.height
|
||||
|
||||
let topContentOffset = self.scrollView.contentOffset.y
|
||||
let navigationBackgroundAlpha = min(20.0, max(0.0, topContentOffset - 95.0)) / 20.0
|
||||
|
||||
let animatedTransition = Transition(animation: .curve(duration: 0.18, curve: .easeInOut))
|
||||
animatedTransition.setAlpha(view: self.navigationBackgroundView, alpha: navigationBackgroundAlpha)
|
||||
animatedTransition.setAlpha(layer: self.navigationSeparatorLayerContainer, alpha: navigationBackgroundAlpha)
|
||||
|
||||
if let navigationMetrics = self.navigationMetrics {
|
||||
let topInset: CGFloat = navigationMetrics.navigationHeight - 56.0
|
||||
|
||||
let titleOffset: CGFloat
|
||||
let titleScale: CGFloat
|
||||
let titleOffsetDelta = (topInset + 160.0) - (navigationMetrics.statusBarHeight + (navigationMetrics.navigationHeight - navigationMetrics.statusBarHeight) / 2.0)
|
||||
|
||||
var topContentOffset = self.scrollView.contentOffset.y
|
||||
|
||||
let navigationBackgroundAlpha = min(20.0, max(0.0, topContentOffset - 95.0)) / 20.0
|
||||
topContentOffset = topContentOffset + max(0.0, min(1.0, topContentOffset / titleOffsetDelta)) * 10.0
|
||||
titleOffset = topContentOffset
|
||||
let fraction = max(0.0, min(1.0, titleOffset / titleOffsetDelta))
|
||||
titleScale = 1.0 - fraction * 0.36
|
||||
|
||||
let headerTransition: Transition = .immediate
|
||||
|
||||
if let starView = self.starView.view {
|
||||
let starPosition = CGPoint(x: self.scrollView.frame.width / 2.0, y: topInset + starView.bounds.height / 2.0 - 30.0 - titleOffset * titleScale)
|
||||
|
||||
headerTransition.setPosition(view: starView, position: starPosition)
|
||||
headerTransition.setScale(view: starView, scale: titleScale)
|
||||
}
|
||||
|
||||
if let titleView = self.titleView.view {
|
||||
let titlePosition = CGPoint(x: scrollBounds.width / 2.0, y: max(topInset + 160.0 - titleOffset, navigationMetrics.statusBarHeight + (navigationMetrics.navigationHeight - navigationMetrics.statusBarHeight) / 2.0))
|
||||
|
||||
headerTransition.setPosition(view: titleView, position: titlePosition)
|
||||
headerTransition.setScale(view: titleView, scale: titleScale)
|
||||
}
|
||||
|
||||
let animatedTransition = Transition(animation: .curve(duration: 0.18, curve: .easeInOut))
|
||||
animatedTransition.setAlpha(view: self.navigationBackgroundView, alpha: navigationBackgroundAlpha)
|
||||
animatedTransition.setAlpha(layer: self.navigationSeparatorLayerContainer, alpha: navigationBackgroundAlpha)
|
||||
|
||||
let expansionDistance: CGFloat = 32.0
|
||||
var expansionDistanceFactor: CGFloat = abs(scrollBounds.maxY - self.scrollView.contentSize.height) / expansionDistance
|
||||
expansionDistanceFactor = max(0.0, min(1.0, expansionDistanceFactor))
|
||||
|
||||
transition.setAlpha(layer: self.navigationSeparatorLayer, alpha: expansionDistanceFactor)
|
||||
if let panelContainerView = self.panelContainer.view as? StarsTransactionsPanelContainerComponent.View {
|
||||
panelContainerView.updateNavigationMergeFactor(value: 1.0 - expansionDistanceFactor, transition: transition)
|
||||
}
|
||||
|
||||
let topBalanceAlpha = 1.0 - expansionDistanceFactor
|
||||
if let view = self.topBalanceTitleView.view {
|
||||
view.alpha = topBalanceAlpha
|
||||
}
|
||||
if let view = self.topBalanceValueView.view {
|
||||
view.alpha = topBalanceAlpha
|
||||
}
|
||||
if let view = self.topBalanceIconView.view {
|
||||
view.alpha = topBalanceAlpha
|
||||
}
|
||||
let expansionDistance: CGFloat = 32.0
|
||||
var expansionDistanceFactor: CGFloat = abs(scrollBounds.maxY - self.scrollView.contentSize.height) / expansionDistance
|
||||
expansionDistanceFactor = max(0.0, min(1.0, expansionDistanceFactor))
|
||||
|
||||
transition.setAlpha(layer: self.navigationSeparatorLayer, alpha: expansionDistanceFactor)
|
||||
if let panelContainerView = self.panelContainer.view as? StarsTransactionsPanelContainerComponent.View {
|
||||
panelContainerView.updateNavigationMergeFactor(value: 1.0 - expansionDistanceFactor, transition: transition)
|
||||
}
|
||||
|
||||
let _ = self.panelContainer.updateEnvironment(
|
||||
@ -290,6 +243,7 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
}
|
||||
|
||||
let environment = environment[ViewControllerComponentContainer.Environment.self].value
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
if self.stateDisposable == nil {
|
||||
self.stateDisposable = (component.starsContext.state
|
||||
@ -335,82 +289,14 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
let sideInsets: CGFloat = environment.safeInsets.left + environment.safeInsets.right + 16 * 2.0
|
||||
let bottomInset: CGFloat = environment.safeInsets.bottom
|
||||
|
||||
contentHeight += environment.statusBarHeight
|
||||
contentHeight += environment.navigationHeight
|
||||
contentHeight += 31.0
|
||||
|
||||
let starTransition: Transition = .immediate
|
||||
|
||||
var topBackgroundColor = environment.theme.list.plainBackgroundColor
|
||||
let bottomBackgroundColor = environment.theme.list.blocksBackgroundColor
|
||||
if environment.theme.overallDarkAppearance {
|
||||
topBackgroundColor = bottomBackgroundColor
|
||||
}
|
||||
|
||||
let overscrollSize = self.overscroll.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(Rectangle(color: topBackgroundColor)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width, height: 1000.0)
|
||||
)
|
||||
let overscrollFrame = CGRect(origin: CGPoint(x: 0.0, y: -overscrollSize.height), size: overscrollSize)
|
||||
if let overscrollView = self.overscroll.view {
|
||||
if overscrollView.superview == nil {
|
||||
self.scrollView.addSubview(overscrollView)
|
||||
}
|
||||
starTransition.setFrame(view: overscrollView, frame: overscrollFrame)
|
||||
}
|
||||
|
||||
let fadeSize = self.fade.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(RoundedRectangle(
|
||||
colors: [
|
||||
topBackgroundColor,
|
||||
bottomBackgroundColor
|
||||
],
|
||||
cornerRadius: 0.0,
|
||||
gradientDirection: .vertical
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width, height: 1000.0)
|
||||
)
|
||||
let fadeFrame = CGRect(origin: CGPoint(x: 0.0, y: -fadeSize.height), size: fadeSize)
|
||||
if let fadeView = self.fade.view {
|
||||
if fadeView.superview == nil {
|
||||
self.scrollView.addSubview(fadeView)
|
||||
}
|
||||
starTransition.setFrame(view: fadeView, frame: fadeFrame)
|
||||
}
|
||||
|
||||
let starSize = self.starView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(PremiumStarComponent(
|
||||
theme: environment.theme,
|
||||
isIntro: true,
|
||||
isVisible: true,
|
||||
hasIdleAnimations: true,
|
||||
colors: [
|
||||
UIColor(rgb: 0xe57d02),
|
||||
UIColor(rgb: 0xf09903),
|
||||
UIColor(rgb: 0xf9b004),
|
||||
UIColor(rgb: 0xfdd219)
|
||||
],
|
||||
particleColor: UIColor(rgb: 0xf9b004)
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: min(414.0, availableSize.width), height: 220.0)
|
||||
)
|
||||
let starFrame = CGRect(origin: .zero, size: starSize)
|
||||
if let starView = self.starView.view {
|
||||
if starView.superview == nil {
|
||||
self.insertSubview(starView, aboveSubview: self.scrollView)
|
||||
}
|
||||
starTransition.setBounds(view: starView, bounds: starFrame)
|
||||
}
|
||||
|
||||
let titleSize = self.titleView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: environment.strings.Stars_Intro_Title, font: Font.bold(28.0), textColor: environment.theme.list.itemPrimaryTextColor)),
|
||||
text: .plain(NSAttributedString(string: "Stars Balance", font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor)),
|
||||
horizontalAlignment: .center,
|
||||
truncationType: .end,
|
||||
maximumNumberOfLines: 1
|
||||
@ -423,114 +309,100 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
if titleView.superview == nil {
|
||||
self.addSubview(titleView)
|
||||
}
|
||||
starTransition.setBounds(view: titleView, bounds: CGRect(origin: .zero, size: titleSize))
|
||||
let titlePosition = CGPoint(x: availableSize.width / 2.0, y: environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0)
|
||||
transition.setPosition(view: titleView, position: titlePosition)
|
||||
transition.setBounds(view: titleView, bounds: CGRect(origin: .zero, size: titleSize))
|
||||
}
|
||||
|
||||
let topBalanceTitleSize = self.topBalanceTitleView.update(
|
||||
let proceedsSize = self.proceedsView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: environment.strings.Stars_Intro_Balance,
|
||||
font: Font.regular(14.0),
|
||||
textColor: environment.theme.actionSheet.primaryTextColor
|
||||
component: AnyComponent(ListSectionComponent(
|
||||
theme: environment.theme,
|
||||
header: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "Proceeds Overview".uppercased(),
|
||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||
textColor: environment.theme.list.freeTextColor
|
||||
)),
|
||||
maximumNumberOfLines: 0
|
||||
)),
|
||||
maximumNumberOfLines: 1
|
||||
footer: nil,
|
||||
items: [AnyComponentWithIdentity(id: 0, component: AnyComponent(
|
||||
VStack([
|
||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(HStack([
|
||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarMedium", tintColor: nil))),
|
||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0), environment.dateTimeFormat.groupingSeparator), font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor))))),
|
||||
AnyComponentWithIdentity(id: 2, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: formatUsdValue(self.starsState?.balance ?? 0, rate: 0.2), font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor))))),
|
||||
], spacing: 3.0))),
|
||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Available Balance", font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor)))))
|
||||
], alignment: .left, spacing: 2.0)
|
||||
)),
|
||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(
|
||||
VStack([
|
||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(HStack([
|
||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarMedium", tintColor: nil))),
|
||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0) * 3, environment.dateTimeFormat.groupingSeparator), font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor))))),
|
||||
AnyComponentWithIdentity(id: 2, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: formatUsdValue((self.starsState?.balance ?? 0) * 3, rate: 0.2), font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor))))),
|
||||
], spacing: 3.0))),
|
||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Total Lifetime Proceeds", font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor)))))
|
||||
], alignment: .left, spacing: 2.0)
|
||||
))],
|
||||
displaySeparators: false
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 120.0, height: 100.0)
|
||||
containerSize: CGSize(width: availableSize.width - sideInsets, height: availableSize.height)
|
||||
)
|
||||
|
||||
let topBalanceValueSize = self.topBalanceValueView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0), environment.dateTimeFormat.groupingSeparator),
|
||||
font: Font.semibold(14.0),
|
||||
textColor: environment.theme.actionSheet.primaryTextColor
|
||||
)),
|
||||
maximumNumberOfLines: 1
|
||||
)),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: 120.0, height: 100.0)
|
||||
)
|
||||
let topBalanceIconSize = self.topBalanceIconView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarSmall", tintColor: nil)),
|
||||
environment: {},
|
||||
containerSize: availableSize
|
||||
)
|
||||
|
||||
let navigationHeight = environment.navigationHeight - environment.statusBarHeight
|
||||
let topBalanceOriginY = environment.statusBarHeight + (navigationHeight - topBalanceTitleSize.height - topBalanceValueSize.height) / 2.0
|
||||
let topBalanceTitleFrame = CGRect(origin: CGPoint(x: availableSize.width - topBalanceTitleSize.width - 16.0 - environment.safeInsets.right, y: topBalanceOriginY), size: topBalanceTitleSize)
|
||||
if let topBalanceTitleView = self.topBalanceTitleView.view {
|
||||
if topBalanceTitleView.superview == nil {
|
||||
topBalanceTitleView.alpha = 0.0
|
||||
self.addSubview(topBalanceTitleView)
|
||||
let proceedsFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - proceedsSize.width) / 2.0), y: contentHeight), size: proceedsSize)
|
||||
if let proceedsView = self.proceedsView.view {
|
||||
if proceedsView.superview == nil {
|
||||
self.scrollView.addSubview(proceedsView)
|
||||
}
|
||||
starTransition.setFrame(view: topBalanceTitleView, frame: topBalanceTitleFrame)
|
||||
}
|
||||
|
||||
let topBalanceValueFrame = CGRect(origin: CGPoint(x: availableSize.width - topBalanceValueSize.width - 16.0 - environment.safeInsets.right, y: topBalanceTitleFrame.maxY), size: topBalanceValueSize)
|
||||
if let topBalanceValueView = self.topBalanceValueView.view {
|
||||
if topBalanceValueView.superview == nil {
|
||||
topBalanceValueView.alpha = 0.0
|
||||
self.addSubview(topBalanceValueView)
|
||||
}
|
||||
starTransition.setFrame(view: topBalanceValueView, frame: topBalanceValueFrame)
|
||||
transition.setFrame(view: proceedsView, frame: proceedsFrame)
|
||||
}
|
||||
|
||||
let topBalanceIconFrame = CGRect(origin: CGPoint(x: topBalanceValueFrame.minX - topBalanceIconSize.width - 2.0, y: floorToScreenPixels(topBalanceValueFrame.midY - topBalanceIconSize.height / 2.0) - UIScreenPixel), size: topBalanceIconSize)
|
||||
if let topBalanceIconView = self.topBalanceIconView.view {
|
||||
if topBalanceIconView.superview == nil {
|
||||
topBalanceIconView.alpha = 0.0
|
||||
self.addSubview(topBalanceIconView)
|
||||
}
|
||||
starTransition.setFrame(view: topBalanceIconView, frame: topBalanceIconFrame)
|
||||
}
|
||||
|
||||
contentHeight += 181.0
|
||||
contentHeight += proceedsSize.height
|
||||
contentHeight += 44.0
|
||||
|
||||
let descriptionSize = self.descriptionView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
BalancedTextComponent(
|
||||
text: .plain(NSAttributedString(string: environment.strings.Stars_Intro_Description, font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor)),
|
||||
horizontalAlignment: .center,
|
||||
maximumNumberOfLines: 0,
|
||||
lineSpacing: 0.2
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - sideInsets - 8.0, height: 240.0)
|
||||
)
|
||||
let descriptionFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - descriptionSize.width) / 2.0), y: contentHeight + 20.0 - floor(descriptionSize.height / 2.0)), size: descriptionSize)
|
||||
if let descriptionView = self.descriptionView.view {
|
||||
if descriptionView.superview == nil {
|
||||
self.scrollView.addSubview(descriptionView)
|
||||
}
|
||||
|
||||
starTransition.setFrame(view: descriptionView, frame: descriptionFrame)
|
||||
}
|
||||
|
||||
contentHeight += descriptionSize.height
|
||||
contentHeight += 29.0
|
||||
let termsFont = Font.regular(13.0)
|
||||
let termsTextColor = environment.theme.list.freeTextColor
|
||||
let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsFont, textColor: environment.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
})
|
||||
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||
let balanceInfoString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("You can withdraw Stars using Fragment, or use Stars to advertise your bot. [Learn More >]()", attributes: termsMarkdownAttributes, textAlignment: .natural
|
||||
))
|
||||
if self.cachedChevronImage == nil || self.cachedChevronImage?.1 !== environment.theme {
|
||||
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Contact List/SubtitleArrow"), color: environment.theme.list.itemAccentColor)!, environment.theme)
|
||||
}
|
||||
if let range = balanceInfoString.string.range(of: ">"), let chevronImage = self.cachedChevronImage?.0 {
|
||||
balanceInfoString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: balanceInfoString.string))
|
||||
}
|
||||
|
||||
let balanceSize = self.balanceView.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(ListSectionComponent(
|
||||
theme: environment.theme,
|
||||
header: nil,
|
||||
footer: nil,
|
||||
header: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(
|
||||
string: "Available Balance".uppercased(),
|
||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||
textColor: environment.theme.list.freeTextColor
|
||||
)),
|
||||
maximumNumberOfLines: 0
|
||||
)),
|
||||
footer: AnyComponent(MultilineTextComponent(
|
||||
text: .plain(balanceInfoString),
|
||||
maximumNumberOfLines: 0
|
||||
)),
|
||||
items: [AnyComponentWithIdentity(id: 0, component: AnyComponent(
|
||||
StarsBalanceComponent(
|
||||
theme: environment.theme,
|
||||
strings: environment.strings,
|
||||
dateTimeFormat: environment.dateTimeFormat,
|
||||
count: self.starsState?.balance ?? 0,
|
||||
rate: nil,
|
||||
actionAvailable: !premiumConfiguration.areStarsDisabled,
|
||||
rate: 0.2,
|
||||
actionTitle: "Withdraw via Fragment",
|
||||
actionAvailable: true,
|
||||
buy: { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
@ -548,7 +420,7 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
if balanceView.superview == nil {
|
||||
self.scrollView.addSubview(balanceView)
|
||||
}
|
||||
starTransition.setFrame(view: balanceView, frame: balanceFrame)
|
||||
transition.setFrame(view: balanceView, frame: balanceFrame)
|
||||
}
|
||||
|
||||
contentHeight += balanceSize.height
|
||||
@ -563,21 +435,7 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
} else {
|
||||
allTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .all)
|
||||
}
|
||||
|
||||
let incomingTransactionsContext: StarsTransactionsContext
|
||||
if let current = self.incomingTransactionsContext {
|
||||
incomingTransactionsContext = current
|
||||
} else {
|
||||
incomingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .incoming)
|
||||
}
|
||||
|
||||
let outgoingTransactionsContext: StarsTransactionsContext
|
||||
if let current = self.outgoingTransactionsContext {
|
||||
outgoingTransactionsContext = current
|
||||
} else {
|
||||
outgoingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .outgoing)
|
||||
}
|
||||
|
||||
|
||||
panelItems.append(StarsTransactionsPanelContainerComponent.Item(
|
||||
id: "all",
|
||||
title: environment.strings.Stars_Intro_AllTransactions,
|
||||
@ -589,30 +447,6 @@ final class StarsStatisticsScreenComponent: Component {
|
||||
}
|
||||
))
|
||||
))
|
||||
|
||||
panelItems.append(StarsTransactionsPanelContainerComponent.Item(
|
||||
id: "incoming",
|
||||
title: environment.strings.Stars_Intro_Incoming,
|
||||
panel: AnyComponent(StarsTransactionsListPanelComponent(
|
||||
context: component.context,
|
||||
transactionsContext: incomingTransactionsContext,
|
||||
action: { transaction in
|
||||
component.openTransaction(transaction)
|
||||
}
|
||||
))
|
||||
))
|
||||
|
||||
panelItems.append(StarsTransactionsPanelContainerComponent.Item(
|
||||
id: "outgoing",
|
||||
title: environment.strings.Stars_Intro_Outgoing,
|
||||
panel: AnyComponent(StarsTransactionsListPanelComponent(
|
||||
context: component.context,
|
||||
transactionsContext: outgoingTransactionsContext,
|
||||
action: { transaction in
|
||||
component.openTransaction(transaction)
|
||||
}
|
||||
))
|
||||
))
|
||||
}
|
||||
|
||||
var panelTransition = transition
|
||||
|
@ -78,10 +78,7 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
private let navigationBackgroundView: BlurredBackgroundView
|
||||
private let navigationSeparatorLayer: SimpleLayer
|
||||
private let navigationSeparatorLayerContainer: SimpleLayer
|
||||
|
||||
private let headerView = ComponentView<Empty>()
|
||||
private let headerOffsetContainer: UIView
|
||||
|
||||
|
||||
private let scrollContainerView: UIView
|
||||
|
||||
private let overscroll = ComponentView<Empty>()
|
||||
@ -119,9 +116,6 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
private var outgoingTransactionsContext: StarsTransactionsContext?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.headerOffsetContainer = UIView()
|
||||
self.headerOffsetContainer.isUserInteractionEnabled = false
|
||||
|
||||
self.navigationBackgroundView = BlurredBackgroundView(color: nil, enableBlur: true)
|
||||
self.navigationBackgroundView.alpha = 0.0
|
||||
|
||||
@ -158,8 +152,6 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
|
||||
self.navigationSeparatorLayerContainer.addSublayer(self.navigationSeparatorLayer)
|
||||
self.layer.addSublayer(self.navigationSeparatorLayerContainer)
|
||||
|
||||
self.addSubview(self.headerOffsetContainer)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@ -530,6 +522,7 @@ final class StarsTransactionsScreenComponent: Component {
|
||||
dateTimeFormat: environment.dateTimeFormat,
|
||||
count: self.starsState?.balance ?? 0,
|
||||
rate: nil,
|
||||
actionTitle: environment.strings.Stars_Intro_Buy,
|
||||
actionAvailable: !premiumConfiguration.areStarsDisabled,
|
||||
buy: { [weak self] in
|
||||
guard let self, let component = self.component else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
func formatUsdValue(_ value: Int64, rate: Double) -> String {
|
||||
let formattedValue = String(format: "%0.2f", (Double(value) / 1000000000) * rate)
|
||||
let formattedValue = String(format: "%0.2f", (Double(value)) * rate)
|
||||
return "$\(formattedValue)"
|
||||
}
|
||||
|
@ -3452,7 +3452,7 @@ final class StoryItemSetContainerSendMessage {
|
||||
action()
|
||||
return
|
||||
}
|
||||
actions.append(ContextMenuAction(content: .textWithIcon(title: updatedPresentationData.initial.strings.Story_ViewLink, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: {
|
||||
actions.append(ContextMenuAction(content: .textWithSubtitleAndIcon(title: updatedPresentationData.initial.strings.Story_ViewLink, subtitle: url, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: {
|
||||
action()
|
||||
}))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user