Add "Choosing sticker" input activity

This commit is contained in:
Ilya Laktyushin 2021-08-18 00:47:36 +04:00
parent ce97e49ed7
commit 74c2145b21
6 changed files with 165 additions and 0 deletions

View File

@ -59,6 +59,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
text = strings.Activity_PlayingGame
case .typingText:
text = strings.DialogList_Typing
case .choosingSticker:
text = strings.Activity_ChoosingSticker
case .speakingInGroupCall:
text = ""
}
@ -77,6 +79,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
state = .playingGame(string, lightColor)
case .speakingInGroupCall:
state = .typingText(string, lightColor)
case .choosingSticker:
state = .choosingSticker(string, lightColor)
}
} else {
let text: String
@ -99,6 +103,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
text = strings.DialogList_SinglePlayingGameSuffix(peerTitle).string
case .typingText:
text = strings.DialogList_SingleTypingSuffix(peerTitle).string
case .choosingSticker:
text = ""
case .speakingInGroupCall:
text = ""
}
@ -120,6 +126,8 @@ final class ChatListInputActivitiesNode: ASDisplayNode {
state = .playingGame(string, lightColor)
case .speakingInGroupCall:
state = .typingText(string, lightColor)
case .choosingSticker:
state = .none
}
}
} else {

View File

@ -0,0 +1,145 @@
import Foundation
import UIKit
import Display
import AsyncDisplayKit
import LegacyComponents
private func interpolate(from: CGFloat, to: CGFloat, value: CGFloat) -> CGFloat {
return (1.0 - value) * from + value * to
}
private final class ChatChoosingStickerActivityIndicatorNodeParameters: NSObject {
let color: UIColor
let progress: CGFloat
init(color: UIColor, progress: CGFloat) {
self.color = color
self.progress = progress
}
}
private class ChatChoosingStickerActivityIndicatorNode: ChatTitleActivityIndicatorNode {
override var duration: CFTimeInterval {
return 2.0
}
override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
if let color = self.color {
return ChatChoosingStickerActivityIndicatorNodeParameters(color: color, progress: self.progress)
} else {
return nil
}
}
@objc override 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? ChatChoosingStickerActivityIndicatorNodeParameters else {
return
}
context.setFillColor(UIColor.red.cgColor)
// context.fill(bounds)
let color = parameters.color
context.setFillColor(color.cgColor)
context.setStrokeColor(color.cgColor)
var heightProgress: CGFloat = parameters.progress * 4.0
if heightProgress > 3.0 {
heightProgress = 4.0 - heightProgress
} else if heightProgress > 2.0 {
heightProgress = heightProgress - 2.0
heightProgress *= heightProgress
} else if heightProgress > 1.0 {
heightProgress = 2.0 - heightProgress
} else {
heightProgress *= heightProgress
}
var pupilProgress: CGFloat = parameters.progress * 4.0
if pupilProgress > 2.0 {
pupilProgress = 3.0 - pupilProgress
}
pupilProgress = min(1.0, max(0.0, pupilProgress))
pupilProgress *= pupilProgress
var positionProgress: CGFloat = parameters.progress * 2.0
if positionProgress > 1.0 {
positionProgress = 2.0 - positionProgress
}
let eyeWidth: CGFloat = 6.0
let eyeHeight: CGFloat = 11.0 - 2.0 * heightProgress
let eyeOffset: CGFloat = -1.0 + positionProgress * 2.0
let leftCenter = CGPoint(x: bounds.width / 2.0 - eyeWidth - 1.0 + eyeOffset, y: bounds.height / 2.0)
let rightCenter = CGPoint(x: bounds.width / 2.0 + 1.0 + eyeOffset, y: bounds.height / 2.0)
let pupilSize: CGFloat = 4.0
let pupilCenter = CGPoint(x: -1.0 + pupilProgress * 2.0, y: 0.0)
context.strokeEllipse(in: CGRect(x: leftCenter.x - eyeWidth / 2.0, y: leftCenter.y - eyeHeight / 2.0, width: eyeWidth, height: eyeHeight))
context.fillEllipse(in: CGRect(x: leftCenter.x - pupilSize / 2.0 + pupilCenter.x * eyeWidth / 4.0, y: leftCenter.y - pupilSize / 2.0, width: pupilSize, height: pupilSize))
context.strokeEllipse(in: CGRect(x: rightCenter.x - eyeWidth / 2.0, y: rightCenter.y - eyeHeight / 2.0, width: eyeWidth, height: eyeHeight))
context.fillEllipse(in: CGRect(x: rightCenter.x - pupilSize / 2.0 + pupilCenter.x * eyeWidth / 4.0, y: rightCenter.y - pupilSize / 2.0, width: pupilSize, height: pupilSize))
// context.strokeEllipse(in: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 20.0))
// context.fillEllipse(in: CGRect(x: , y: , width: 4.0, height: 4.0))
}
}
class ChatChoosingStickerActivityContentNode: ChatTitleActivityContentNode {
private let indicatorNode: ChatChoosingStickerActivityIndicatorNode
private let advanced: Bool
init(text: NSAttributedString, color: UIColor) {
self.indicatorNode = ChatChoosingStickerActivityIndicatorNode(color: color)
var text = text
self.advanced = text.string == "choosing sticker"
if self.advanced {
let mutable = text.mutableCopy() as? NSMutableAttributedString
mutable?.replaceCharacters(in: NSMakeRange(2, 2), with: " ")
if let updated = mutable{
text = updated
}
}
super.init(text: text)
self.addSubnode(self.indicatorNode)
}
override func updateLayout(_ constrainedSize: CGSize, offset: CGFloat, alignment: NSTextAlignment) -> CGSize {
let size = self.textNode.updateLayout(constrainedSize)
let indicatorSize = CGSize(width: 24.0, height: 16.0)
let originX: CGFloat
let indicatorOriginX: CGFloat
if case .center = alignment {
if self.advanced {
originX = floorToScreenPixels((-size.width) / 2.0)
} else {
originX = floorToScreenPixels((indicatorSize.width - size.width) / 2.0)
}
} else {
originX = indicatorSize.width
}
self.textNode.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: size)
if self.advanced {
indicatorOriginX = self.textNode.frame.minX + 14.0 + UIScreenPixel
} else {
indicatorOriginX = self.textNode.frame.minX - indicatorSize.width
}
self.indicatorNode.frame = CGRect(origin: CGPoint(x: indicatorOriginX, y: 0.0), size: indicatorSize)
return CGSize(width: size.width + indicatorSize.width, height: size.height)
}
}

