Various improvements

This commit is contained in:
Ilya Laktyushin 2024-07-24 09:25:48 +04:00
parent a7aefe85f8
commit 9ba0743553
6 changed files with 110 additions and 67 deletions

View File

@ -55,7 +55,7 @@ public final class BrowserBookmarksScreen: ViewController {
}, navigateToMessage: { _, _, _ in
}, navigateToMessageStandalone: { _ in
}, navigateToThreadMessage: { _, _, _ in
}, tapMessage: nil, clickThroughMessage: {
}, tapMessage: nil, clickThroughMessage: { _, _ in
}, toggleMessagesSelection: { _, _ in
}, sendCurrentMessage: { _, _ in
}, sendMessage: { _ in

View File

@ -97,6 +97,7 @@ swift_library(
"//submodules/ChatPresentationInterfaceState:ChatPresentationInterfaceState",
"//submodules/StickerPackPreviewUI:StickerPackPreviewUI",
"//submodules/TelegramUI/Components/LottieComponent",
"//submodules/TelegramUI/Components/LottieComponentResourceContent",
"//submodules/ImageTransparency",
"//submodules/GalleryUI",
"//submodules/MediaPlayer:UniversalMediaPlayer",

View File

@ -1,6 +1,7 @@
import Foundation
import UIKit
import Display
import ComponentFlow
import SwiftSignalKit
import AccountContext
import TelegramCore
@ -9,6 +10,8 @@ import TelegramAnimatedStickerNode
import StickerResources
import MediaEditor
import TelegramStringFormatting
import LottieComponent
import LottieComponentResourceContent
private func generateIcon(style: DrawingWeatherEntity.Style) -> UIImage? {
guard let image = UIImage(bundleImageName: "Chat/Attach Menu/Location") else {
@ -53,9 +56,8 @@ public final class DrawingWeatherEntityView: DrawingEntityView, UITextViewDelega
let backgroundView: UIView
let textView: DrawingTextView
let iconView: UIImageView
private let imageNode: TransformImageNode
private var animationNode: AnimatedStickerNode?
private var animation = ComponentView<Empty>()
private var didSetUpAnimationNode = false
private let stickerFetchedDisposable = MetaDisposable()
@ -88,20 +90,14 @@ public final class DrawingWeatherEntityView: DrawingEntityView, UITextViewDelega
self.textView.spellCheckingType = .no
self.textView.textContainer.maximumNumberOfLines = 2
self.textView.textContainer.lineBreakMode = .byTruncatingTail
self.iconView = UIImageView()
self.imageNode = TransformImageNode()
super.init(context: context, entity: entity)
self.textView.delegate = self
self.addSubview(self.backgroundView)
self.addSubview(self.textView)
self.addSubview(self.iconView)
self.update(animated: false)
self.setup()
}
required init?(coder: NSCoder) {
@ -134,17 +130,35 @@ public final class DrawingWeatherEntityView: DrawingEntityView, UITextViewDelega
let iconSize = min(80.0, floor(self.bounds.height * 0.7))
let iconOffset: CGFloat = 0.3
self.iconView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels(iconSize * iconOffset), y: floorToScreenPixels((self.bounds.height - iconSize) / 2.0)), size: CGSize(width: iconSize, height: iconSize))
self.imageNode.frame = self.iconView.frame.offsetBy(dx: 0.0, dy: 2.0)
let iconFrame = CGRect(origin: CGPoint(x: floorToScreenPixels(iconSize * iconOffset), y: floorToScreenPixels((self.bounds.height - iconSize) / 2.0)), size: CGSize(width: iconSize, height: iconSize))
if let animationNode = self.animationNode {
animationNode.frame = self.iconView.frame
animationNode.updateLayout(size: self.iconView.frame.size)
if let icon = self.weatherEntity.icon {
let _ = self.animation.update(
transition: .immediate,
component: AnyComponent(
LottieComponent(
content: LottieComponent.ResourceContent(
context: self.context,
file: icon,
attemptSynchronously: true,
providesPlaceholder: true
),
color: nil,
placeholderColor: UIColor(rgb: 0x000000, alpha: 0.1),
loop: !["🌑", "🌒", "🌓", "🌔", "🌕", "🌖", "🌗", "🌘"].contains(self.weatherEntity.emoji)
)
),
environment: {},
containerSize: iconFrame.size
)
if let animationView = self.animation.view {
if animationView.superview == nil {
self.addSubview(animationView)
}
animationView.frame = iconFrame
}
}
let imageSize = CGSize(width: iconSize, height: iconSize)
self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))()
self.textView.frame = CGRect(origin: CGPoint(x: self.bounds.width - self.textSize.width - 6.0, y: floorToScreenPixels((self.bounds.height - self.textSize.height) / 2.0)), size: self.textSize)
self.backgroundView.frame = self.bounds
}
@ -263,10 +277,8 @@ public final class DrawingWeatherEntityView: DrawingEntityView, UITextViewDelega
self.sizeToFit()
if self.currentStyle != self.weatherEntity.style {
self.currentStyle = self.weatherEntity.style
self.iconView.image = generateIcon(style: self.weatherEntity.style)
}
self.currentStyle = self.weatherEntity.style
self.backgroundView.layer.cornerRadius = self.textSize.height * 0.2
if #available(iOS 13.0, *) {
@ -276,42 +288,6 @@ public final class DrawingWeatherEntityView: DrawingEntityView, UITextViewDelega
super.update(animated: animated)
}
private func setup() {
if let file = self.weatherEntity.icon {
self.iconView.isHidden = true
self.addSubnode(self.imageNode)
if let dimensions = file.dimensions {
if file.isAnimatedSticker || file.isVideoSticker || file.mimeType == "video/webm" {
let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 256.0, height: 256.0))
if self.animationNode == nil {
let animationNode = DefaultAnimatedStickerNodeImpl()
animationNode.autoplay = true
self.animationNode = animationNode
animationNode.started = { [weak self] in
self?.imageNode.isHidden = true
}
animationNode.setup(source: AnimatedStickerResourceSource(account: self.context.account, resource: file.resource, isVideo: file.isVideoSticker), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
self.addSubnode(animationNode)
}
self.imageNode.setSignal(chatMessageAnimatedSticker(postbox: self.context.account.postbox, userLocation: .other, file: file, small: false, size: fittedDimensions))
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: stickerPackFileReference(file), resource: file.resource).start())
} else {
if let animationNode = self.animationNode {
animationNode.visibility = false
self.animationNode = nil
animationNode.removeFromSupernode()
self.imageNode.isHidden = false
self.didSetUpAnimationNode = false
}
self.imageNode.setSignal(chatMessageSticker(account: self.context.account, userLocation: .other, file: file, small: false, synchronousLoad: false))
self.stickerFetchedDisposable.set(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: false)).start())
}
self.setNeedsLayout()
}
}
}
override func updateSelectionView() {
guard let selectionView = self.selectionView as? DrawingWeatherEntitySelectionView else {
return

View File

@ -86,6 +86,7 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
let peers: [EnginePeer.Id: EnginePeer]
let stateUpdated: (ComponentTransition) -> Void
let buy: (StarsProduct) -> Void
let openAppExamples: () -> Void
init(
context: AccountContext,
@ -100,7 +101,8 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
expanded: Bool,
peers: [EnginePeer.Id: EnginePeer],
stateUpdated: @escaping (ComponentTransition) -> Void,
buy: @escaping (StarsProduct) -> Void
buy: @escaping (StarsProduct) -> Void,
openAppExamples: @escaping () -> Void
) {
self.context = context
self.externalState = externalState
@ -115,6 +117,7 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
self.peers = peers
self.stateUpdated = stateUpdated
self.buy = buy
self.openAppExamples = openAppExamples
}
static func ==(lhs: StarsPurchaseScreenContentComponent, rhs: StarsPurchaseScreenContentComponent) -> Bool {
@ -225,15 +228,16 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: accentColor)!, theme)
}
let titleAttributedString = parseMarkdownIntoAttributedString(textString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
let textAttributedString = parseMarkdownIntoAttributedString(textString, attributes: markdownAttributes).mutableCopy() as! NSMutableAttributedString
if let range = titleAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 {
titleAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: titleAttributedString.string))
if let range = textAttributedString.string.range(of: ">"), let chevronImage = state.cachedChevronImage?.0 {
textAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: textAttributedString.string))
}
let openAppExamples = component.openAppExamples
let text = text.update(
component: BalancedTextComponent(
text: .plain(titleAttributedString),
text: .plain(textAttributedString),
horizontalAlignment: .center,
maximumNumberOfLines: 0,
lineSpacing: 0.2,
@ -246,6 +250,7 @@ private final class StarsPurchaseScreenContentComponent: CombinedComponent {
}
},
tapAction: { _, _ in
openAppExamples()
}
),
environment: {},
@ -473,6 +478,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
let options: [Any]
let purpose: StarsPurchasePurpose
let forceDark: Bool
let openAppExamples: () -> Void
let updateInProgress: (Bool) -> Void
let present: (ViewController) -> Void
let completion: (Int64) -> Void
@ -483,6 +489,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
options: [Any],
purpose: StarsPurchasePurpose,
forceDark: Bool,
openAppExamples: @escaping () -> Void,
updateInProgress: @escaping (Bool) -> Void,
present: @escaping (ViewController) -> Void,
completion: @escaping (Int64) -> Void
@ -492,6 +499,7 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
self.options = options
self.purpose = purpose
self.forceDark = forceDark
self.openAppExamples = openAppExamples
self.updateInProgress = updateInProgress
self.present = present
self.completion = completion
@ -872,7 +880,8 @@ private final class StarsPurchaseScreenComponent: CombinedComponent {
},
buy: { [weak state] product in
state?.buy(product: product)
}
},
openAppExamples: context.component.openAppExamples
)),
contentInsets: UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: environment.safeInsets.bottom, right: 0.0),
contentOffsetUpdated: { [weak state] topContentOffset, bottomContentOffset in
@ -985,6 +994,7 @@ public final class StarsPurchaseScreen: ViewControllerComponentContainer {
self.context = context
self.starsContext = starsContext
var openAppExamplesImpl: (() -> Void)?
var updateInProgressImpl: ((Bool) -> Void)?
var presentImpl: ((ViewController) -> Void)?
var completionImpl: ((Int64) -> Void)?
@ -994,6 +1004,9 @@ public final class StarsPurchaseScreen: ViewControllerComponentContainer {
options: options,
purpose: purpose,
forceDark: false,
openAppExamples: {
openAppExamplesImpl?()
},
updateInProgress: { inProgress in
updateInProgressImpl?(inProgress)
},
@ -1011,6 +1024,19 @@ public final class StarsPurchaseScreen: ViewControllerComponentContainer {
self.navigationItem.setLeftBarButton(cancelItem, animated: false)
self.navigationPresentation = .modal
openAppExamplesImpl = { [weak self] in
guard let self else {
return
}
let _ = (context.sharedContext.makeMiniAppListScreenInitialData(context: context)
|> deliverOnMainQueue).startStandalone(next: { [weak self] initialData in
guard let self, let navigationController = self.navigationController as? NavigationController else {
return
}
navigationController.pushViewController(context.sharedContext.makeMiniAppListScreen(context: context, initialData: initialData))
})
}
updateInProgressImpl = { [weak self] inProgress in
if let strongSelf = self {
strongSelf.navigationItem.leftBarButtonItem?.isEnabled = !inProgress

View File

@ -34,6 +34,7 @@ swift_library(
"//submodules/TelegramUI/Components/Stars/StarsImageComponent",
"//submodules/TelegramUI/Components/Stars/StarsAvatarComponent",
"//submodules/GalleryUI",
"//submodules/TelegramUI/Components/MiniAppListScreen",
],
visibility = [
"//visibility:public",

View File

@ -23,6 +23,7 @@ import UndoUI
import StarsImageComponent
import GalleryUI
import StarsAvatarComponent
import MiniAppListScreen
private final class StarsTransactionSheetContent: CombinedComponent {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
@ -34,6 +35,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
let openPeer: (EnginePeer) -> Void
let openMessage: (EngineMessage.Id) -> Void
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
let openAppExamples: () -> Void
let copyTransactionId: (String) -> Void
init(
@ -44,6 +46,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
openPeer: @escaping (EnginePeer) -> Void,
openMessage: @escaping (EngineMessage.Id) -> Void,
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
openAppExamples: @escaping () -> Void,
copyTransactionId: @escaping (String) -> Void
) {
self.context = context
@ -53,6 +56,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
self.openPeer = openPeer
self.openMessage = openMessage
self.openMedia = openMedia
self.openAppExamples = openAppExamples
self.copyTransactionId = copyTransactionId
}
@ -345,6 +349,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
photo = nil
isRefund = false
isGift = true
delayedCloseOnOpenPeer = false
}
if let spaceRegex {
let nsRange = NSRange(descriptionText.startIndex..., in: descriptionText)
@ -647,6 +652,8 @@ private final class StarsTransactionSheetContent: CombinedComponent {
var descriptionSize: CGSize = .zero
if !descriptionText.isEmpty {
let openAppExamples = component.openAppExamples
if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== environment.theme {
state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: linkColor)!, theme)
}
@ -665,7 +672,18 @@ private final class StarsTransactionSheetContent: CombinedComponent {
text: .plain(attributedString),
horizontalAlignment: .center,
maximumNumberOfLines: 5,
lineSpacing: 0.2
lineSpacing: 0.2,
highlightColor: linkColor.withAlphaComponent(0.2),
highlightAction: { attributes in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
} else {
return nil
}
},
tapAction: { _, _ in
openAppExamples()
}
),
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
transition: .immediate
@ -765,6 +783,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
let openPeer: (EnginePeer) -> Void
let openMessage: (EngineMessage.Id) -> Void
let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void
let openAppExamples: () -> Void
let copyTransactionId: (String) -> Void
init(
@ -774,6 +793,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
openPeer: @escaping (EnginePeer) -> Void,
openMessage: @escaping (EngineMessage.Id) -> Void,
openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void,
openAppExamples: @escaping () -> Void,
copyTransactionId: @escaping (String) -> Void
) {
self.context = context
@ -782,6 +802,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
self.openPeer = openPeer
self.openMessage = openMessage
self.openMedia = openMedia
self.openAppExamples = openAppExamples
self.copyTransactionId = copyTransactionId
}
@ -826,6 +847,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent {
openPeer: context.component.openPeer,
openMessage: context.component.openMessage,
openMedia: context.component.openMedia,
openAppExamples: context.component.openAppExamples,
copyTransactionId: context.component.copyTransactionId
)),
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
@ -915,6 +937,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
var openPeerImpl: ((EnginePeer) -> Void)?
var openMessageImpl: ((EngineMessage.Id) -> Void)?
var openMediaImpl: (([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)?
var openAppExamplesImpl: (() -> Void)?
var copyTransactionIdImpl: ((String) -> Void)?
super.init(
context: context,
@ -931,6 +954,9 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
openMedia: { media, transitionNode, addToTransitionSurface in
openMediaImpl?(media, transitionNode, addToTransitionSurface)
},
openAppExamples: {
openAppExamplesImpl?()
},
copyTransactionId: { transactionId in
copyTransactionIdImpl?(transactionId)
}
@ -1018,6 +1044,19 @@ public class StarsTransactionScreen: ViewControllerComponentContainer {
}))
}
openAppExamplesImpl = { [weak self] in
guard let self else {
return
}
let _ = (context.sharedContext.makeMiniAppListScreenInitialData(context: context)
|> deliverOnMainQueue).startStandalone(next: { [weak self] initialData in
guard let self, let navigationController = self.navigationController as? NavigationController else {
return
}
navigationController.pushViewController(context.sharedContext.makeMiniAppListScreen(context: context, initialData: initialData))
})
}
copyTransactionIdImpl = { [weak self] transactionId in
guard let self else {
return