Various improvements

This commit is contained in:
Ilya Laktyushin 2024-06-07 14:07:01 +04:00
parent 5470ba80ec
commit 1cc27e2a20
14 changed files with 281 additions and 331 deletions

View File

@ -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 {

View File

@ -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:

View File

@ -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) })

View File

@ -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
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
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
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
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.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
self.iconView = iconView
self.textNode = nil
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

View File

@ -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 handleWidth: CGFloat = 33.0
let maxPageWidth = layout.size.width - 20.0 - pageLeftSize.width - pageRightSize.width
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 {

View File

@ -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

View File

@ -319,6 +319,8 @@ private final class CreateLinkSheetComponent: CombinedComponent {
self.link = link?.url ?? ""
self.name = link?.name ?? ""
self.positionBelowText = link?.positionBelowText ?? true
self.largeMedia = link?.largeMedia
super.init()
@ -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

View File

@ -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,18 +4480,46 @@ 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
}
let linkController = CreateLinkScreen(context: controller.context, link: nil, completion: { [weak self] url, result in
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: 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
@ -4500,12 +4530,16 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
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)

View File

@ -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()
}))

View File

@ -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,

View File

@ -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()
@ -207,60 +200,20 @@ final class StarsStatisticsScreenComponent: Component {
let isLockedAtPanels = scrollBounds.maxY == self.scrollView.contentSize.height
if let navigationMetrics = self.navigationMetrics {
let topInset: CGFloat = navigationMetrics.navigationHeight - 56.0
let topContentOffset = self.scrollView.contentOffset.y
let navigationBackgroundAlpha = min(20.0, max(0.0, topContentOffset - 95.0)) / 20.0
let titleOffset: CGFloat
let titleScale: CGFloat
let titleOffsetDelta = (topInset + 160.0) - (navigationMetrics.statusBarHeight + (navigationMetrics.navigationHeight - navigationMetrics.statusBarHeight) / 2.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)
var topContentOffset = self.scrollView.contentOffset.y
let expansionDistance: CGFloat = 32.0
var expansionDistanceFactor: CGFloat = abs(scrollBounds.maxY - self.scrollView.contentSize.height) / expansionDistance
expansionDistanceFactor = max(0.0, min(1.0, expansionDistanceFactor))
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
}
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
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)
}
contentHeight += environment.navigationHeight
contentHeight += 31.0
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)
transition.setFrame(view: proceedsView, frame: proceedsFrame)
}
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)
contentHeight += proceedsSize.height
contentHeight += 44.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 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 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
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 premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
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
@ -564,20 +436,6 @@ final class StarsStatisticsScreenComponent: Component {
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

View File

@ -79,9 +79,6 @@ final class StarsTransactionsScreenComponent: Component {
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 {

View File

@ -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)"
}

View File

@ -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()
}))
}