View File

@ -23,6 +23,7 @@ public enum ChatTitleActivityNodeState: Equatable {
case recordingVoice(NSAttributedString, UIColor)
case recordingVideo(NSAttributedString, UIColor)
case playingGame(NSAttributedString, UIColor)
case choosingSticker(NSAttributedString, UIColor)
func contentNode() -> ChatTitleActivityContentNode? {
switch self {
@ -40,6 +41,8 @@ public enum ChatTitleActivityNodeState: Equatable {
return ChatRecordingVideoActivityContentNode(text: text, color: color)
case let .playingGame(text, color):
return ChatPlayingActivityContentNode(text: text, color: color)
case let .choosingSticker(text, color):
return ChatChoosingStickerActivityContentNode(text: text, color: color)
}
}

View File

@ -129,6 +129,8 @@ private func actionFromActivity(_ activity: PeerInputActivity?) -> Api.SendMessa
return .sendMessageUploadRoundAction(progress: progress)
case .speakingInGroupCall:
return .speakingInGroupCallAction
case .choosingSticker:
return .sendMessageGamePlayAction
}
} else {
return .sendMessageCancelAction

View File

@ -11,6 +11,7 @@ public enum PeerInputActivity: Comparable {
case recordingInstantVideo
case uploadingInstantVideo(progress: Int32)
case speakingInGroupCall(timestamp: Int32)
case choosingSticker
public var key: Int32 {
switch self {
@ -32,6 +33,8 @@ public enum PeerInputActivity: Comparable {
return 7
case .playingGame:
return 8
case .choosingSticker:
return 9
}
}

View File

@ -341,6 +341,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
stringValue = strings.Activity_RecordingVideoMessage
case .uploadingInstantVideo:
stringValue = strings.Activity_UploadingVideoMessage
case .choosingSticker:
stringValue = strings.Activity_ChoosingSticker
case .speakingInGroupCall:
stringValue = ""
}
@ -372,6 +374,8 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
state = .playingGame(string, color)
case .speakingInGroupCall:
state = .typingText(string, color)
case .choosingSticker:
state = .choosingSticker(string, color)
}
} else {
if let titleContent = self.titleContent {