mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
[WIP] Stories
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "ChatSendButtonRadialStatusNode",
|
||||
module_name = "ChatSendButtonRadialStatusNode",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/Display",
|
||||
"//submodules/SSignalKit/SwiftSignalKit",
|
||||
"//submodules/LegacyComponents",
|
||||
"//submodules/ChatPresentationInterfaceState",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,196 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import LegacyComponents
|
||||
import ChatPresentationInterfaceState
|
||||
|
||||
private final class ChatSendButtonRadialStatusNodeParameters: NSObject {
|
||||
let color: UIColor
|
||||
let progress: CGFloat
|
||||
|
||||
init(color: UIColor, progress: CGFloat) {
|
||||
self.color = color
|
||||
self.progress = progress
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChatSendButtonRadialStatusNode: ASDisplayNode {
|
||||
private let color: UIColor
|
||||
|
||||
private var effectiveProgress: CGFloat = 0.0 {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public var slowmodeState: ChatSlowmodeState? = nil {
|
||||
didSet {
|
||||
if self.slowmodeState != oldValue {
|
||||
self.updateProgress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var updateTimer: SwiftSignalKit.Timer?
|
||||
|
||||
public init(color: UIColor) {
|
||||
self.color = color
|
||||
|
||||
super.init()
|
||||
|
||||
self.isUserInteractionEnabled = false
|
||||
self.isOpaque = false
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.updateTimer?.invalidate()
|
||||
}
|
||||
|
||||
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||
return ChatSendButtonRadialStatusNodeParameters(color: self.color, progress: self.effectiveProgress)
|
||||
}
|
||||
|
||||
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
if !isRasterizing {
|
||||
context.setBlendMode(.copy)
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.fill(bounds)
|
||||
}
|
||||
|
||||
if let parameters = parameters as? ChatSendButtonRadialStatusNodeParameters {
|
||||
context.setStrokeColor(parameters.color.cgColor)
|
||||
|
||||
var progress = parameters.progress
|
||||
let startAngle = -CGFloat.pi / 2.0
|
||||
let endAngle = CGFloat(progress) * 2.0 * CGFloat.pi + startAngle
|
||||
|
||||
progress = min(1.0, progress)
|
||||
|
||||
let lineWidth: CGFloat = 2.0
|
||||
|
||||
let pathDiameter = bounds.size.width - lineWidth
|
||||
|
||||
let path = UIBezierPath(arcCenter: CGPoint(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0), radius: pathDiameter / 2.0, startAngle: startAngle, endAngle: endAngle, clockwise: true)
|
||||
path.lineWidth = lineWidth
|
||||
path.lineCapStyle = .round
|
||||
path.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateProgress() {
|
||||
if let slowmodeState = self.slowmodeState {
|
||||
let progress: CGFloat
|
||||
switch slowmodeState.variant {
|
||||
case .pendingMessages:
|
||||
progress = 1.0
|
||||
case let .timestamp(validUntilTimestamp):
|
||||
let timestamp = CGFloat(Date().timeIntervalSince1970)
|
||||
let relativeTimestamp = CGFloat(validUntilTimestamp) - timestamp
|
||||
progress = max(0.0, min(1.0, CGFloat(relativeTimestamp / CGFloat(slowmodeState.timeout))))
|
||||
}
|
||||
|
||||
self.effectiveProgress = progress
|
||||
self.updateTimer?.invalidate()
|
||||
self.updateTimer = SwiftSignalKit.Timer(timeout: 1.0 / 60.0, repeat: false, completion: { [weak self] in
|
||||
self?.updateProgress()
|
||||
}, queue: .mainQueue())
|
||||
self.updateTimer?.start()
|
||||
} else {
|
||||
self.effectiveProgress = 0.0
|
||||
self.updateTimer?.invalidate()
|
||||
self.updateTimer = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ChatSendButtonRadialStatusView: UIView {
|
||||
private let color: UIColor
|
||||
|
||||
private var effectiveProgress: CGFloat = 0.0 {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
public var slowmodeState: ChatSlowmodeState? = nil {
|
||||
didSet {
|
||||
if self.slowmodeState != oldValue {
|
||||
self.updateProgress()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var updateTimer: SwiftSignalKit.Timer?
|
||||
|
||||
public init(color: UIColor) {
|
||||
self.color = color
|
||||
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.isUserInteractionEnabled = false
|
||||
self.isOpaque = false
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.updateTimer?.invalidate()
|
||||
}
|
||||
|
||||
override public func draw(_ rect: CGRect) {
|
||||
if rect.isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
context.setStrokeColor(self.color.cgColor)
|
||||
|
||||
var progress = self.effectiveProgress
|
||||
let startAngle = -CGFloat.pi / 2.0
|
||||
let endAngle = CGFloat(progress) * 2.0 * CGFloat.pi + startAngle
|
||||
|
||||
progress = min(1.0, progress)
|
||||
|
||||
let lineWidth: CGFloat = 2.0
|
||||
|
||||
let pathDiameter = bounds.size.width - lineWidth
|
||||
|
||||
let path = UIBezierPath(arcCenter: CGPoint(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0), radius: pathDiameter / 2.0, startAngle: startAngle, endAngle: endAngle, clockwise: true)
|
||||
path.lineWidth = lineWidth
|
||||
path.lineCapStyle = .round
|
||||
path.stroke()
|
||||
}
|
||||
|
||||
private func updateProgress() {
|
||||
if let slowmodeState = self.slowmodeState {
|
||||
let progress: CGFloat
|
||||
switch slowmodeState.variant {
|
||||
case .pendingMessages:
|
||||
progress = 1.0
|
||||
case let .timestamp(validUntilTimestamp):
|
||||
let timestamp = CGFloat(Date().timeIntervalSince1970)
|
||||
let relativeTimestamp = CGFloat(validUntilTimestamp) - timestamp
|
||||
progress = max(0.0, min(1.0, CGFloat(relativeTimestamp / CGFloat(slowmodeState.timeout))))
|
||||
}
|
||||
|
||||
self.effectiveProgress = progress
|
||||
self.updateTimer?.invalidate()
|
||||
self.updateTimer = SwiftSignalKit.Timer(timeout: 1.0 / 60.0, repeat: false, completion: { [weak self] in
|
||||
self?.updateProgress()
|
||||
}, queue: .mainQueue())
|
||||
self.updateTimer?.start()
|
||||
} else {
|
||||
self.effectiveProgress = 0.0
|
||||
self.updateTimer?.invalidate()
|
||||
self.updateTimer = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user