Merge commit '2b6636a0198c2ad8d80b67ef47a0402ee8bb6bd3'

This commit is contained in:
Isaac 2024-08-06 15:00:31 +04:00
commit 8069dfa73a
30 changed files with 167 additions and 76 deletions

View File

@ -653,7 +653,7 @@ public final class DefaultAnimatedStickerNodeImpl: ASDisplayNode, AnimatedSticke
strongSelf.frameUpdated(frame.index, frame.totalFrames)
strongSelf.currentFrameIndex = frame.index
strongSelf.currentFrameCount = frame.totalFrames;
strongSelf.currentFrameCount = frame.totalFrames
strongSelf.currentFrameRate = frameRate
if frame.isLastFrame {

View File

@ -18,6 +18,7 @@ import MinimizedContainer
import InstantPageUI
import NavigationStackComponent
import LottieComponent
import WebKit
private let settingsTag = GenericComponentViewTag()
@ -489,13 +490,13 @@ public class BrowserScreen: ViewController, MinimizableController {
case expand
}
fileprivate final class Node: ViewControllerTracingNode {
final class Node: ViewControllerTracingNode {
private weak var controller: BrowserScreen?
private let context: AccountContext
private let contentContainerView = UIView()
fileprivate let contentNavigationContainer = ComponentView<Empty>()
fileprivate var content: [BrowserContent] = []
private(set) var content: [BrowserContent] = []
fileprivate var contentState: BrowserContentState?
private var contentStateDisposable = MetaDisposable()
@ -785,13 +786,14 @@ public class BrowserScreen: ViewController, MinimizableController {
let browserContent: BrowserContent
switch content {
case let .webPage(url):
let webContent = BrowserWebContent(context: self.context, presentationData: self.presentationData, url: url)
let webContent = BrowserWebContent(context: self.context, presentationData: self.presentationData, url: url, preferredConfiguration: self.controller?.preferredConfiguration)
webContent.cancelInteractiveTransitionGestures = { [weak self] in
if let self, let view = self.controller?.view {
cancelInteractiveTransitionGestures(view: view)
}
}
browserContent = webContent
self.controller?.preferredConfiguration = nil
case let .instantPage(webPage, anchor, sourceLocation):
let instantPageContent = BrowserInstantPageContent(context: self.context, presentationData: self.presentationData, webPage: webPage, anchor: anchor, url: webPage.content.url ?? "", sourceLocation: sourceLocation)
instantPageContent.openPeer = { [weak self] peer in
@ -846,7 +848,9 @@ public class BrowserScreen: ViewController, MinimizableController {
return
}
if controller.isMinimized {
if let navigationController = controller.navigationController as? NavigationController, let minimizedContainer = navigationController.minimizedContainer {
minimizedContainer.removeController(controller)
}
} else {
controller.dismiss()
}
@ -1328,7 +1332,8 @@ public class BrowserScreen: ViewController, MinimizableController {
right: layout.safeInsets.right
),
navigationBarHeight: navigationBarHeight,
scrollingPanelOffsetFraction: self.scrollingPanelOffsetFraction
scrollingPanelOffsetFraction: self.scrollingPanelOffsetFraction,
hasBottomPanel: !layout.metrics.isTablet || self.presentationState.isSearching
)
))
)
@ -1372,7 +1377,7 @@ public class BrowserScreen: ViewController, MinimizableController {
private let context: AccountContext
private let subject: Subject
private var preferredConfiguration: WKWebViewConfiguration?
private var openPreviousOnClose = false
private var validLayout: ContainerViewLayout?
@ -1389,7 +1394,7 @@ public class BrowserScreen: ViewController, MinimizableController {
// "application/vnd.openxmlformats-officedocument.presentationml.presentation"
]
public init(context: AccountContext, subject: Subject, openPreviousOnClose: Bool = false) {
public init(context: AccountContext, subject: Subject, preferredConfiguration: WKWebViewConfiguration? = nil, openPreviousOnClose: Bool = false) {
var subject = subject
if case let .webPage(url) = subject, let parsedUrl = URL(string: url) {
if parsedUrl.host?.hasSuffix(".ton") == true {
@ -1402,6 +1407,7 @@ public class BrowserScreen: ViewController, MinimizableController {
}
self.context = context
self.subject = subject
self.preferredConfiguration = preferredConfiguration
self.openPreviousOnClose = openPreviousOnClose
super.init(navigationBarPresentationData: nil)
@ -1419,7 +1425,7 @@ public class BrowserScreen: ViewController, MinimizableController {
preconditionFailure()
}
private var node: Node {
var node: Node {
return self.displayNode as! Node
}
@ -1539,17 +1545,20 @@ private final class BrowserContentComponent: Component {
let insets: UIEdgeInsets
let navigationBarHeight: CGFloat
let scrollingPanelOffsetFraction: CGFloat
let hasBottomPanel: Bool
init(
content: BrowserContent,
insets: UIEdgeInsets,
navigationBarHeight: CGFloat,
scrollingPanelOffsetFraction: CGFloat
scrollingPanelOffsetFraction: CGFloat,
hasBottomPanel: Bool
) {
self.content = content
self.insets = insets
self.navigationBarHeight = navigationBarHeight
self.scrollingPanelOffsetFraction = scrollingPanelOffsetFraction
self.hasBottomPanel = hasBottomPanel
}
static func ==(lhs: BrowserContentComponent, rhs: BrowserContentComponent) -> Bool {
@ -1565,6 +1574,9 @@ private final class BrowserContentComponent: Component {
if lhs.scrollingPanelOffsetFraction != rhs.scrollingPanelOffsetFraction {
return false
}
if lhs.hasBottomPanel != rhs.hasBottomPanel {
return false
}
return true
}
@ -1584,9 +1596,9 @@ private final class BrowserContentComponent: Component {
let collapsedHeight: CGFloat = 24.0
let topInset: CGFloat = component.navigationBarHeight * (1.0 - component.scrollingPanelOffsetFraction) + (component.insets.top + collapsedHeight) * component.scrollingPanelOffsetFraction
let bottomInset = (49.0 + component.insets.bottom) * (1.0 - component.scrollingPanelOffsetFraction)
let bottomInset = component.hasBottomPanel ? (49.0 + component.insets.bottom) * (1.0 - component.scrollingPanelOffsetFraction) : 0.0
let insets = UIEdgeInsets(top: topInset, left: component.insets.left, bottom: bottomInset, right: component.insets.right)
let fullInsets = UIEdgeInsets(top: component.insets.top + component.navigationBarHeight, left: component.insets.left, bottom: 49.0 + component.insets.bottom, right: component.insets.right)
let fullInsets = UIEdgeInsets(top: component.insets.top + component.navigationBarHeight, left: component.insets.left, bottom: component.hasBottomPanel ? 49.0 + component.insets.bottom : 0.0, right: component.insets.right)
component.content.updateLayout(size: availableSize, insets: insets, fullInsets: fullInsets, safeInsets: component.insets, transition: transition)
transition.setFrame(view: component.content, frame: CGRect(origin: .zero, size: availableSize))

View File

@ -203,40 +203,46 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
private var tempFile: TempBoxFile?
init(context: AccountContext, presentationData: PresentationData, url: String) {
init(context: AccountContext, presentationData: PresentationData, url: String, preferredConfiguration: WKWebViewConfiguration? = nil) {
self.context = context
self.uuid = UUID()
self.presentationData = presentationData
let configuration = WKWebViewConfiguration()
var proxyServerHost = "magic.org"
if let data = context.currentAppConfiguration.with({ $0 }).data, let hostValue = data["ton_proxy_address"] as? String {
proxyServerHost = hostValue
}
configuration.setURLSchemeHandler(TonSchemeHandler(proxyServerHost: proxyServerHost), forURLScheme: "tonsite")
configuration.allowsInlineMediaPlayback = true
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
configuration.mediaTypesRequiringUserActionForPlayback = []
} else {
configuration.mediaPlaybackRequiresUserAction = false
}
let contentController = WKUserContentController()
let videoScript = WKUserScript(source: videoSource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(videoScript)
let touchScript = WKUserScript(source: setupTouchObservers, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(touchScript)
configuration.userContentController = contentController
configuration.applicationNameForUserAgent = computedUserAgent()
var handleScriptMessageImpl: ((WKScriptMessage) -> Void)?
let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(eventProxyScript)
contentController.add(WeakScriptMessageHandler { message in
handleScriptMessageImpl?(message)
}, name: "performAction")
let configuration: WKWebViewConfiguration
if let preferredConfiguration {
configuration = preferredConfiguration
} else {
configuration = WKWebViewConfiguration()
var proxyServerHost = "magic.org"
if let data = context.currentAppConfiguration.with({ $0 }).data, let hostValue = data["ton_proxy_address"] as? String {
proxyServerHost = hostValue
}
configuration.setURLSchemeHandler(TonSchemeHandler(proxyServerHost: proxyServerHost), forURLScheme: "tonsite")
configuration.allowsInlineMediaPlayback = true
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
configuration.mediaTypesRequiringUserActionForPlayback = []
} else {
configuration.mediaPlaybackRequiresUserAction = false
}
let contentController = WKUserContentController()
let videoScript = WKUserScript(source: videoSource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(videoScript)
let touchScript = WKUserScript(source: setupTouchObservers, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(touchScript)
let eventProxyScript = WKUserScript(source: eventProxySource, injectionTime: .atDocumentStart, forMainFrameOnly: false)
contentController.addUserScript(eventProxyScript)
contentController.add(WeakScriptMessageHandler { message in
handleScriptMessageImpl?(message)
}, name: "performAction")
configuration.userContentController = contentController
configuration.applicationNameForUserAgent = computedUserAgent()
}
self.webView = WebView(frame: CGRect(), configuration: configuration)
self.webView.allowsLinkPreview = true
@ -711,7 +717,12 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
self.minimize()
self.openAppUrl(url)
} else {
decisionHandler(.allow, preferences)
if let scheme = navigationAction.request.url?.scheme, !["http", "https", "tonsite", "about"].contains(scheme.lowercased()) {
decisionHandler(.cancel, preferences)
self.context.sharedContext.openExternalUrl(context: self.context, urlContext: .generic, url: url, forceExternal: true, presentationData: self.presentationData, navigationController: nil, dismissInput: {})
} else {
decisionHandler(.allow, preferences)
}
}
} else {
decisionHandler(.allow, preferences)
@ -786,7 +797,7 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
self.minimize()
self.openAppUrl(url)
} else {
self.open(url: url, new: true)
return self.open(url: url, configuration: configuration, new: true)
}
}
}
@ -927,17 +938,19 @@ final class BrowserWebContent: UIView, BrowserContent, WKNavigationDelegate, WKU
self.present(alertController, nil)
}
private func open(url: String, new: Bool) {
@discardableResult private func open(url: String, configuration: WKWebViewConfiguration? = nil, new: Bool) -> WKWebView? {
let subject: BrowserScreen.Subject = .webPage(url: url)
if new, let navigationController = self.getNavigationController() {
navigationController._keepModalDismissProgress = true
self.minimize()
let controller = BrowserScreen(context: self.context, subject: subject, openPreviousOnClose: true)
let controller = BrowserScreen(context: self.context, subject: subject, preferredConfiguration: configuration, openPreviousOnClose: true)
navigationController._keepModalDismissProgress = true
navigationController.pushViewController(controller)
return (controller.node.content.last as? BrowserWebContent)?.webView
} else {
self.pushContent(subject)
}
return nil
}
private func share(url: String) {

View File

@ -6,12 +6,15 @@ public protocol MinimizedContainer: ASDisplayNode {
var controllers: [MinimizableController] { get }
var isExpanded: Bool { get }
var willMaximize: (() -> Void)? { get set }
var willMaximize: ((MinimizedContainer) -> Void)? { get set }
var willDismiss: ((MinimizedContainer) -> Void)? { get set }
var didDismiss: ((MinimizedContainer) -> Void)? { get set }
var statusBarStyle: StatusBarStyle { get }
var statusBarStyleUpdated: (() -> Void)? { get set }
func addController(_ viewController: MinimizableController, topEdgeOffset: CGFloat?, beforeMaximize: @escaping (NavigationController, @escaping () -> Void) -> Void, transition: ContainedViewLayoutTransition)
func removeController(_ viewController: MinimizableController)
func maximizeController(_ viewController: MinimizableController, animated: Bool, completion: @escaping (Bool) -> Void)
func collapse()
func dismissAll(completion: @escaping () -> Void)

View File

@ -153,13 +153,23 @@ open class NavigationController: UINavigationController, ContainableController,
open var minimizedContainer: MinimizedContainer? {
didSet {
self.minimizedContainer?.navigationController = self
self.minimizedContainer?.willMaximize = { [weak self] in
self.minimizedContainer?.willMaximize = { [weak self] _ in
guard let self else {
return
}
self.isMaximizing = true
self.updateContainersNonReentrant(transition: .animated(duration: 0.4, curve: .spring))
}
self.minimizedContainer?.willDismiss = { [weak self] _ in
guard let self else {
return
}
self.minimizedContainer = nil
self.updateContainersNonReentrant(transition: .animated(duration: 0.4, curve: .spring))
}
self.minimizedContainer?.didDismiss = { minimizedContainer in
minimizedContainer.removeFromSupernode()
}
self.minimizedContainer?.statusBarStyleUpdated = { [weak self] in
guard let self else {
return

View File

@ -209,7 +209,7 @@ public final class DrawingLinkEntityView: DrawingEntityView, UITextViewDelegate
if !self.linkEntity.name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
string = self.linkEntity.name.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
} else {
string = self.linkEntity.url.uppercased().replacingOccurrences(of: "http://", with: "").replacingOccurrences(of: "https://", with: "")
string = self.linkEntity.url.uppercased().replacingOccurrences(of: "http://", with: "").replacingOccurrences(of: "https://", with: "").replacingOccurrences(of: "tonsite://", with: "")
}
let text = NSMutableAttributedString(string: string)
let range = NSMakeRange(0, text.length)

View File

@ -624,6 +624,15 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate
}
func getRenderSubEntities() -> [DrawingEntity] {
var explicitlyStaticStickers = Set<Int64>()
if let customEmojiContainerView = self.customEmojiContainerView {
for (key, view) in customEmojiContainerView.emojiLayers {
if let view = view as? EmojiTextAttachmentView, let numFrames = view.contentLayer.numFrames, numFrames == 1 {
explicitlyStaticStickers.insert(key.id)
}
}
}
let textSize = self.textView.bounds.size
let textPosition = self.textEntity.position
let scale = self.textEntity.scale
@ -638,6 +647,9 @@ public final class DrawingTextEntityView: DrawingEntityView, UITextViewDelegate
let emojiTextPosition = emojiRect.center.offsetBy(dx: -textSize.width / 2.0, dy: -textSize.height / 2.0)
let entity = DrawingStickerEntity(content: .file(.standalone(media: file), .sticker))
if explicitlyStaticStickers.contains(file.fileId.id) {
entity.isExplicitlyStatic = true
}
entity.referenceDrawingSize = CGSize(width: itemSize * 4.0, height: itemSize * 4.0)
entity.scale = scale
entity.position = textPosition.offsetBy(

View File

@ -477,16 +477,18 @@ public final class LegacyPaintEntityRenderer: NSObject, TGPhotoPaintEntityRender
}
func lcm(_ x: Int64, _ y: Int64) -> Int64 {
let x = max(x, 1)
let y = max(y, 1)
return x / gcd(x, y) * y
}
return combineLatest(durations)
|> map { durations in
var result: Double
let minDuration: Double = 3.0
if durations.count > 1 {
let reduced = durations.reduce(1.0) { lhs, rhs -> Double in
return Double(lcm(Int64(lhs * 10.0), Int64(rhs * 10.0)))
return Double(lcm(Int64(lhs * 100.0), Int64(rhs * 100.0)))
}
result = min(6.0, Double(reduced) / 10.0)
} else if let duration = durations.first {

View File

@ -33,12 +33,15 @@ private func currentTemperatureUnit() -> TemperatureUnit {
return temperatureUnit
}
public func stringForTemperature(_ value: Double) -> String {
private var formatter: MeasurementFormatter = {
let formatter = MeasurementFormatter()
formatter.locale = Locale.current
formatter.unitStyle = .short
formatter.numberFormatter.maximumFractionDigits = 0
formatter.unitOptions = .temperatureWithoutUnit
return formatter
}()
public func stringForTemperature(_ value: Double) -> String {
let valueString = formatter.string(from: Measurement(value: value, unit: UnitTemperature.celsius)).trimmingCharacters(in: CharacterSet(charactersIn: "0123456789-,.").inverted)
return valueString + currentTemperatureUnit().suffix
}

View File

@ -776,7 +776,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget {
}
public final class EmojiTextAttachmentView: UIView {
private let contentLayer: InlineStickerItemLayer
public let contentLayer: InlineStickerItemLayer
public var isActive: Bool = true {
didSet {
@ -826,7 +826,7 @@ public final class EmojiTextAttachmentView: UIView {
public final class CustomEmojiContainerView: UIView {
private let emojiViewProvider: (ChatTextInputTextCustomEmojiAttribute) -> UIView?
private var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:]
public private(set) var emojiLayers: [InlineStickerItemLayer.Key: UIView] = [:]
public init(emojiViewProvider: @escaping (ChatTextInputTextCustomEmojiAttribute) -> UIView?) {
self.emojiViewProvider = emojiViewProvider

View File

@ -88,11 +88,15 @@ public final class DrawingTextEntity: DrawingEntity, Codable {
return true
}
var isAnimated = false
self.text.enumerateAttributes(in: NSMakeRange(0, self.text.length), options: [], using: { attributes, range, _ in
if let _ = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute {
isAnimated = true
if let renderSubEntities = self.renderSubEntities {
for entity in renderSubEntities {
if entity.isAnimated {
isAnimated = true
break
}
}
})
}
return isAnimated
}

View File

@ -10,6 +10,7 @@ import UIKitRuntimeUtils
private let minimizedNavigationHeight: CGFloat = 44.0
private let minimizedTopMargin: CGFloat = 3.0
private let maximizeLastStandingController = false
final class ScrollViewImpl: UIScrollView {
var shouldPassthrough: () -> Bool = { return false }
@ -112,7 +113,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.snapshotContainerView.isUserInteractionEnabled = false
super.init()
self.clipsToBounds = true
self.cornerRadius = 10.0
applySmoothRoundedCorners(self.layer)
@ -308,7 +309,9 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
private var presentationDataDisposable: Disposable?
public private(set) var isExpanded: Bool = false
public var willMaximize: (() -> Void)?
public var willMaximize: ((MinimizedContainer) -> Void)?
public var willDismiss: ((MinimizedContainer) -> Void)?
public var didDismiss: ((MinimizedContainer) -> Void)?
public private(set) var statusBarStyle: StatusBarStyle = .White
public var statusBarStyleUpdated: (() -> Void)?
@ -500,10 +503,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.currentTransition = .dismiss(itemId: itemId)
self.items.removeAll(where: { $0.id == itemId })
if self.items.count == 1 {
if self.items.count == 1, maximizeLastStandingController {
self.isExpanded = false
self.willMaximize?()
self.willMaximize?(self)
needsLayout = false
} else if self.items.count == 0 {
self.willDismiss?(self)
self.isExpanded = false
}
}
if let item = self.items.first(where: { $0.id == itemId }), !item.controller.shouldDismissImmediately() {
@ -558,6 +564,15 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.requestUpdate(transition: transition)
}
public func removeController(_ viewController: MinimizableController) {
guard let item = self.items.first(where: { $0.controller === viewController }) else {
return
}
self.items.removeAll(where: { $0.id == item.id })
self.requestUpdate(transition: .animated(duration: 0.25, curve: .easeInOut))
}
private enum Transition: Equatable {
case minimize(itemId: AnyHashable)
case maximize(itemId: AnyHashable)
@ -759,7 +774,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
if let currentTransition = self.currentTransition {
if currentTransition.matches(item: item) {
continue
} else if case .dismiss = currentTransition, self.items.count == 1 {
} else if case .dismiss = currentTransition, self.items.count == 1 && maximizeLastStandingController {
continue
}
}
@ -789,10 +804,13 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.currentTransition = .dismiss(itemId: item.id)
self.items.removeAll(where: { $0.id == item.id })
if self.items.count == 1 {
if self.items.count == 1, maximizeLastStandingController {
self.isExpanded = false
self.willMaximize?()
self.willMaximize?(self)
needsLayout = false
} else if self.items.count == 0 {
self.isExpanded = false
self.willDismiss?(self)
}
if needsLayout {
self.requestUpdate(transition: .animated(duration: 0.4, curve: .spring))
@ -1097,7 +1115,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
guard let dismissedItemNode = self.itemNodes[itemId] else {
return
}
if self.items.count == 1 {
if self.items.count == 1, maximizeLastStandingController {
if let itemNode = self.itemNodes.first(where: { $0.0 != itemId })?.value, let navigationController = self.navigationController {
itemNode.item.beforeMaximize(navigationController, { [weak self] in
guard let self else {
@ -1137,6 +1155,7 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
}
transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y))
} else {
let isLast = self.items.isEmpty
transition.updatePosition(node: dismissedItemNode, position: CGPoint(x: -layout.size.width, y: dismissedItemNode.position.y), completion: { _ in
self.isApplyingTransition = false
if self.currentTransition == currentTransition {
@ -1146,7 +1165,15 @@ public class MinimizedContainerImpl: ASDisplayNode, MinimizedContainer, ASScroll
self.itemNodes[itemId] = nil
dismissedItemNode.removeFromSupernode()
if isLast {
self.didDismiss?(self)
}
})
if isLast {
let dismissOffset = collapsedHeight(layout: layout)
transition.updatePosition(layer: self.bottomEdgeView.layer, position: self.bottomEdgeView.layer.position.offsetBy(dx: 0.0, dy: dismissOffset))
}
}
case .dismissAll:
let dismissOffset = collapsedHeight(layout: layout)

View File

@ -73,7 +73,7 @@ final class MinimizedHeaderNode: ASDisplayNode {
guard let self else {
return
}
let titles = titles.compactMap { $0 }
let titles = titles.compactMap { $0 }.filter { !$0.isEmpty }
if titles.count == 1, let title = titles.first {
self.title = title
} else if let title = titles.last {

View File

@ -113,7 +113,10 @@ func interitemSpacing(itemCount: Int, boundingSize: CGSize, insets: UIEdgeInsets
func frameForIndex(index: Int, size: CGSize, insets: UIEdgeInsets, itemCount: Int, boundingSize: CGSize) -> CGRect {
let spacing = interitemSpacing(itemCount: itemCount, boundingSize: boundingSize, insets: insets)
let y = additionalInsetTop + insets.top + spacing * CGFloat(index)
var y = additionalInsetTop + insets.top + spacing * CGFloat(index)
if itemCount == 1 {
y += 72.0
}
let origin = CGPoint(x: insets.left, y: y)
return CGRect(origin: origin, size: CGSize(width: size.width - insets.left - insets.right, height: size.height))

View File

@ -17,6 +17,7 @@ private var nextRenderTargetId: Int64 = 1
open class MultiAnimationRenderTarget: SimpleLayer {
public let id: Int64
public var numFrames: Int?
let deinitCallbacks = Bag<() -> Void>()
let updateStateCallbacks = Bag<() -> Void>()
@ -545,6 +546,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer {
}
target.contents = loadedFrame.image.cgImage
target.numFrames = item.numFrames
if let blurredRepresentationTarget = target.blurredRepresentationTarget {
blurredRepresentationTarget.contents = loadedFrame.blurredRepresentation(color: target.blurredRepresentationBackgroundColor)?.cgImage
@ -580,6 +582,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer {
completion(false, true)
return
}
target.numFrames = item.numFrames
if let loadedFrame = loadedFrame {
if let cgImage = loadedFrame.image.cgImage {
if hadIntermediateUpdate {

View File

@ -336,7 +336,7 @@ public final class StarsLabelComponent: CombinedComponent {
transition: context.transition
)
let iconSize = CGSize(width: 20.0, height: 20.0)
let iconSize = CGSize(width: 24.0, height: 24.0)
let icon = icon.update(
component: BundleIconComponent(
name: "Premium/Stars/StarLarge",

View File

@ -699,7 +699,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
originY += description.size.height + 10.0
}
let amountSpacing: CGFloat = 3.0
let amountSpacing: CGFloat = 1.0
var totalAmountWidth: CGFloat = amount.size.width + amountSpacing + amountStar.size.width
var amountOriginX: CGFloat = floor(context.availableSize.width - totalAmountWidth) / 2.0
if isRefund {
@ -746,8 +746,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
context.add(amountStar
.position(CGPoint(x: amountOriginX + amount.size.width + amountSpacing + amountStar.size.width / 2.0, y: amountOrigin + amountStar.size.height / 2.0))
)
context.add(table
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + table.size.height / 2.0))
)

View File

@ -161,7 +161,7 @@ final class StarsBalanceComponent: Component {
let titleFrame = CGRect(origin: CGPoint(x: origin + icon.size.width + spacing, y: contentHeight - 3.0), size: titleSize)
titleView.frame = titleFrame
self.icon.frame = CGRect(origin: CGPoint(x: origin, y: contentHeight + 2.0), size: icon.size)
self.icon.frame = CGRect(origin: CGPoint(x: origin, y: contentHeight), size: icon.size)
}
}
contentHeight += titleSize.height

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "balancestar_48 (2).pdf",
"filename" : "StarBalance.pdf",
"idiom" : "universal"
}
],

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "Star20 (3).pdf",
"filename" : "StarLarge.pdf",
"idiom" : "universal"
}
],

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "star_18 (3).pdf",
"filename" : "StarMedium.pdf",
"idiom" : "universal"
}
],

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "star_16 (3).pdf",
"filename" : "StarSmall.pdf",
"idiom" : "universal"
}
],