mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Add interactive dice success animation
Fix interactive dice tooltip localization
This commit is contained in:
parent
c3f2fa5bc3
commit
6e7a5af08d
@ -5474,19 +5474,10 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"MuteFor.Forever" = "Mute Forever";
|
||||
|
||||
"Conversation.Dice" = "Send a 🎲 emoji to any chat to get a random number from Telegram.";
|
||||
|
||||
"Conversation.Dice.🎲" = "Send a dice emoji to any chat to roll a die.";
|
||||
"Conversation.Dice.🎯" = "Send a dart emoji to try your luck.";
|
||||
"Conversation.Dice.u1F3B2" = "Send a dice emoji to any chat to roll a die.";
|
||||
"Conversation.Dice.u1F3AF" = "Send a dart emoji to try your luck.";
|
||||
"Conversation.SendDice" = "Send";
|
||||
|
||||
"ForwardedDices_1" = "Forwarded dice";
|
||||
"ForwardedDices_2" = "2 forwarded dices";
|
||||
"ForwardedDices_3_10" = "%@ forwarded dices";
|
||||
"ForwardedDices_any" = "%@ forwarded dices";
|
||||
"ForwardedDices_many" = "%@ forwarded dices";
|
||||
"ForwardedDices_0" = "%@ forwarded dices";
|
||||
|
||||
"Conversation.ContextMenuDiscuss" = "Discuss";
|
||||
|
||||
"CreatePoll.ExplanationHeader" = "EXPLANATION";
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -1971,6 +1971,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self?.displayPollSolution(solution: solution, sourceNode: sourceNode, isAutomatic: false)
|
||||
}, displayDiceTooltip: { [weak self] dice in
|
||||
self?.displayDiceTooltip(dice: dice)
|
||||
}, animateDiceSuccess: { [weak self] in
|
||||
self?.chatDisplayNode.animateQuizCorrectOptionSelected()
|
||||
}, requestMessageUpdate: { [weak self] id in
|
||||
if let strongSelf = self {
|
||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)
|
||||
@ -6552,13 +6554,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
controller.dismissWithCommitAction()
|
||||
}
|
||||
})
|
||||
|
||||
let value: String?
|
||||
if dice.emoji == "🎲" {
|
||||
value = self.presentationData.strings.Conversation_Dice_🎲
|
||||
} else if dice.emoji == "🎯" {
|
||||
value = self.presentationData.strings.Conversation_Dice_🎯
|
||||
} else {
|
||||
let key = "Conversation.Dice.\(dice.emoji)"
|
||||
switch dice.emoji {
|
||||
case "🎲":
|
||||
value = self.presentationData.strings.Conversation_Dice_u1F3B2
|
||||
case "🎯":
|
||||
value = self.presentationData.strings.Conversation_Dice_u1F3AF
|
||||
default:
|
||||
let emojiHex = dice.emoji.unicodeScalars.map({ String(format:"%02x", $0.value) }).joined().uppercased()
|
||||
let key = "Conversation.Dice.u\(emojiHex)"
|
||||
if let string = self.presentationData.strings.primaryComponent.dict[key] {
|
||||
value = string
|
||||
} else if let string = self.presentationData.strings.secondaryComponent?.dict[key] {
|
||||
|
@ -109,6 +109,7 @@ public final class ChatControllerInteraction {
|
||||
let openPollCreation: (Bool?) -> Void
|
||||
let displayPollSolution: (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void
|
||||
let displayDiceTooltip: (TelegramMediaDice) -> Void
|
||||
let animateDiceSuccess: () -> Void
|
||||
|
||||
let requestMessageUpdate: (MessageId) -> Void
|
||||
let cancelInteractiveKeyboardGestures: () -> Void
|
||||
@ -125,7 +126,7 @@ public final class ChatControllerInteraction {
|
||||
var searchTextHighightState: (String, [MessageIndex])?
|
||||
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
||||
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, tapMessage: ((Message) -> Void)?, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?, Message?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOptions: @escaping (MessageId, [Data]) -> Void, requestOpenMessagePollResults: @escaping (MessageId, MediaId) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String?) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, dismissReplyMarkupMessage: @escaping (Message) -> Void, openMessagePollResults: @escaping (MessageId, Data) -> Void, openPollCreation: @escaping (Bool?) -> Void, displayPollSolution: @escaping (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void, displayDiceTooltip: @escaping (TelegramMediaDice) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, tapMessage: ((Message) -> Void)?, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?, Message?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOptions: @escaping (MessageId, [Data]) -> Void, requestOpenMessagePollResults: @escaping (MessageId, MediaId) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String?) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, dismissReplyMarkupMessage: @escaping (Message) -> Void, openMessagePollResults: @escaping (MessageId, Data) -> Void, openPollCreation: @escaping (Bool?) -> Void, displayPollSolution: @escaping (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void, displayDiceTooltip: @escaping (TelegramMediaDice) -> Void, animateDiceSuccess: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
self.openMessage = openMessage
|
||||
self.openPeer = openPeer
|
||||
self.openPeerMention = openPeerMention
|
||||
@ -185,6 +186,7 @@ public final class ChatControllerInteraction {
|
||||
self.dismissReplyMarkupMessage = dismissReplyMarkupMessage
|
||||
self.openMessagePollResults = openMessagePollResults
|
||||
self.displayDiceTooltip = displayDiceTooltip
|
||||
self.animateDiceSuccess = animateDiceSuccess
|
||||
|
||||
self.requestMessageUpdate = requestMessageUpdate
|
||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||
@ -228,6 +230,7 @@ public final class ChatControllerInteraction {
|
||||
}, openPollCreation: { _ in
|
||||
}, displayPollSolution: { _, _ in
|
||||
}, displayDiceTooltip: { _ in
|
||||
}, animateDiceSuccess: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -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)*/
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
|
||||
if let telegramDice = self.telegramDice {
|
||||
let animationNode = ManagedDiceAnimationNode(context: item.context, dice: telegramDice)
|
||||
let animationNode = ManagedDiceAnimationNode(context: item.context, emoji: telegramDice.emoji)
|
||||
self.animationNode = animationNode
|
||||
} else {
|
||||
let animationNode = AnimatedStickerNode()
|
||||
|
@ -425,6 +425,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
}, openPollCreation: { _ in
|
||||
}, displayPollSolution: { _, _ in
|
||||
}, displayDiceTooltip: { _ in
|
||||
}, animateDiceSuccess: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||
|
@ -61,8 +61,8 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
|
||||
return ("", true)
|
||||
case _ as TelegramMediaPoll:
|
||||
return (strings.ForwardedPolls(1), true)
|
||||
case _ as TelegramMediaDice:
|
||||
return (strings.ForwardedDices(1), true)
|
||||
case let dice as TelegramMediaDice:
|
||||
return (dice.emoji, true)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -68,20 +68,61 @@ private func rollingAnimationItem(account: Account, emojis: Signal<[TelegramMedi
|
||||
}
|
||||
}
|
||||
|
||||
private struct InteractiveEmojiSuccessParameters {
|
||||
let value: Int
|
||||
let frame: Int
|
||||
}
|
||||
|
||||
public struct InteractiveEmojiConfiguration {
|
||||
static var defaultValue: InteractiveEmojiConfiguration {
|
||||
return InteractiveEmojiConfiguration(emojis: [], successParameters: [:])
|
||||
}
|
||||
|
||||
public let emojis: [String]
|
||||
fileprivate let successParameters: [String: InteractiveEmojiSuccessParameters]
|
||||
|
||||
fileprivate init(emojis: [String], successParameters: [String: InteractiveEmojiSuccessParameters]) {
|
||||
self.emojis = emojis
|
||||
self.successParameters = successParameters
|
||||
}
|
||||
|
||||
static func with(appConfiguration: AppConfiguration) -> InteractiveEmojiConfiguration {
|
||||
if let data = appConfiguration.data, let emojis = data["emojies_send_dice"] as? [String] {
|
||||
var successParameters: [String: InteractiveEmojiSuccessParameters] = [:]
|
||||
if let success = data["emojies_send_dice_success"] as? [String: [String: Double]] {
|
||||
for (key, dict) in success {
|
||||
if let successValue = dict[""], let successFrame = dict[""] {
|
||||
successParameters[key] = InteractiveEmojiSuccessParameters(value: Int(successValue), frame: Int(successFrame))
|
||||
}
|
||||
}
|
||||
}
|
||||
return InteractiveEmojiConfiguration(emojis: emojis, successParameters: successParameters)
|
||||
} else {
|
||||
return .defaultValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStickerNode {
|
||||
private let context: AccountContext
|
||||
private let dice: TelegramMediaDice
|
||||
private let emoji: String
|
||||
|
||||
private var diceState: ManagedDiceAnimationState? = nil
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
private let emojis = Promise<[TelegramMediaFile]>()
|
||||
|
||||
init(context: AccountContext, dice: TelegramMediaDice) {
|
||||
init(context: AccountContext, emoji: String) {
|
||||
self.context = context
|
||||
self.dice = dice
|
||||
self.emoji = emoji
|
||||
|
||||
self.emojis.set(loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: .dice(dice.emoji), forceActualized: false)
|
||||
self.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration])
|
||||
|> map { preferencesView -> InteractiveEmojiConfiguration in
|
||||
let appConfiguration: AppConfiguration = preferencesView.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue
|
||||
return InteractiveEmojiConfiguration.with(appConfiguration: appConfiguration)
|
||||
}
|
||||
|
||||
self.emojis.set(loadedStickerPack(postbox: context.account.postbox, network: context.account.network, reference: .dice(emoji), forceActualized: false)
|
||||
|> mapToSignal { stickerPack -> Signal<[TelegramMediaFile], NoError> in
|
||||
switch stickerPack {
|
||||
case let .result(_, items, _):
|
||||
@ -114,14 +155,14 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick
|
||||
case .rolling:
|
||||
switch diceState {
|
||||
case let .value(value, _):
|
||||
item = animationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji, value: value)
|
||||
item = animationItem(account: context.account, emojis: self.emojis.get(), emoji: self.emoji, value: value)
|
||||
case .rolling:
|
||||
break
|
||||
}
|
||||
case .value:
|
||||
switch diceState {
|
||||
case .rolling:
|
||||
item = rollingAnimationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji)
|
||||
item = rollingAnimationItem(account: context.account, emojis: self.emojis.get(), emoji: self.emoji)
|
||||
case .value:
|
||||
break
|
||||
}
|
||||
@ -129,9 +170,9 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick
|
||||
} else {
|
||||
switch diceState {
|
||||
case let .value(value, immediate):
|
||||
item = animationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji, value: value, immediate: immediate, roll: true)
|
||||
item = animationItem(account: context.account, emojis: self.emojis.get(), emoji: self.emoji, value: value, immediate: immediate, roll: true)
|
||||
case .rolling:
|
||||
item = rollingAnimationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji)
|
||||
item = rollingAnimationItem(account: context.account, emojis: self.emojis.get(), emoji: self.emoji)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
||||
}, openPollCreation: { _ in
|
||||
}, displayPollSolution: { _, _ in
|
||||
}, displayDiceTooltip: { _ in
|
||||
}, animateDiceSuccess: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))
|
||||
|
@ -1529,6 +1529,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
}, openPollCreation: { _ in
|
||||
}, displayPollSolution: { _, _ in
|
||||
}, displayDiceTooltip: { _ in
|
||||
}, animateDiceSuccess: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -429,6 +429,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
|
||||
}, openPollCreation: { _ in
|
||||
}, displayPollSolution: { _, _ in
|
||||
}, displayDiceTooltip: { _ in
|
||||
}, animateDiceSuccess: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
@ -1137,6 +1137,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
}, openPollCreation: { _ in
|
||||
}, displayPollSolution: { _, _ in
|
||||
}, displayDiceTooltip: { _ in
|
||||
}, animateDiceSuccess: {
|
||||
}, requestMessageUpdate: { _ in
|
||||
}, cancelInteractiveKeyboardGestures: {
|
||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||
|
Loading…
x
Reference in New Issue
Block a user