Add interactive dice success animation

Fix interactive dice tooltip localization
This commit is contained in:
Ilya Laktyushin
2020-04-23 05:41:38 +04:00
parent c3f2fa5bc3
commit 6e7a5af08d
14 changed files with 4089 additions and 4189 deletions

View File

@@ -56,26 +56,6 @@ private struct ChatControllerNodeDerivedLayoutState {
var upperInputPositionBound: CGFloat?
}
public struct InteractiveEmojiConfiguration {
static var defaultValue: InteractiveEmojiConfiguration {
return InteractiveEmojiConfiguration(emojis: [])
}
public let emojis: [String]
fileprivate init(emojis: [String]) {
self.emojis = emojis
}
static func with(appConfiguration: AppConfiguration) -> InteractiveEmojiConfiguration {
if let data = appConfiguration.data, let value = data["emojies_send_dice"] as? [String] {
return InteractiveEmojiConfiguration(emojis: value)
} else {
return .defaultValue
}
}
}
class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
let context: AccountContext
let chatLocation: ChatLocation
@@ -149,7 +129,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
var chatPresentationInterfaceState: ChatPresentationInterfaceState
var automaticMediaDownloadSettings: MediaAutoDownloadSettings
private var interactiveEmojis: [String] = []
private var interactiveEmojis: InteractiveEmojiConfiguration?
private var interactiveEmojisDisposable: Disposable?
private let selectedMessagesPromise = Promise<Set<MessageId>?>(nil)
@@ -318,10 +298,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
}))
self.interactiveEmojisDisposable = (self.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|> map { preferencesView -> [String] in
|> map { preferencesView -> InteractiveEmojiConfiguration in
let appConfiguration: AppConfiguration = preferencesView.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue
let configuration = InteractiveEmojiConfiguration.with(appConfiguration: appConfiguration)
return configuration.emojis
return InteractiveEmojiConfiguration.with(appConfiguration: appConfiguration)
}
|> deliverOnMainQueue).start(next: { [weak self] emojis in
if let strongSelf = self {
@@ -2299,7 +2278,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
let effectiveInputText = effectivePresentationInterfaceState.interfaceState.composeInputState.inputText
let trimmedInputText = effectiveInputText.string.trimmingCharacters(in: .whitespacesAndNewlines)
if case let .peer(peerId) = effectivePresentationInterfaceState.chatLocation, peerId.namespace != Namespaces.Peer.SecretChat, self.interactiveEmojis.contains(trimmedInputText) {
if case let .peer(peerId) = effectivePresentationInterfaceState.chatLocation, peerId.namespace != Namespaces.Peer.SecretChat, let interactiveEmojis = self.interactiveEmojis, interactiveEmojis.emojis.contains(trimmedInputText) {
messages.append(.message(text: "", attributes: [], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil))
} else {
let inputText = convertMarkdownToAttributes(effectiveInputText)
@@ -2400,123 +2379,5 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
func animateQuizCorrectOptionSelected() {
self.view.insertSubview(ConfettiView(frame: self.view.bounds), aboveSubview: self.historyNode.view)
/*class ConfettiView: UIView {
private let direction: Bool
private let confettiViewEmitterLayer = CAEmitterLayer()
private let confettiViewEmitterCell = CAEmitterCell()
init(frame: CGRect, direction: Bool) {
self.direction = direction
super.init(frame: frame)
self.isUserInteractionEnabled = false
self.setupConfettiEmitterLayer()
self.confettiViewEmitterLayer.frame = self.bounds
self.confettiViewEmitterLayer.emitterCells = generateConfettiEmitterCells()
self.layer.addSublayer(self.confettiViewEmitterLayer)
let animation = CAKeyframeAnimation(keyPath: #keyPath(CAEmitterLayer.birthRate))
animation.duration = 0.5
animation.timingFunction = CAMediaTimingFunction(name: .easeIn)
animation.fillMode = .forwards
animation.values = [1, 0, 0]
animation.keyTimes = [0, 0.5, 1]
animation.isRemovedOnCompletion = false
self.confettiViewEmitterLayer.beginTime = CACurrentMediaTime()
self.confettiViewEmitterLayer.birthRate = 1.0
CATransaction.begin()
CATransaction.setCompletionBlock { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, delay: 1.0, removeOnCompletion: false, completion: { _ in
self?.removeFromSuperview()
})
}
self.confettiViewEmitterLayer.add(animation, forKey: nil)
CATransaction.commit()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupConfettiEmitterLayer() {
let emitterWidth: CGFloat = self.bounds.width / 4.0
self.confettiViewEmitterLayer.emitterSize = CGSize(width: emitterWidth, height: 2.0)
self.confettiViewEmitterLayer.emitterShape = .line
self.confettiViewEmitterLayer.emitterPosition = CGPoint(x: direction ? 0.0 : (self.bounds.width - emitterWidth * 0.0), y: self.bounds.height)
}
private func generateConfettiEmitterCells() -> [CAEmitterCell] {
var cells = [CAEmitterCell]()
let cellImageCircle = generateFilledCircleImage(diameter: 4.0, color: .white)!.cgImage!
let cellImageLine = generateImage(CGSize(width: 4.0, height: 10.0), opaque: false, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(UIColor.white.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.width)))
context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: size.height - size.width), size: CGSize(width: size.width, height: size.width)))
context.fill(CGRect(origin: CGPoint(x: 0.0, y: size.width / 2.0), size: CGSize(width: size.width, height: size.height - size.width)))
})!.cgImage!
for index in 0 ..< 4 {
let cell = CAEmitterCell()
cell.color = self.nextColor(i: index).cgColor
cell.contents = index % 2 == 0 ? cellImageCircle : cellImageLine
cell.birthRate = 60.0
cell.lifetime = 14.0
cell.lifetimeRange = 0
if index % 2 == 0 {
cell.scale = 0.8
cell.scaleRange = 0.4
} else {
cell.scale = 0.5
cell.scaleRange = 0.1
}
cell.velocity = -self.randomVelocity
cell.velocityRange = abs(cell.velocity) * 0.3
cell.yAcceleration = 3000.0
cell.emissionLongitude = (self.direction ? -1.0 : 1.0) * (CGFloat.pi * 0.95)
cell.emissionRange = 0.2
cell.spin = 5.5
cell.spinRange = 1.0
cells.append(cell)
}
return cells
}
var randomNumber: Int {
let dimension = 4
return Int(arc4random_uniform(UInt32(dimension)))
}
var randomVelocity: CGFloat {
let velocities: [CGFloat] = [100.0, 120.0, 130.0, 140.0]
return velocities[self.randomNumber] * 12.0
}
private let colors: [UIColor] = ([
0x56CE6B,
0xCD89D0,
0x1E9AFF,
0xFF8724
] as [UInt32]).map(UIColor.init(rgb:))
private func nextColor(i: Int) -> UIColor {
return self.colors[i % self.colors.count]
}
}
self.view.insertSubview(ConfettiView(frame: self.view.bounds, direction: true), aboveSubview: self.historyNode.view)
self.view.insertSubview(ConfettiView(frame: self.view.bounds, direction: false), aboveSubview: self.historyNode.view)*/
}
}