mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-28 19:05:49 +00:00
# Conflicts: # submodules/AttachmentUI/Sources/AttachmentPanel.swift # submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift # submodules/TelegramUI/BUILD # submodules/TelegramUI/Components/Chat/ChatRecentActionsController/Sources/ChatRecentActionsController.swift # submodules/TelegramUI/Components/Chat/ChatTextInputActionButtonsNode/Sources/ChatTextInputActionButtonsNode.swift # submodules/TelegramUI/Components/Chat/ChatTextInputPanelNode/Sources/ChatTextInputPanelNode.swift # submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift # submodules/TelegramUI/Components/PeerSelectionController/Sources/PeerSelectionControllerNode.swift # submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift # submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift
131 lines
5.7 KiB
Swift
131 lines
5.7 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import Display
|
|
import AsyncDisplayKit
|
|
import TelegramPresentationData
|
|
import SwiftSignalKit
|
|
import ChatPresentationInterfaceState
|
|
import AnimatedCountLabelNode
|
|
import TelegramStringFormatting
|
|
|
|
private func generateClearImage(color: UIColor) -> UIImage? {
|
|
return generateImage(CGSize(width: 17.0, height: 17.0), rotatedContext: { size, context in
|
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
|
context.setFillColor(color.cgColor)
|
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
|
context.setBlendMode(.copy)
|
|
context.setStrokeColor(UIColor.clear.cgColor)
|
|
context.setLineCap(.round)
|
|
context.setLineWidth(1.66)
|
|
context.move(to: CGPoint(x: 6.0, y: 6.0))
|
|
context.addLine(to: CGPoint(x: 11.0, y: 11.0))
|
|
context.strokePath()
|
|
context.move(to: CGPoint(x: size.width - 6.0, y: 6.0))
|
|
context.addLine(to: CGPoint(x: size.width - 11.0, y: 11.0))
|
|
context.strokePath()
|
|
})
|
|
}
|
|
|
|
|
|
final class BoostSlowModeButton: HighlightTrackingButtonNode {
|
|
let containerNode: ASDisplayNode
|
|
let backgroundNode: ASImageNode
|
|
let textNode: ImmediateAnimatedCountLabelNode
|
|
let iconNode: ASImageNode
|
|
|
|
private var updateTimer: SwiftSignalKit.Timer?
|
|
|
|
var requestUpdate: () -> Void = {}
|
|
|
|
override init(pointerStyle: PointerStyle? = nil) {
|
|
self.containerNode = ASDisplayNode()
|
|
|
|
self.backgroundNode = ASImageNode()
|
|
self.backgroundNode.displaysAsynchronously = false
|
|
self.backgroundNode.clipsToBounds = true
|
|
self.backgroundNode.image = generateGradientImage(size: CGSize(width: 100.0, height: 2.0), scale: 1.0, colors: [UIColor(rgb: 0x9076ff), UIColor(rgb: 0xbc6de8)], locations: [0.0, 1.0], direction: .horizontal)
|
|
|
|
self.iconNode = ASImageNode()
|
|
self.iconNode.displaysAsynchronously = false
|
|
self.iconNode.image = generateClearImage(color: .white)
|
|
|
|
self.textNode = ImmediateAnimatedCountLabelNode()
|
|
self.textNode.alwaysOneDirection = true
|
|
self.textNode.isUserInteractionEnabled = false
|
|
|
|
super.init(pointerStyle: pointerStyle)
|
|
|
|
self.addSubnode(self.containerNode)
|
|
self.containerNode.addSubnode(self.backgroundNode)
|
|
self.containerNode.addSubnode(self.iconNode)
|
|
self.containerNode.addSubnode(self.textNode)
|
|
|
|
self.highligthedChanged = { [weak self] highlighted in
|
|
if let self {
|
|
if highlighted {
|
|
self.containerNode.layer.animateScale(from: 1.0, to: 0.75, duration: 0.4, removeOnCompletion: false)
|
|
} else if let presentationLayer = self.containerNode.layer.presentation() {
|
|
self.containerNode.layer.animateScale(from: CGFloat((presentationLayer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0), to: 1.0, duration: 0.25, removeOnCompletion: false)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func update(size: CGSize, interfaceState: ChatPresentationInterfaceState) -> CGSize {
|
|
var text = ""
|
|
if let slowmodeState = interfaceState.slowmodeState {
|
|
let relativeTimestamp: CGFloat
|
|
switch slowmodeState.variant {
|
|
case let .timestamp(validUntilTimestamp):
|
|
let timestamp = CGFloat(Date().timeIntervalSince1970)
|
|
relativeTimestamp = CGFloat(validUntilTimestamp) - timestamp
|
|
case .pendingMessages:
|
|
relativeTimestamp = CGFloat(slowmodeState.timeout)
|
|
}
|
|
|
|
self.updateTimer?.invalidate()
|
|
|
|
if relativeTimestamp >= 0.0 {
|
|
text = stringForDuration(Int32(relativeTimestamp))
|
|
|
|
self.updateTimer = SwiftSignalKit.Timer(timeout: 1.0 / 60.0, repeat: false, completion: { [weak self] in
|
|
self?.requestUpdate()
|
|
}, queue: .mainQueue())
|
|
self.updateTimer?.start()
|
|
}
|
|
} else {
|
|
self.updateTimer?.invalidate()
|
|
self.updateTimer = nil
|
|
}
|
|
|
|
let font = Font.with(size: 15.0, design: .round, weight: .semibold, traits: [.monospacedNumbers])
|
|
let textColor = UIColor.white
|
|
|
|
var segments: [AnimatedCountLabelNode.Segment] = []
|
|
var textCount = 0
|
|
|
|
for char in text {
|
|
if let intValue = Int(String(char)) {
|
|
segments.append(.number(intValue, NSAttributedString(string: String(char), font: font, textColor: textColor)))
|
|
} else {
|
|
segments.append(.text(textCount, NSAttributedString(string: String(char), font: font, textColor: textColor)))
|
|
textCount += 1
|
|
}
|
|
}
|
|
self.textNode.segments = segments
|
|
|
|
let textSize = self.textNode.updateLayout(size: CGSize(width: 200.0, height: 100.0), animated: true)
|
|
let totalSize = CGSize(width: textSize.width > 0.0 ? textSize.width + 38.0 : 33.0, height: 33.0)
|
|
|
|
self.containerNode.bounds = CGRect(origin: .zero, size: totalSize)
|
|
self.containerNode.position = CGPoint(x: totalSize.width / 2.0, y: totalSize.height / 2.0)
|
|
self.backgroundNode.frame = CGRect(origin: .zero, size: totalSize)
|
|
self.backgroundNode.cornerRadius = totalSize.height / 2.0
|
|
self.textNode.frame = CGRect(origin: CGPoint(x: 9.0, y: floorToScreenPixels((totalSize.height - textSize.height) / 2.0)), size: textSize)
|
|
if let icon = self.iconNode.image {
|
|
self.iconNode.frame = CGRect(origin: CGPoint(x: totalSize.width - icon.size.width - 7.0, y: floorToScreenPixels((totalSize.height - icon.size.height) / 2.0)), size: icon.size)
|
|
}
|
|
return totalSize
|
|
}
|
|
}
|