Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2021-01-23 23:46:17 +03:00
commit 8467d6b387
48 changed files with 1251 additions and 1216 deletions

View File

@ -757,6 +757,8 @@ public final class AnimatedStickerNode: ASDisplayNode {
private var canDisplayFirstFrame: Bool = false
private var playbackMode: AnimatedStickerPlaybackMode = .loop
public var stopAtNearestLoop: Bool = false
private let playbackStatus = Promise<AnimatedStickerStatus>()
public var status: Signal<AnimatedStickerStatus, NoError> {
return self.playbackStatus.get()
@ -966,7 +968,13 @@ public final class AnimatedStickerNode: ASDisplayNode {
if frame.isLastFrame {
var stopped = false
var stopNow = false
if case .once = strongSelf.playbackMode {
stopNow = true
} else if strongSelf.stopAtNearestLoop {
stopNow = true
}
if stopNow {
strongSelf.stop()
strongSelf.isPlaying = false
stopped = true
@ -1043,7 +1051,13 @@ public final class AnimatedStickerNode: ASDisplayNode {
if frame.isLastFrame {
var stopped = false
var stopNow = false
if case .once = strongSelf.playbackMode {
stopNow = true
} else if strongSelf.stopAtNearestLoop {
stopNow = true
}
if stopNow {
strongSelf.stop()
strongSelf.isPlaying = false
stopped = true

View File

@ -0,0 +1,227 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
private final class ZoomWheelNodeDrawingState: NSObject {
let transition: CGFloat
let reverse: Bool
init(transition: CGFloat, reverse: Bool) {
self.transition = transition
self.reverse = reverse
super.init()
}
}
final class ZoomWheelNode: ASDisplayNode {
class State: Equatable {
let active: Bool
init(active: Bool) {
self.active = active
}
static func ==(lhs: State, rhs: State) -> Bool {
if lhs.active != rhs.active {
return false
}
return true
}
}
private class TransitionContext {
let startTime: Double
let duration: Double
let previousState: State
init(startTime: Double, duration: Double, previousState: State) {
self.startTime = startTime
self.duration = duration
self.previousState = previousState
}
}
private var animator: ConstantDisplayLinkAnimator?
private var hasState = false
private var state: State = State(active: false)
private var transitionContext: TransitionContext?
override init() {
super.init()
self.isOpaque = false
}
func update(state: State, animated: Bool) {
var animated = animated
if !self.hasState {
self.hasState = true
animated = false
}
if self.state != state {
let previousState = self.state
self.state = state
if animated {
self.transitionContext = TransitionContext(startTime: CACurrentMediaTime(), duration: 0.18, previousState: previousState)
}
self.updateAnimations()
self.setNeedsDisplay()
}
}
private func updateAnimations() {
var animate = false
let timestamp = CACurrentMediaTime()
if let transitionContext = self.transitionContext {
if transitionContext.startTime + transitionContext.duration < timestamp {
self.transitionContext = nil
} else {
animate = true
}
}
if animate {
let animator: ConstantDisplayLinkAnimator
if let current = self.animator {
animator = current
} else {
animator = ConstantDisplayLinkAnimator(update: { [weak self] in
self?.updateAnimations()
})
self.animator = animator
}
animator.isPaused = false
} else {
self.animator?.isPaused = true
}
self.setNeedsDisplay()
}
override public func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
var transitionFraction: CGFloat = self.state.active ? 1.0 : 0.0
var reverse = false
if let transitionContext = self.transitionContext {
let timestamp = CACurrentMediaTime()
var t = CGFloat((timestamp - transitionContext.startTime) / transitionContext.duration)
t = min(1.0, max(0.0, t))
if transitionContext.previousState.active != self.state.active {
transitionFraction = self.state.active ? t : 1.0 - t
reverse = transitionContext.previousState.active
}
}
return ZoomWheelNodeDrawingState(transition: transitionFraction, reverse: reverse)
}
@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)
}
guard let parameters = parameters as? ZoomWheelNodeDrawingState else {
return
}
let color = UIColor(rgb: 0xffffff)
context.setFillColor(color.cgColor)
let clearLineWidth: CGFloat = 4.0
let lineWidth: CGFloat = 1.0 + UIScreenPixel
context.scaleBy(x: 2.5, y: 2.5)
context.translateBy(x: 4.0, y: 3.0)
let _ = try? drawSvgPath(context, path: "M14,8.335 C14.36727,8.335 14.665,8.632731 14.665,9 C14.665,11.903515 12.48064,14.296846 9.665603,14.626311 L9.665,16 C9.665,16.367269 9.367269,16.665 9,16.665 C8.666119,16.665 8.389708,16.418942 8.34221,16.098269 L8.335,16 L8.3354,14.626428 C5.519879,14.297415 3.335,11.90386 3.335,9 C3.335,8.632731 3.632731,8.335 4,8.335 C4.367269,8.335 4.665,8.632731 4.665,9 C4.665,11.394154 6.605846,13.335 9,13.335 C11.39415,13.335 13.335,11.394154 13.335,9 C13.335,8.632731 13.63273,8.335 14,8.335 Z ")
let _ = try? drawSvgPath(context, path: "M9,2.5 C10.38071,2.5 11.5,3.61929 11.5,5 L11.5,9 C11.5,10.380712 10.38071,11.5 9,11.5 C7.619288,11.5 6.5,10.380712 6.5,9 L6.5,5 C6.5,3.61929 7.619288,2.5 9,2.5 Z ")
context.translateBy(x: -4.0, y: -3.0)
if parameters.transition > 0.0 {
let startPoint: CGPoint
let endPoint: CGPoint
let origin = CGPoint(x: 9.0, y: 10.0 - UIScreenPixel)
let length: CGFloat = 17.0
if parameters.reverse {
startPoint = CGPoint(x: origin.x + length * (1.0 - parameters.transition), y: origin.y + length * (1.0 - parameters.transition))
endPoint = CGPoint(x: origin.x + length, y: origin.y + length)
} else {
startPoint = origin
endPoint = CGPoint(x: origin.x + length * parameters.transition, y: origin.y + length * parameters.transition)
}
context.setBlendMode(.clear)
context.setLineWidth(clearLineWidth)
context.move(to: startPoint)
context.addLine(to: endPoint)
context.strokePath()
context.setBlendMode(.normal)
context.setStrokeColor(color.cgColor)
context.setLineWidth(lineWidth)
context.setLineCap(.round)
context.setLineJoin(.round)
context.move(to: startPoint)
context.addLine(to: endPoint)
context.strokePath()
}
}
}
private class ButtonNode: HighlightTrackingButtonNode {
private let backgroundNode: ASDisplayNode
private let textNode: ImmediateTextNode
init() {
self.backgroundNode = ASDisplayNode()
self.textNode = ImmediateTextNode()
super.init()
self.addSubnode(self.backgroundNode)
self.addSubnode(self.textNode)
self.highligthedChanged = { [weak self] highlight in
if let strongSelf = self {
}
}
}
func update() {
}
}
final class CameraZoomNode: ASDisplayNode {
private let wheelNode: ZoomWheelNode
private let backgroundNode: ASDisplayNode
override init() {
self.wheelNode = ZoomWheelNode()
self.backgroundNode = ASDisplayNode()
super.init()
self.addSubnode(self.wheelNode)
}
}

View File

@ -22,6 +22,7 @@ swift_library(
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/ChatHistoryImportTasks:ChatHistoryImportTasks",
"//submodules/MimeTypes:MimeTypes",
"//submodules/ConfettiEffect:ConfettiEffect",
],
visibility = [
"//visibility:public",

View File

@ -13,6 +13,7 @@ import AnimatedStickerNode
import AppBundle
import ZIPFoundation
import MimeTypes
import ConfettiEffect
public final class ChatImportActivityScreen: ViewController {
private final class Node: ViewControllerTracingNode {
@ -22,6 +23,7 @@ public final class ChatImportActivityScreen: ViewController {
private var presentationData: PresentationData
private let animationNode: AnimatedStickerNode
private let doneAnimationNode: AnimatedStickerNode
private let radialStatus: RadialStatusNode
private let radialCheck: RadialStatusNode
private let radialStatusBackground: ASImageNode
@ -38,6 +40,8 @@ public final class ChatImportActivityScreen: ViewController {
private let totalBytes: Int
private var isDone: Bool = false
private var feedback: HapticFeedback?
init(controller: ChatImportActivityScreen, context: AccountContext, totalBytes: Int) {
self.controller = controller
self.context = context
@ -46,6 +50,8 @@ public final class ChatImportActivityScreen: ViewController {
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
self.animationNode = AnimatedStickerNode()
self.doneAnimationNode = AnimatedStickerNode()
self.doneAnimationNode.isHidden = true
self.radialStatus = RadialStatusNode(backgroundNodeColor: .clear)
self.radialCheck = RadialStatusNode(backgroundNodeColor: .clear)
@ -89,8 +95,19 @@ public final class ChatImportActivityScreen: ViewController {
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 170 * 2, height: 170 * 2, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
self.animationNode.visibility = true
}
if let path = getAppBundle().path(forResource: "HistoryImportDone", ofType: "tgs") {
self.doneAnimationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 170 * 2, height: 170 * 2, playbackMode: .once, mode: .direct(cachePathPrefix: nil))
self.doneAnimationNode.started = { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.animationNode.isHidden = true
}
self.doneAnimationNode.visibility = false
}
self.addSubnode(self.animationNode)
self.addSubnode(self.doneAnimationNode)
self.addSubnode(self.radialStatusBackground)
self.addSubnode(self.radialStatus)
self.addSubnode(self.radialCheck)
@ -112,6 +129,15 @@ public final class ChatImportActivityScreen: ViewController {
}
}
}
self.animationNode.completed = { [weak self] stopped in
guard let strongSelf = self, stopped else {
return
}
strongSelf.animationNode.visibility = false
strongSelf.doneAnimationNode.visibility = true
strongSelf.doneAnimationNode.isHidden = false
}
}
@objc private func statusButtonPressed() {
@ -119,6 +145,7 @@ public final class ChatImportActivityScreen: ViewController {
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
let isFirstLayout = self.validLayout == nil
self.validLayout = (layout, navigationHeight)
//TODO:localize
@ -156,11 +183,14 @@ public final class ChatImportActivityScreen: ViewController {
}
transition.updateAlpha(node: self.animationNode, alpha: hideIcon ? 0.0 : 1.0)
transition.updateAlpha(node: self.doneAnimationNode, alpha: hideIcon ? 0.0 : 1.0)
let contentOriginY = navigationHeight + floor((layout.size.height - contentHeight) / 2.0)
self.animationNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentOriginY), size: iconSize)
self.animationNode.updateLayout(size: iconSize)
self.doneAnimationNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: contentOriginY), size: iconSize)
self.doneAnimationNode.updateLayout(size: iconSize)
self.radialStatus.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - radialStatusSize.width) / 2.0), y: hideIcon ? contentOriginY : (contentOriginY + iconSize.height + maxIconStatusSpacing)), size: radialStatusSize)
let checkSize: CGFloat = 130.0
@ -184,17 +214,22 @@ public final class ChatImportActivityScreen: ViewController {
self.statusButtonText.isHidden = !self.isDone
self.statusButton.isHidden = !self.isDone
self.progressText.isHidden = self.isDone
if isFirstLayout {
self.updateProgress(totalProgress: self.totalProgress, isDone: self.isDone, animated: false)
}
}
func updateProgress(totalProgress: CGFloat, isDone: Bool, animated: Bool) {
self.totalProgress = totalProgress
let wasDone = self.isDone
self.isDone = isDone
if let (layout, navigationHeight) = self.validLayout {
self.containerLayoutUpdated(layout, navigationHeight: navigationHeight, transition: .immediate)
self.radialStatus.transitionToState(.progress(color: self.presentationData.theme.list.itemAccentColor, lineWidth: 6.0, value: max(0.02, self.totalProgress), cancelEnabled: false), animated: animated, synchronous: true, completion: {})
self.radialStatus.transitionToState(.progress(color: self.presentationData.theme.list.itemAccentColor, lineWidth: 6.0, value: max(0.02, self.totalProgress), cancelEnabled: false, animateRotation: false), animated: animated, synchronous: true, completion: {})
if isDone {
self.radialCheck.transitionToState(.progress(color: .clear, lineWidth: 6.0, value: self.totalProgress, cancelEnabled: false), animated: false, synchronous: true, completion: {})
self.radialCheck.transitionToState(.progress(color: .clear, lineWidth: 6.0, value: self.totalProgress, cancelEnabled: false, animateRotation: false), animated: false, synchronous: true, completion: {})
self.radialCheck.transitionToState(.check(self.presentationData.theme.list.itemAccentColor), animated: animated, synchronous: true, completion: {})
self.radialStatus.layer.animateScale(from: 1.0, to: 1.05, duration: 0.07, delay: 0.0, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false, additive: false, completion: { [weak self] _ in
guard let strongSelf = self else {
@ -216,6 +251,17 @@ public final class ChatImportActivityScreen: ViewController {
transition = .immediate
}
transition.updateAlpha(node: self.radialStatusText, alpha: 0.0)
if !wasDone {
self.view.addSubview(ConfettiView(frame: self.view.bounds))
if self.feedback == nil {
self.feedback = HapticFeedback()
}
self.feedback?.success()
self.animationNode.stopAtNearestLoop = true
}
}
}
}

View File

@ -234,7 +234,7 @@ private final class VisualMediaItemNode: ASDisplayNode {
switch status {
case let .Fetching(_, progress):
let adjustedProgress = max(progress, 0.027)
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
case .Local:
statusState = .none
case .Remote:

View File

@ -459,14 +459,14 @@ private class ChatListStatusProgressNode: ChatListStatusContentNode {
super.init()
self.statusNode.transitionToState(.progress(color: color, lineWidth: 1.0, value: progress, cancelEnabled: false))
self.statusNode.transitionToState(.progress(color: color, lineWidth: 1.0, value: progress, cancelEnabled: false, animateRotation: true))
self.addSubnode(self.statusNode)
}
override func updateWithState(_ state: ChatListStatusNodeState, animated: Bool) {
if case let .progress(color, progress) = state {
self.statusNode.transitionToState(.progress(color: color, lineWidth: 1.0, value: progress, cancelEnabled: false), animated: animated, completion: {})
self.statusNode.transitionToState(.progress(color: color, lineWidth: 1.0, value: progress, cancelEnabled: false, animateRotation: true), animated: animated, completion: {})
}
}

View File

@ -279,7 +279,7 @@ public final class ChatMessageInteractiveMediaBadge: ASDisplayNode {
isCompact = true
originY = -1.0 - UIScreenPixel
case .compactFetching:
state = .progress(color: .white, lineWidth: nil, value: 0.0, cancelEnabled: true)
state = .progress(color: .white, lineWidth: nil, value: 0.0, cancelEnabled: true, animateRotation: true)
isCompact = true
originY = -1.0
}

View File

@ -0,0 +1,16 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "ConfettiEffect",
module_name = "ConfettiEffect",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
],
visibility = [
"//visibility:public",
],
)

View File

@ -44,13 +44,13 @@ private final class ParticleLayer: CALayer {
}
}
final class ConfettiView: UIView {
public final class ConfettiView: UIView {
private var particles: [ParticleLayer] = []
private var displayLink: ConstantDisplayLinkAnimator?
private var localTime: Float = 0.0
override init(frame: CGRect) {
override public init(frame: CGRect) {
super.init(frame: frame)
self.isUserInteractionEnabled = false
@ -142,7 +142,7 @@ final class ConfettiView: UIView {
self.displayLink?.isPaused = false
}
required init?(coder: NSCoder) {
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

View File

@ -214,10 +214,10 @@ final class ChatAnimationGalleryItemNode: ZoomableContentGalleryItemNode {
strongSelf.statusNode.alpha = 1.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
let adjustedProgress = max(progress, 0.027)
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true), completion: {})
case .Local:
if let previousStatus = previousStatus, case .Fetching = previousStatus {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true, animateRotation: true), completion: {
if let strongSelf = self {
strongSelf.statusNode.alpha = 0.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = false

View File

@ -203,10 +203,10 @@ class ChatDocumentGalleryItemNode: ZoomableContentGalleryItemNode, WKNavigationD
strongSelf.statusNode.alpha = 1.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
let adjustedProgress = max(progress, 0.027)
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true), completion: {})
case .Local:
if let previousStatus = previousStatus, case .Fetching = previousStatus {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true, animateRotation: true), completion: {
if let strongSelf = self {
strongSelf.statusNode.alpha = 0.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = false

View File

@ -201,10 +201,10 @@ class ChatExternalFileGalleryItemNode: GalleryItemNode {
strongSelf.statusNode.alpha = 1.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
let adjustedProgress = max(progress, 0.027)
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true), completion: {})
case .Local:
if let previousStatus = previousStatus, case .Fetching = previousStatus {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true, animateRotation: true), completion: {
if let strongSelf = self {
strongSelf.statusNode.alpha = 0.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = false

View File

@ -426,10 +426,10 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
strongSelf.statusNode.alpha = 1.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = true
let adjustedProgress = max(progress, 0.027)
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true), completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true), completion: {})
case .Local:
if let previousStatus = previousStatus, case .Fetching = previousStatus {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true), completion: {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: true, animateRotation: true), completion: {
if let strongSelf = self {
strongSelf.statusNode.alpha = 0.0
strongSelf.statusNodeContainer.isUserInteractionEnabled = false

View File

@ -723,7 +723,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
var fetching = false
if initialBuffering {
if displayProgress {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false), animated: false, completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false, animateRotation: true), animated: false, completion: {})
} else {
strongSelf.statusNode.transitionToState(.none, animated: false, completion: {})
}
@ -740,7 +740,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
fetching = true
isPaused = true
}
state = .progress(color: .white, lineWidth: nil, value: CGFloat(progress), cancelEnabled: true)
state = .progress(color: .white, lineWidth: nil, value: CGFloat(progress), cancelEnabled: true, animateRotation: true)
default:
break
}

View File

@ -176,7 +176,7 @@ final class InstantPageImageNode: ASDisplayNode, InstantPageNode {
switch fetchStatus {
case let .Fetching(_, progress):
let adjustedProgress = max(progress, 0.027)
state = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
state = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
case .Remote:
state = .download(.white)
default:

View File

@ -119,7 +119,7 @@ final class InstantPagePlayableVideoNode: ASDisplayNode, InstantPageNode, Galler
switch fetchStatus {
case let .Fetching(_, progress):
let adjustedProgress = max(progress, 0.027)
state = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
state = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
case .Remote:
state = .download(.white)
default:

View File

@ -28,7 +28,7 @@ private final class LegacyDataImportSplashImpl: WindowCoveringView, LegacyDataIm
self.updateLayout(size)
}
}
self.progressNode.transitionToState(.progress(color: self.theme?.list.itemAccentColor ?? UIColor(rgb: 0x007ee5), lineWidth: 2.0, value: CGFloat(max(0.025, self.progress.1)), cancelEnabled: false), animated: false, completion: {})
self.progressNode.transitionToState(.progress(color: self.theme?.list.itemAccentColor ?? UIColor(rgb: 0x007ee5), lineWidth: 2.0, value: CGFloat(max(0.025, self.progress.1)), cancelEnabled: false, animateRotation: true), animated: false, completion: {})
}
}

View File

@ -138,7 +138,7 @@ final class SecureIdValueFormFileItemNode: FormEditableBlockItemNode<SecureIdVal
let progressState: RadialStatusNodeState
if let progress = progress {
progressState = .progress(color: .white, lineWidth: nil, value: progress, cancelEnabled: false)
progressState = .progress(color: .white, lineWidth: nil, value: progress, cancelEnabled: false, animateRotation: true)
} else {
progressState = .none
}

View File

@ -99,9 +99,12 @@ private final class RadialProgressContentSpinnerNode: ASDisplayNode {
let lineWidth: CGFloat?
init(color: UIColor, lineWidth: CGFloat?) {
private let animateRotation: Bool
init(color: UIColor, lineWidth: CGFloat?, animateRotation: Bool) {
self.color = color
self.lineWidth = lineWidth
self.animateRotation = animateRotation
super.init()
@ -159,25 +162,29 @@ private final class RadialProgressContentSpinnerNode: ASDisplayNode {
override func willEnterHierarchy() {
super.willEnterHierarchy()
let basicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
basicAnimation.duration = 1.5
var fromValue = Float.pi + 0.58
if let presentation = self.layer.presentation(), let value = (presentation.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue {
fromValue = value
if self.animateRotation {
let basicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
basicAnimation.duration = 1.5
var fromValue = Float.pi + 0.58
if let presentation = self.layer.presentation(), let value = (presentation.value(forKeyPath: "transform.rotation.z") as? NSNumber)?.floatValue {
fromValue = value
}
basicAnimation.fromValue = NSNumber(value: fromValue)
basicAnimation.toValue = NSNumber(value: fromValue + Float.pi * 2.0)
basicAnimation.repeatCount = Float.infinity
basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
basicAnimation.beginTime = 0.0
self.layer.add(basicAnimation, forKey: "progressRotation")
}
basicAnimation.fromValue = NSNumber(value: fromValue)
basicAnimation.toValue = NSNumber(value: fromValue + Float.pi * 2.0)
basicAnimation.repeatCount = Float.infinity
basicAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
basicAnimation.beginTime = 0.0
self.layer.add(basicAnimation, forKey: "progressRotation")
}
override func didExitHierarchy() {
super.didExitHierarchy()
self.layer.removeAnimation(forKey: "progressRotation")
if self.animateRotation {
self.layer.removeAnimation(forKey: "progressRotation")
}
}
}
@ -258,13 +265,16 @@ final class RadialProgressContentNode: RadialStatusContentNode {
let displayCancel: Bool
var ready: Bool = false
let animateRotation: Bool
private var enqueuedReadyForTransition: (() -> Void)?
init(color: UIColor, lineWidth: CGFloat?, displayCancel: Bool) {
init(color: UIColor, lineWidth: CGFloat?, displayCancel: Bool, animateRotation: Bool) {
self.color = color
self.displayCancel = displayCancel
self.animateRotation = animateRotation
self.spinnerNode = RadialProgressContentSpinnerNode(color: color, lineWidth: lineWidth)
self.spinnerNode = RadialProgressContentSpinnerNode(color: color, lineWidth: lineWidth, animateRotation: animateRotation)
self.cancelNode = RadialProgressContentCancelNode(color: color, displayCancel: displayCancel)
super.init()

View File

@ -7,7 +7,7 @@ public enum RadialStatusNodeState: Equatable {
case download(UIColor)
case play(UIColor)
case pause(UIColor)
case progress(color: UIColor, lineWidth: CGFloat?, value: CGFloat?, cancelEnabled: Bool)
case progress(color: UIColor, lineWidth: CGFloat?, value: CGFloat?, cancelEnabled: Bool, animateRotation: Bool)
case cloudProgress(color: UIColor, strokeBackgroundColor: UIColor, lineWidth: CGFloat, value: CGFloat?)
case check(UIColor)
case customIcon(UIImage)
@ -39,8 +39,8 @@ public enum RadialStatusNodeState: Equatable {
} else {
return false
}
case let .progress(lhsColor, lhsLineWidth, lhsValue, lhsCancelEnabled):
if case let .progress(rhsColor, rhsLineWidth, rhsValue, rhsCancelEnabled) = rhs, lhsColor.isEqual(rhsColor), lhsValue == rhsValue, lhsLineWidth == rhsLineWidth, lhsCancelEnabled == rhsCancelEnabled {
case let .progress(lhsColor, lhsLineWidth, lhsValue, lhsCancelEnabled, lhsAnimateRotation):
if case let .progress(rhsColor, rhsLineWidth, rhsValue, rhsCancelEnabled, rhsAnimateRotation) = rhs, lhsColor.isEqual(rhsColor), lhsValue == rhsValue, lhsLineWidth == rhsLineWidth, lhsCancelEnabled == rhsCancelEnabled, lhsAnimateRotation == rhsAnimateRotation {
return true
} else {
return false
@ -98,8 +98,8 @@ public enum RadialStatusNodeState: Equatable {
} else {
return false
}
case let .progress(lhsColor, lhsLineWidth, lhsValue, lhsCancelEnabled):
if case let .progress(rhsColor, rhsLineWidth, rhsValue, rhsCancelEnabled) = rhs, lhsColor.isEqual(rhsColor), lhsValue == rhsValue, lhsLineWidth == rhsLineWidth, lhsCancelEnabled == rhsCancelEnabled {
case let .progress(lhsColor, lhsLineWidth, lhsValue, lhsCancelEnabled, lhsAnimateRotation):
if case let .progress(rhsColor, rhsLineWidth, rhsValue, rhsCancelEnabled, rhsAnimateRotation) = rhs, lhsColor.isEqual(rhsColor), lhsValue == rhsValue, lhsLineWidth == rhsLineWidth, lhsCancelEnabled == rhsCancelEnabled, lhsAnimateRotation == rhsAnimateRotation {
return true
} else {
return false
@ -154,15 +154,15 @@ public enum RadialStatusNodeState: Equatable {
return RadialStatusIconContentNode(icon: .custom(image), synchronous: synchronous)
case let .check(color):
return RadialCheckContentNode(color: color)
case let .progress(color, lineWidth, value, cancelEnabled):
if let current = current as? RadialProgressContentNode, current.displayCancel == cancelEnabled {
case let .progress(color, lineWidth, value, cancelEnabled, animateRotation):
if let current = current as? RadialProgressContentNode, current.displayCancel == cancelEnabled, current.animateRotation == animateRotation {
if !current.color.isEqual(color) {
current.color = color
}
current.progress = value
return current
} else {
let node = RadialProgressContentNode(color: color, lineWidth: lineWidth, displayCancel: cancelEnabled)
let node = RadialProgressContentNode(color: color, lineWidth: lineWidth, displayCancel: cancelEnabled, animateRotation: animateRotation)
node.progress = value
return node
}

View File

@ -501,12 +501,12 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
switch status {
case let .Fetching(_, progress):
let adjustedProgress = max(progress, 0.027)
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: false)
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: false, animateRotation: true)
case .Local:
state = .none
local = true
case .Remote:
state = .progress(color: statusForegroundColor, lineWidth: nil, value: 0.027, cancelEnabled: false)
state = .progress(color: statusForegroundColor, lineWidth: nil, value: 0.027, cancelEnabled: false, animateRotation: true)
}
strongSelf.statusNode.transitionToState(state, completion: {})

View File

@ -31,11 +31,11 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain
case let .progress(value):
self.activityIndicator.isHidden = true
self.statusNode.isHidden = false
self.statusNode.transitionToState(.progress(color: self.theme.actionSheet.controlAccentColor, lineWidth: 2.0, value: max(0.12, CGFloat(value)), cancelEnabled: false), completion: {})
self.statusNode.transitionToState(.progress(color: self.theme.actionSheet.controlAccentColor, lineWidth: 2.0, value: max(0.12, CGFloat(value)), cancelEnabled: false, animateRotation: true), completion: {})
case .done:
self.activityIndicator.isHidden = true
self.statusNode.isHidden = false
self.statusNode.transitionToState(.progress(color: self.theme.actionSheet.controlAccentColor, lineWidth: 2.0, value: 1.0, cancelEnabled: false), completion: {})
self.statusNode.transitionToState(.progress(color: self.theme.actionSheet.controlAccentColor, lineWidth: 2.0, value: 1.0, cancelEnabled: false, animateRotation: true), completion: {})
self.doneStatusNode.transitionToState(.check(self.theme.actionSheet.controlAccentColor), completion: {})
}
}
@ -52,7 +52,7 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain
self.addSubnode(self.activityIndicator)
self.addSubnode(self.statusNode)
self.addSubnode(self.doneStatusNode)
self.doneStatusNode.transitionToState(.progress(color: self.theme.actionSheet.controlAccentColor, lineWidth: 2.0, value: 0.0, cancelEnabled: false), completion: {})
self.doneStatusNode.transitionToState(.progress(color: self.theme.actionSheet.controlAccentColor, lineWidth: 2.0, value: 0.0, cancelEnabled: false, animateRotation: true), completion: {})
}
public func activate() {

View File

@ -11,8 +11,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[2055070967] = { return Api.ChatFull.parse_channelFull($0) }
dict[-213431562] = { return Api.ChatFull.parse_chatFull($0) }
dict[-281384243] = { return Api.ChatFull.parse_channelFull($0) }
dict[231260545] = { return Api.ChatFull.parse_chatFull($0) }
dict[-1159937629] = { return Api.PollResults.parse_pollResults($0) }
dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) }
dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) }
@ -150,7 +150,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1649296275] = { return Api.Peer.parse_peerUser($0) }
dict[-1160714821] = { return Api.Peer.parse_peerChat($0) }
dict[-1109531342] = { return Api.Peer.parse_peerChannel($0) }
dict[410107472] = { return Api.messages.ExportedChatInvite.parse_exportedChatInvite($0) }
dict[-1868808300] = { return Api.PaymentRequestedInfo.parse_paymentRequestedInfo($0) }
dict[164646985] = { return Api.UserStatus.parse_userStatusEmpty($0) }
dict[-306628279] = { return Api.UserStatus.parse_userStatusOnline($0) }
@ -350,7 +349,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1768777083] = { return Api.InputBotInlineMessage.parse_inputBotInlineMessageMediaGeo($0) }
dict[2002815875] = { return Api.KeyboardButtonRow.parse_keyboardButtonRow($0) }
dict[1088567208] = { return Api.StickerSet.parse_stickerSet($0) }
dict[-1111085620] = { return Api.messages.ExportedChatInvites.parse_exportedChatInvites($0) }
dict[354925740] = { return Api.SecureSecretSettings.parse_secureSecretSettings($0) }
dict[539045032] = { return Api.photos.Photo.parse_photo($0) }
dict[-208488460] = { return Api.InputContact.parse_inputPhoneContact($0) }
@ -407,7 +405,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
dict[1694474197] = { return Api.messages.Chats.parse_chats($0) }
dict[-1663561404] = { return Api.messages.Chats.parse_chatsSlice($0) }
dict[-2118733814] = { return Api.messages.ChatInviteImporters.parse_chatInviteImporters($0) }
dict[-659913713] = { return Api.InputGroupCall.parse_inputGroupCall($0) }
dict[482797855] = { return Api.InputSingleMedia.parse_inputSingleMedia($0) }
dict[1163625789] = { return Api.MessageViews.parse_messageViews($0) }
@ -549,7 +546,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1032140601] = { return Api.BotCommand.parse_botCommand($0) }
dict[1474462241] = { return Api.account.ContentSettings.parse_contentSettings($0) }
dict[-1661028051] = { return Api.phone.GroupParticipants.parse_groupParticipants($0) }
dict[507405952] = { return Api.ChatInviteImporter.parse_chatInviteImporter($0) }
dict[-2066640507] = { return Api.messages.AffectedMessages.parse_affectedMessages($0) }
dict[-402498398] = { return Api.messages.SavedGifs.parse_savedGifsNotModified($0) }
dict[772213157] = { return Api.messages.SavedGifs.parse_savedGifs($0) }
@ -740,7 +736,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1673717362] = { return Api.InputPeerNotifySettings.parse_inputPeerNotifySettings($0) }
dict[-1634752813] = { return Api.messages.FavedStickers.parse_favedStickersNotModified($0) }
dict[-209768682] = { return Api.messages.FavedStickers.parse_favedStickers($0) }
dict[1847917725] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[1776236393] = { return Api.ExportedChatInvite.parse_chatInviteEmpty($0) }
dict[-64092740] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[-1389486888] = { return Api.account.AuthorizationForm.parse_authorizationForm($0) }
dict[-1392388579] = { return Api.Authorization.parse_authorization($0) }
dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) }
@ -1039,8 +1036,6 @@ public struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.Peer:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.ExportedChatInvite:
_1.serialize(buffer, boxed)
case let _1 as Api.PaymentRequestedInfo:
_1.serialize(buffer, boxed)
case let _1 as Api.UserStatus:
@ -1113,8 +1108,6 @@ public struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.StickerSet:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.ExportedChatInvites:
_1.serialize(buffer, boxed)
case let _1 as Api.SecureSecretSettings:
_1.serialize(buffer, boxed)
case let _1 as Api.photos.Photo:
@ -1161,8 +1154,6 @@ public struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.messages.Chats:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.ChatInviteImporters:
_1.serialize(buffer, boxed)
case let _1 as Api.InputGroupCall:
_1.serialize(buffer, boxed)
case let _1 as Api.InputSingleMedia:
@ -1293,8 +1284,6 @@ public struct Api {
_1.serialize(buffer, boxed)
case let _1 as Api.phone.GroupParticipants:
_1.serialize(buffer, boxed)
case let _1 as Api.ChatInviteImporter:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.AffectedMessages:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.SavedGifs:

View File

@ -219,52 +219,6 @@ public struct messages {
}
}
}
public enum ExportedChatInvite: TypeConstructorDescription {
case exportedChatInvite(invite: Api.ExportedChatInvite, users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .exportedChatInvite(let invite, let users):
if boxed {
buffer.appendInt32(410107472)
}
invite.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .exportedChatInvite(let invite, let users):
return ("exportedChatInvite", [("invite", invite), ("users", users)])
}
}
public static func parse_exportedChatInvite(_ reader: BufferReader) -> ExportedChatInvite? {
var _1: Api.ExportedChatInvite?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
}
var _2: [Api.User]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.messages.ExportedChatInvite.exportedChatInvite(invite: _1!, users: _2!)
}
else {
return nil
}
}
}
public enum VotesList: TypeConstructorDescription {
case votesList(flags: Int32, count: Int32, votes: [Api.MessageUserVote], users: [Api.User], nextOffset: String?)
@ -483,60 +437,6 @@ public struct messages {
}
}
}
public enum ExportedChatInvites: TypeConstructorDescription {
case exportedChatInvites(count: Int32, invites: [Api.ExportedChatInvite], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .exportedChatInvites(let count, let invites, let users):
if boxed {
buffer.appendInt32(-1111085620)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(invites.count))
for item in invites {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .exportedChatInvites(let count, let invites, let users):
return ("exportedChatInvites", [("count", count), ("invites", invites), ("users", users)])
}
}
public static func parse_exportedChatInvites(_ reader: BufferReader) -> ExportedChatInvites? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.ExportedChatInvite]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ExportedChatInvite.self)
}
var _3: [Api.User]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.messages.ExportedChatInvites.exportedChatInvites(count: _1!, invites: _2!, users: _3!)
}
else {
return nil
}
}
}
public enum BotResults: TypeConstructorDescription {
case botResults(flags: Int32, queryId: Int64, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?, results: [Api.BotInlineResult], cacheTime: Int32, users: [Api.User])
@ -725,60 +625,6 @@ public struct messages {
}
}
}
public enum ChatInviteImporters: TypeConstructorDescription {
case chatInviteImporters(count: Int32, importers: [Api.ChatInviteImporter], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .chatInviteImporters(let count, let importers, let users):
if boxed {
buffer.appendInt32(-2118733814)
}
serializeInt32(count, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(importers.count))
for item in importers {
item.serialize(buffer, true)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(users.count))
for item in users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .chatInviteImporters(let count, let importers, let users):
return ("chatInviteImporters", [("count", count), ("importers", importers), ("users", users)])
}
}
public static func parse_chatInviteImporters(_ reader: BufferReader) -> ChatInviteImporters? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.ChatInviteImporter]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChatInviteImporter.self)
}
var _3: [Api.User]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.messages.ChatInviteImporters.chatInviteImporters(count: _1!, importers: _2!, users: _3!)
}
else {
return nil
}
}
}
public enum DhConfig: TypeConstructorDescription {
case dhConfigNotModified(random: Buffer)
@ -2278,14 +2124,14 @@ public extension Api {
}
public enum ChatFull: TypeConstructorDescription {
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?)
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?)
case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int32?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?)
case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?, call: Api.InputGroupCall?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let linkedChatId, let location, let slowmodeSeconds, let slowmodeNextSendDate, let statsDc, let pts, let call):
if boxed {
buffer.appendInt32(2055070967)
buffer.appendInt32(-281384243)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
@ -2300,7 +2146,7 @@ public extension Api {
serializeInt32(unreadCount, buffer: buffer, boxed: false)
chatPhoto.serialize(buffer, true)
notifySettings.serialize(buffer, true)
if Int(flags) & Int(1 << 23) != 0 {exportedInvite!.serialize(buffer, true)}
exportedInvite.serialize(buffer, true)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(botInfo.count))
for item in botInfo {
@ -2322,7 +2168,7 @@ public extension Api {
break
case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId, let call):
if boxed {
buffer.appendInt32(-213431562)
buffer.appendInt32(231260545)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(id, buffer: buffer, boxed: false)
@ -2330,7 +2176,7 @@ public extension Api {
participants.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {chatPhoto!.serialize(buffer, true)}
notifySettings.serialize(buffer, true)
if Int(flags) & Int(1 << 13) != 0 {exportedInvite!.serialize(buffer, true)}
exportedInvite.serialize(buffer, true)
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(botInfo!.count))
for item in botInfo! {
@ -2384,9 +2230,9 @@ public extension Api {
_13 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
}
var _14: Api.ExportedChatInvite?
if Int(_1!) & Int(1 << 23) != 0 {if let signature = reader.readInt32() {
if let signature = reader.readInt32() {
_14 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
} }
}
var _15: [Api.BotInfo]?
if let _ = reader.readInt32() {
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self)
@ -2436,7 +2282,7 @@ public extension Api {
let _c11 = _11 != nil
let _c12 = _12 != nil
let _c13 = _13 != nil
let _c14 = (Int(_1!) & Int(1 << 23) == 0) || _14 != nil
let _c14 = _14 != nil
let _c15 = _15 != nil
let _c16 = (Int(_1!) & Int(1 << 4) == 0) || _16 != nil
let _c17 = (Int(_1!) & Int(1 << 4) == 0) || _17 != nil
@ -2452,7 +2298,7 @@ public extension Api {
let _c27 = _27 != nil
let _c28 = (Int(_1!) & Int(1 << 21) == 0) || _28 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 {
return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!, call: _28)
return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, linkedChatId: _22, location: _23, slowmodeSeconds: _24, slowmodeNextSendDate: _25, statsDc: _26, pts: _27!, call: _28)
}
else {
return nil
@ -2478,9 +2324,9 @@ public extension Api {
_6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings
}
var _7: Api.ExportedChatInvite?
if Int(_1!) & Int(1 << 13) != 0 {if let signature = reader.readInt32() {
if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
} }
}
var _8: [Api.BotInfo]?
if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self)
@ -2499,13 +2345,13 @@ public extension Api {
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
let _c6 = _6 != nil
let _c7 = (Int(_1!) & Int(1 << 13) == 0) || _7 != nil
let _c7 = _7 != nil
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil
let _c11 = (Int(_1!) & Int(1 << 12) == 0) || _11 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11)
return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7!, botInfo: _8, pinnedMsgId: _9, folderId: _10, call: _11)
}
else {
return nil
@ -16122,44 +15968,6 @@ public extension Api {
}
}
}
public enum ChatInviteImporter: TypeConstructorDescription {
case chatInviteImporter(userId: Int32, date: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .chatInviteImporter(let userId, let date):
if boxed {
buffer.appendInt32(507405952)
}
serializeInt32(userId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .chatInviteImporter(let userId, let date):
return ("chatInviteImporter", [("userId", userId), ("date", date)])
}
}
public static func parse_chatInviteImporter(_ reader: BufferReader) -> ChatInviteImporter? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.ChatInviteImporter.chatInviteImporter(userId: _1!, date: _2!)
}
else {
return nil
}
}
}
public enum CdnPublicKey: TypeConstructorDescription {
case cdnPublicKey(dcId: Int32, publicKey: String)
@ -21078,60 +20886,44 @@ public extension Api {
}
public enum ExportedChatInvite: TypeConstructorDescription {
case chatInviteExported(flags: Int32, link: String, adminId: Int32, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?)
case chatInviteEmpty
case chatInviteExported(link: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage):
case .chatInviteEmpty:
if boxed {
buffer.appendInt32(1847917725)
buffer.appendInt32(1776236393)
}
break
case .chatInviteExported(let link):
if boxed {
buffer.appendInt32(-64092740)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false)
serializeInt32(adminId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 4) != 0 {serializeInt32(startDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage):
return ("chatInviteExported", [("flags", flags), ("link", link), ("adminId", adminId), ("date", date), ("startDate", startDate), ("expireDate", expireDate), ("usageLimit", usageLimit), ("usage", usage)])
case .chatInviteEmpty:
return ("chatInviteEmpty", [])
case .chatInviteExported(let link):
return ("chatInviteExported", [("link", link)])
}
}
public static func parse_chatInviteEmpty(_ reader: BufferReader) -> ExportedChatInvite? {
return Api.ExportedChatInvite.chatInviteEmpty
}
public static func parse_chatInviteExported(_ reader: BufferReader) -> ExportedChatInvite? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
if Int(_1!) & Int(1 << 4) != 0 {_5 = reader.readInt32() }
var _6: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_6 = reader.readInt32() }
var _7: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_7 = reader.readInt32() }
var _8: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_8 = reader.readInt32() }
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8)
if _c1 {
return Api.ExportedChatInvite.chatInviteExported(link: _1!)
}
else {
return nil

View File

@ -3190,6 +3190,20 @@ public extension Api {
})
}
public static func exportChatInvite(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
let buffer = Buffer()
buffer.appendInt32(234312524)
peer.serialize(buffer, true)
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("peer", peer)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
let reader = BufferReader(buffer)
var result: Api.ExportedChatInvite?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
}
return result
})
}
public static func getEmojiKeywords(langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.EmojiKeywordsDifference>) {
let buffer = Buffer()
buffer.appendInt32(899735650)
@ -3874,123 +3888,6 @@ public extension Api {
})
}
public static func deleteChatUser(flags: Int32, chatId: Int32, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(-986430054)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(chatId, buffer: buffer, boxed: false)
userId.serialize(buffer, true)
return (FunctionDescription(name: "messages.deleteChatUser", parameters: [("flags", flags), ("chatId", chatId), ("userId", userId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
public static func getExportedChatInvites(flags: Int32, peer: Api.InputPeer, adminId: Api.InputUser?, offsetDate: Int32?, offsetLink: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ExportedChatInvites>) {
let buffer = Buffer()
buffer.appendInt32(1785900140)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {adminId!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(offsetDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeString(offsetLink!, buffer: buffer, boxed: false)}
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.getExportedChatInvites", parameters: [("flags", flags), ("peer", peer), ("adminId", adminId), ("offsetDate", offsetDate), ("offsetLink", offsetLink), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvites? in
let reader = BufferReader(buffer)
var result: Api.messages.ExportedChatInvites?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvites
}
return result
})
}
public static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
let buffer = Buffer()
buffer.appendInt32(347716823)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", flags), ("peer", peer), ("expireDate", expireDate), ("usageLimit", usageLimit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
let reader = BufferReader(buffer)
var result: Api.ExportedChatInvite?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
}
return result
})
}
public static func editExportedChatInvite(flags: Int32, peer: Api.InputPeer, link: String, expireDate: Int32?, usageLimit: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ExportedChatInvite>) {
let buffer = Buffer()
buffer.appendInt32(48562110)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(link, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "messages.editExportedChatInvite", parameters: [("flags", flags), ("peer", peer), ("link", link), ("expireDate", expireDate), ("usageLimit", usageLimit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ExportedChatInvite? in
let reader = BufferReader(buffer)
var result: Api.messages.ExportedChatInvite?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.ExportedChatInvite
}
return result
})
}
public static func deleteRevokedExportedChatInvites(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(1375999075)
peer.serialize(buffer, true)
return (FunctionDescription(name: "messages.deleteRevokedExportedChatInvites", parameters: [("peer", peer)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
public static func deleteExportedChatInvite(peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-731601877)
peer.serialize(buffer, true)
serializeString(link, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.deleteExportedChatInvite", parameters: [("peer", peer), ("link", link)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
public static func getChatInviteImporters(peer: Api.InputPeer, link: String, offsetDate: Int32, offsetUser: Api.InputUser, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.ChatInviteImporters>) {
let buffer = Buffer()
buffer.appendInt32(654013065)
peer.serialize(buffer, true)
serializeString(link, buffer: buffer, boxed: false)
serializeInt32(offsetDate, buffer: buffer, boxed: false)
offsetUser.serialize(buffer, true)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.getChatInviteImporters", parameters: [("peer", peer), ("link", link), ("offsetDate", offsetDate), ("offsetUser", offsetUser), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.ChatInviteImporters? in
let reader = BufferReader(buffer)
var result: Api.messages.ChatInviteImporters?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.ChatInviteImporters
}
return result
})
}
public static func discardEncryption(flags: Int32, chatId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-208425312)
@ -4034,6 +3931,20 @@ public extension Api {
})
}
public static func checkHistoryImport(importHead: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.HistoryImportParsed>) {
let buffer = Buffer()
buffer.appendInt32(1140726259)
serializeString(importHead, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.checkHistoryImport", parameters: [("importHead", importHead)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HistoryImportParsed? in
let reader = BufferReader(buffer)
var result: Api.messages.HistoryImportParsed?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.HistoryImportParsed
}
return result
})
}
public static func initHistoryImport(peer: Api.InputPeer, file: Api.InputFile, mediaCount: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.HistoryImport>) {
let buffer = Buffer()
buffer.appendInt32(873008187)
@ -4082,15 +3993,17 @@ public extension Api {
})
}
public static func checkHistoryImport(importHead: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.HistoryImportParsed>) {
public static func deleteChatUser(flags: Int32, chatId: Int32, userId: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(1140726259)
serializeString(importHead, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.checkHistoryImport", parameters: [("importHead", importHead)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.HistoryImportParsed? in
buffer.appendInt32(-986430054)
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(chatId, buffer: buffer, boxed: false)
userId.serialize(buffer, true)
return (FunctionDescription(name: "messages.deleteChatUser", parameters: [("flags", flags), ("chatId", chatId), ("userId", userId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.messages.HistoryImportParsed?
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.messages.HistoryImportParsed
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})

View File

@ -1421,7 +1421,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
pollChannelSignals = []
} else if shouldResetChannels {
var channelPeers: [Peer] = []
for peerId in channelsToPoll {
for peerId in channelsToPoll.union(missingUpdatesFromChannels) {
if let peer = updatedState.peers[peerId] {
channelPeers.append(peer)
} else {

View File

@ -7,8 +7,12 @@ import SyncCore
extension ExportedInvitation {
init?(apiExportedInvite: Api.ExportedChatInvite) {
switch apiExportedInvite {
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage):
self = ExportedInvitation(link: link, isPermanent: (flags & (1 << 5)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage)
case .chatInviteEmpty:
return nil
case let .chatInviteExported(link):
self = ExportedInvitation(link: link, isPermanent: true, isRevoked: false, adminId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), date: 0, startDate: nil, expireDate: nil, usageLimit: nil, count: nil)
/*case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage):
self = ExportedInvitation(link: link, isPermanent: (flags & (1 << 5)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: adminId), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage)*/
}
}
}

View File

@ -11,7 +11,7 @@ public func revokePersistentPeerExportedInvitation(account: Account, peerId: Pee
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
let flags: Int32 = (1 << 2)
if let _ = peer as? TelegramChannel {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
return account.network.request(Api.functions.messages.exportChatInvite(peer: inputPeer))
|> retryRequest
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
return account.postbox.transaction { transaction -> ExportedInvitation? in
@ -30,7 +30,7 @@ public func revokePersistentPeerExportedInvitation(account: Account, peerId: Pee
}
}
} else if let _ = peer as? TelegramGroup {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil))
return account.network.request(Api.functions.messages.exportChatInvite(peer: inputPeer))
|> retryRequest
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
return account.postbox.transaction { transaction -> ExportedInvitation? in
@ -62,7 +62,8 @@ public enum CreatePeerExportedInvitationError {
}
public func createPeerExportedInvitation(account: Account, peerId: PeerId, expireDate: Int32?, usageLimit: Int32?) -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> {
return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> in
return .fail(.generic)
/*return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, CreatePeerExportedInvitationError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 0
if let _ = expireDate {
@ -85,7 +86,7 @@ public func createPeerExportedInvitation(account: Account, peerId: PeerId, expir
}
}
|> castError(CreatePeerExportedInvitationError.self)
|> switchToLatest
|> switchToLatest*/
}
public enum EditPeerExportedInvitationError {
@ -93,7 +94,8 @@ public enum EditPeerExportedInvitationError {
}
public func editPeerExportedInvitation(account: Account, peerId: PeerId, link: String, expireDate: Int32?, usageLimit: Int32?) -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> {
return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> in
return .fail(.generic)
/*return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, EditPeerExportedInvitationError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 0
if let _ = expireDate {
@ -126,7 +128,7 @@ public func editPeerExportedInvitation(account: Account, peerId: PeerId, link: S
}
}
|> castError(EditPeerExportedInvitationError.self)
|> switchToLatest
|> switchToLatest*/
}
public enum RevokePeerExportedInvitationError {
@ -134,7 +136,8 @@ public enum RevokePeerExportedInvitationError {
}
public func revokePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal<ExportedInvitation?, RevokePeerExportedInvitationError> {
return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, RevokePeerExportedInvitationError> in
return .fail(.generic)
/*return account.postbox.transaction { transaction -> Signal<ExportedInvitation?, RevokePeerExportedInvitationError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
let flags: Int32 = (1 << 2)
return account.network.request(Api.functions.messages.editExportedChatInvite(flags: flags, peer: inputPeer, link: link, expireDate: nil, usageLimit: nil))
@ -161,7 +164,7 @@ public func revokePeerExportedInvitation(account: Account, peerId: PeerId, link:
}
}
|> castError(RevokePeerExportedInvitationError.self)
|> switchToLatest
|> switchToLatest*/
}
public struct ExportedInvitations : Equatable {
@ -170,7 +173,8 @@ public struct ExportedInvitations : Equatable {
}
public func peerExportedInvitations(account: Account, peerId: PeerId, revoked: Bool, offsetLink: ExportedInvitation? = nil) -> Signal<ExportedInvitations?, NoError> {
return account.postbox.transaction { transaction -> Signal<ExportedInvitations?, NoError> in
return .single(nil)
/*return account.postbox.transaction { transaction -> Signal<ExportedInvitations?, NoError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 0
if let _ = offsetLink {
@ -213,7 +217,7 @@ public func peerExportedInvitations(account: Account, peerId: PeerId, revoked: B
} else {
return .single(nil)
}
} |> switchToLatest
} |> switchToLatest*/
}
@ -222,7 +226,8 @@ public enum DeletePeerExportedInvitationError {
}
public func deletePeerExportedInvitation(account: Account, peerId: PeerId, link: String) -> Signal<Never, DeletePeerExportedInvitationError> {
return account.postbox.transaction { transaction -> Signal<Never, DeletePeerExportedInvitationError> in
return .fail(.generic)
/*return account.postbox.transaction { transaction -> Signal<Never, DeletePeerExportedInvitationError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
return account.network.request(Api.functions.messages.deleteExportedChatInvite(peer: inputPeer, link: link))
|> mapError { _ in return DeletePeerExportedInvitationError.generic }
@ -232,11 +237,12 @@ public func deletePeerExportedInvitation(account: Account, peerId: PeerId, link:
}
}
|> castError(DeletePeerExportedInvitationError.self)
|> switchToLatest
|> switchToLatest*/
}
public func deleteAllRevokedPeerExportedInvitations(account: Account, peerId: PeerId) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Signal<Never, NoError> in
return .complete()
/*return account.postbox.transaction { transaction -> Signal<Never, NoError> in
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
return account.network.request(Api.functions.messages.deleteRevokedExportedChatInvites(peer: inputPeer))
|> `catch` { _ -> Signal<Api.Bool, NoError> in
@ -247,7 +253,7 @@ public func deleteAllRevokedPeerExportedInvitations(account: Account, peerId: Pe
return .complete()
}
}
|> switchToLatest
|> switchToLatest*/
}
private let cachedPeerExportedInvitationsCollectionSpec = ItemCacheCollectionSpec(lowWaterItemCount: 10, highWaterItemCount: 20)
@ -367,7 +373,7 @@ private final class PeerExportedInvitationsContextImpl {
}
func loadMore() {
if self.isLoadingMore {
/*if self.isLoadingMore {
return
}
self.isLoadingMore = true
@ -461,7 +467,7 @@ private final class PeerExportedInvitationsContextImpl {
strongSelf.loadMore()
}
}))
self.updateState()
self.updateState()*/
}
public func add(_ invite: ExportedInvitation) {
@ -717,7 +723,7 @@ private final class PeerInvitationImportersContextImpl {
if self.isLoadingMore {
return
}
self.isLoadingMore = true
/*self.isLoadingMore = true
let account = self.account
let peerId = self.peerId
let link = self.link
@ -805,7 +811,7 @@ private final class PeerInvitationImportersContextImpl {
}
strongSelf.updateState()
}))
self.updateState()
self.updateState()*/
}
private func updateState() {

View File

@ -254,7 +254,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
let photo: TelegramMediaImage? = chatFull.chatPhoto.flatMap(telegramMediaImageFromApiPhoto)
let exportedInvitation = chatFull.exportedInvite.flatMap { ExportedInvitation(apiExportedInvite: $0) }
let exportedInvitation = Optional(chatFull.exportedInvite).flatMap { ExportedInvitation(apiExportedInvite: $0) }
let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) })
var peers: [Peer] = []
@ -510,7 +510,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI
return previous.withUpdatedFlags(channelFlags)
.withUpdatedAbout(about)
.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: bannedCount, kickedCount: kickedCount))
.withUpdatedExportedInvitation(apiExportedInvite.flatMap { ExportedInvitation(apiExportedInvite: $0) })
.withUpdatedExportedInvitation(Optional(apiExportedInvite).flatMap { ExportedInvitation(apiExportedInvite: $0) })
.withUpdatedBotInfos(botInfos)
.withUpdatedPinnedMessageId(pinnedMessageId)
.withUpdatedStickerPack(stickerPack)

View File

@ -217,6 +217,7 @@ swift_library(
"//submodules/ChatImportUI:ChatImportUI",
"//submodules/ChatHistoryImportTasks:ChatHistoryImportTasks",
"//submodules/DatePickerNode:DatePickerNode",
"//submodules/ConfettiEffect:ConfettiEffect",
],
visibility = [
"//visibility:public",

View File

@ -15,6 +15,7 @@ import ReactionSelectionNode
import TelegramUniversalVideoContent
import ChatInterfaceState
import FastBlur
import ConfettiEffect
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
let itemNode: OverlayMediaItemNode

View File

@ -335,7 +335,7 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
transition.updateFrameAdditive(node: statusNode, frame: statusFrame)
}
statusNode.transitionToState(.progress(color: messageTheme.accentTextColor, lineWidth: 1.5, value: nil, cancelEnabled: false), animated: false, synchronous: false, completion: {})
statusNode.transitionToState(.progress(color: messageTheme.accentTextColor, lineWidth: 1.5, value: nil, cancelEnabled: false, animateRotation: true), animated: false, synchronous: false, completion: {})
} else {
strongSelf.arrowNode.isHidden = false
if let statusNode = strongSelf.statusNode {

View File

@ -593,13 +593,13 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
case let .Fetching(_, progress):
if let isBuffering = isBuffering {
if isBuffering {
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: nil, cancelEnabled: true)
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: nil, cancelEnabled: true, animateRotation: true)
} else {
state = .none
}
} else {
let adjustedProgress = max(progress, 0.027)
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
}
case .Local:
if isSecretMedia && self.secretProgressIcon != nil {
@ -620,7 +620,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
isLocal = true
}
if (isBuffering ?? false) && !isLocal {
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: nil, cancelEnabled: true)
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: nil, cancelEnabled: true, animateRotation: true)
} else {
state = .none
}

View File

@ -1036,7 +1036,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
}
var animated: Bool = animated
if let updatingMedia = attributes.updatingMedia, case .update = updatingMedia.media {
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(updatingMedia.progress), cancelEnabled: true)
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(updatingMedia.progress), cancelEnabled: true, animateRotation: true)
} else if var fetchStatus = self.fetchStatus {
var playerPosition: Int32?
var playerDuration: Int32 = 0
@ -1087,7 +1087,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
if adjustedProgress.isEqual(to: 1.0), case .unconstrained = sizeCalculation, (message.flags.contains(.Unsent) || wasCheck) {
state = .check(messageTheme.mediaOverlayControlColors.foregroundColor)
} else {
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
state = .progress(color: messageTheme.mediaOverlayControlColors.foregroundColor, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
}
if let file = self.media as? TelegramMediaFile {

View File

@ -216,7 +216,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
transition.updateSublayerTransformScale(node: strongSelf.buttonsContainer, scale: 0.1)
if let theme = strongSelf.theme {
strongSelf.activityIndicator.transitionToState(.progress(color: theme.chat.inputPanel.panelControlAccentColor, lineWidth: nil, value: nil, cancelEnabled: false), animated: false, completion: {
strongSelf.activityIndicator.transitionToState(.progress(color: theme.chat.inputPanel.panelControlAccentColor, lineWidth: nil, value: nil, cancelEnabled: false, animateRotation: true), animated: false, completion: {
})
}
}

View File

@ -50,7 +50,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode {
strongSelf.statusNode.transitionToState(.none, completion: {})
} else {
strongSelf.activityIndicator.isHidden = true
strongSelf.statusNode.transitionToState(.progress(color: strongSelf.theme.chat.inputPanel.panelControlAccentColor, lineWidth: nil, value: CGFloat(value), cancelEnabled: false), completion: {})
strongSelf.statusNode.transitionToState(.progress(color: strongSelf.theme.chat.inputPanel.panelControlAccentColor, lineWidth: nil, value: CGFloat(value), cancelEnabled: false, animateRotation: true), completion: {})
}
} else {
strongSelf.activityIndicator.isHidden = true

View File

@ -248,7 +248,7 @@ final class GridMessageItemNode: GridItemNode {
switch status {
case let .Fetching(_, progress):
let adjustedProgress = max(progress, 0.027)
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
case .Local:
statusState = .none
case .Remote:

View File

@ -460,7 +460,7 @@ final class HorizontalListContextResultsChatInputPanelItemNode: ListViewItemNode
switch status {
case let .Fetching(_, progress):
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(max(progress, 0.2)), cancelEnabled: false)
state = .progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(max(progress, 0.2)), cancelEnabled: false, animateRotation: true)
case .Remote:
//state = .download(statusForegroundColor)
state = .none

View File

@ -345,7 +345,7 @@ private final class VisualMediaItemNode: ASDisplayNode {
switch status {
case let .Fetching(_, progress):
let adjustedProgress = max(progress, 0.027)
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true)
statusState = .progress(color: .white, lineWidth: nil, value: CGFloat(adjustedProgress), cancelEnabled: true, animateRotation: true)
case .Local:
statusState = .none
case .Remote:

View File

@ -287,10 +287,10 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
}
if isLoading, let progress = progress {
strongSelf.hasProgress = true
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(max(0.027, progress)), cancelEnabled: false), completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: CGFloat(max(0.027, progress)), cancelEnabled: false, animateRotation: true), completion: {})
} else if strongSelf.hasProgress {
strongSelf.hasProgress = false
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: false), completion: { [weak self] in
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: 1.0, cancelEnabled: false, animateRotation: true), completion: { [weak self] in
guard let strongSelf = self else {
return
}
@ -1517,7 +1517,7 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode {
if let updatingAvatar = updatingAvatar {
overlayHidden = false
self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: max(0.027, uploadProgress ?? 0.0), cancelEnabled: true))
self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: max(0.027, uploadProgress ?? 0.0), cancelEnabled: true, animateRotation: true))
if case let .image(representation) = updatingAvatar {
if representation != self.currentRepresentation {

View File

@ -22,6 +22,7 @@ import OverlayStatusController
import PresentationDataUtils
import ChatImportUI
import ZIPFoundation
import ActivityIndicator
private let inForeground = ValuePromise<Bool>(false, ignoreRepeated: true)
@ -462,10 +463,10 @@ public class ShareRootControllerImpl {
if let mainFile = mainFile, let mainFileText = try? String(contentsOf: URL(fileURLWithPath: mainFile.path)) {
let mainFileHeader: String
if mainFileText.count < 1000 {
if mainFileText.count < 2000 {
mainFileHeader = mainFileText
} else {
mainFileHeader = String(mainFileText[mainFileText.startIndex ..< mainFileText.index(mainFileText.startIndex, offsetBy: 1000)])
mainFileHeader = String(mainFileText[mainFileText.startIndex ..< mainFileText.index(mainFileText.startIndex, offsetBy: 2000)])
}
final class TempController: ViewController {
@ -476,11 +477,16 @@ public class ShareRootControllerImpl {
}
}
private let activityIndicator: ActivityIndicator
init(context: AccountContext) {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.activityIndicator = ActivityIndicator(type: .custom(presentationData.theme.list.itemAccentColor, 22.0, 1.0, false))
super.init(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData))
//TODO:localize
self.title = "Import Chat"
self.navigationItem.setLeftBarButton(UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed)), animated: false)
}
@ -492,6 +498,19 @@ public class ShareRootControllerImpl {
@objc private func cancelPressed() {
//self?.getExtensionContext()?.completeRequest(returningItems: nil, completionHandler: nil)
}
override func displayNodeDidLoad() {
super.displayNodeDidLoad()
self.displayNode.addSubnode(self.activityIndicator)
}
override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
let indicatorSize = self.activityIndicator.measure(CGSize(width: 100.0, height: 100.0))
transition.updateFrame(node: self.activityIndicator, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - indicatorSize.width) / 2.0), y: floor((layout.size.height - indicatorSize.height - 50.0) / 2.0)), size: indicatorSize))
}
}
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
@ -533,7 +552,7 @@ public class ShareRootControllerImpl {
attemptSelectionImpl = { peer in
var errorText: String?
if let channel = peer as? TelegramChannel {
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
if channel.hasPermission(.changeInfo) {
} else {
errorText = "You need to be an admin of the group to import messages into it."
}
@ -620,10 +639,8 @@ public class ShareRootControllerImpl {
}
navigationController.viewControllers = [controller]
strongSelf.mainWindow?.present(navigationController, on: .root)
case let .privateChat(title):
let presentationData = internalContext.sharedContext.currentPresentationData.with { $0 }
let navigationController = NavigationController(mode: .single, theme: NavigationControllerTheme(presentationTheme: presentationData.theme))
//TODO:localize
var attemptSelectionImpl: ((Peer) -> Void)?
@ -684,7 +701,6 @@ public class ShareRootControllerImpl {
}
navigationController.viewControllers = [controller]
strongSelf.mainWindow?.present(navigationController, on: .root)
case let .unknown(peerTitle):
//TODO:localize
var attemptSelectionImpl: ((Peer) -> Void)?
@ -736,7 +752,7 @@ public class ShareRootControllerImpl {
var errorText: String?
if let channel = peer as? TelegramChannel {
if channel.flags.contains(.isCreator) || channel.adminRights != nil {
if channel.hasPermission(.changeInfo) {
} else {
errorText = "You need to be an admin of the group to import messages into it."
}
@ -839,7 +855,6 @@ public class ShareRootControllerImpl {
}
navigationController.viewControllers = [controller]
strongSelf.mainWindow?.present(navigationController, on: .root)
}
}, error: { _ in
beginShare()

View File

@ -364,7 +364,7 @@ final class VerticalListContextResultsChatInputPanelItemNode: ListViewItemNode {
switch status {
case let .Fetching(_, progress):
state = RadialStatusNodeState.progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(max(progress, 0.2)), cancelEnabled: false)
state = RadialStatusNodeState.progress(color: statusForegroundColor, lineWidth: nil, value: CGFloat(max(progress, 0.2)), cancelEnabled: false, animateRotation: true)
case .Remote:
state = .download(statusForegroundColor)
case .Local:

View File

@ -188,7 +188,7 @@ final class OverlayVideoDecoration: UniversalVideoDecoration {
return
}
if let status = status, case .buffering = status.status {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false))
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false, animateRotation: true))
} else {
strongSelf.statusNode.transitionToState(.none)
}

View File

@ -227,7 +227,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode {
var fetching = false
if initialBuffering {
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false), animated: false, completion: {})
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false, animateRotation: true), animated: false, completion: {})
} else {
var state: RadialStatusNodeState = .none
@ -237,7 +237,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode {
case let .Fetching(_, progress):
fetching = true
isPaused = true
state = .progress(color: .white, lineWidth: nil, value: CGFloat(max(0.027, progress)), cancelEnabled: false)
state = .progress(color: .white, lineWidth: nil, value: CGFloat(max(0.027, progress)), cancelEnabled: false, animateRotation: true)
default:
break
}