From caaca2c32f1dae4db1cdbc90e77e335454720526 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 18 Apr 2020 07:03:03 +0400 Subject: [PATCH 1/2] Add support for server-configurable dice emojies --- .../Sources/ManagedAnimationNode.swift | 57 ++++-- .../Sources/ManagedMonkeyAnimationNode.swift | 38 ++-- .../Sources/ChatControllerNode.swift | 48 +++++- .../Sources/ManagedDiceAnimationNode.swift | 163 +++++++----------- .../Sources/UndoOverlayControllerNode.swift | 2 +- 5 files changed, 164 insertions(+), 144 deletions(-) diff --git a/submodules/ManagedAnimationNode/Sources/ManagedAnimationNode.swift b/submodules/ManagedAnimationNode/Sources/ManagedAnimationNode.swift index f30e53c9c3..2131982654 100644 --- a/submodules/ManagedAnimationNode/Sources/ManagedAnimationNode.swift +++ b/submodules/ManagedAnimationNode/Sources/ManagedAnimationNode.swift @@ -59,14 +59,14 @@ public final class ManagedAnimationState { } } -public struct ManagedAnimationFrameRange: Equatable { - var startFrame: Int - var endFrame: Int - - public init(startFrame: Int, endFrame: Int) { - self.startFrame = startFrame - self.endFrame = endFrame - } +public enum ManagedAnimationFramePosition { + case start + case end +} + +public enum ManagedAnimationFrameRange: Equatable { + case range(startFrame: Int, endFrame: Int) + case still(ManagedAnimationFramePosition) } public enum ManagedAnimationSource: Equatable { @@ -111,11 +111,11 @@ public enum ManagedAnimationSource: Equatable { public struct ManagedAnimationItem: Equatable { public let source: ManagedAnimationSource - var frames: ManagedAnimationFrameRange - var duration: Double + var frames: ManagedAnimationFrameRange? + var duration: Double? var loop: Bool - public init(source: ManagedAnimationSource, frames: ManagedAnimationFrameRange, duration: Double, loop: Bool = false) { + public init(source: ManagedAnimationSource, frames: ManagedAnimationFrameRange? = nil, duration: Double? = nil, loop: Bool = false) { self.source = source self.frames = frames self.duration = duration @@ -195,17 +195,42 @@ open class ManagedAnimationNode: ASDisplayNode { guard let state = self.state else { return } - let timestamp = CACurrentMediaTime() - let fps = state.fps - let frameRange = state.item.frames + let startFrame: Int + let endFrame: Int + let duration: Double + if let frames = state.item.frames { + switch frames { + case let .range(start, end): + startFrame = start + endFrame = end + case let .still(position): + switch position { + case .start: + startFrame = 0 + endFrame = 0 + case .end: + startFrame = state.frameCount + endFrame = state.frameCount + } + } + } else { + startFrame = 0 + endFrame = state.frameCount + } + + if let durationValue = state.item.duration { + duration = durationValue + } else { + let fps: Double = state.fps > 0 ? state.fps : 60 + duration = Double(state.frameCount) / fps + } - let duration: Double = state.item.duration var t = state.relativeTime / duration t = max(0.0, t) t = min(1.0, t) //print("\(t) \(state.item.name)") - let frameOffset = Int(Double(frameRange.startFrame) * (1.0 - t) + Double(frameRange.endFrame) * t) + let frameOffset = Int(Double(startFrame) * (1.0 - t) + Double(endFrame) * t) let lowerBound: Int = 0 let upperBound = state.frameCount - 1 let frameIndex = max(lowerBound, min(upperBound, frameOffset)) diff --git a/submodules/PasswordSetupUI/Sources/ManagedMonkeyAnimationNode.swift b/submodules/PasswordSetupUI/Sources/ManagedMonkeyAnimationNode.swift index 217cf54187..b564786ab5 100644 --- a/submodules/PasswordSetupUI/Sources/ManagedMonkeyAnimationNode.swift +++ b/submodules/PasswordSetupUI/Sources/ManagedMonkeyAnimationNode.swift @@ -28,7 +28,7 @@ final class ManagedMonkeyAnimationNode: ManagedAnimationNode { init() { super.init(size: CGSize(width: 136.0, height: 136.0)) - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.3)) } deinit { @@ -68,12 +68,12 @@ final class ManagedMonkeyAnimationNode: ManagedAnimationNode { private func enqueueIdle(_ idle: ManagedMonkeyAnimationIdle) { switch idle { case .still: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.3)) case .blink: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle1"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 30), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle1"), frames: .range(startFrame: 0, endFrame: 30), duration: 0.3)) case .ear: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle2"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 30), duration: 0.3)) - //self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 179), duration: 3.0)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle2"), frames: .range(startFrame: 0, endFrame: 30), duration: 0.3)) + //self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: .range(startFrame: 0, endFrame: 179), duration: 3.0)) } } @@ -89,7 +89,7 @@ final class ManagedMonkeyAnimationNode: ManagedAnimationNode { let upperBound = 160 let frameIndex = lowerBound + Int(value * CGFloat(upperBound - lowerBound)) if let state = self.state, state.item.source == .local("TwoFactorSetupMonkeyTracking") { - let item = ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyTracking"), frames: ManagedAnimationFrameRange(startFrame: state.frameIndex ?? 0, endFrame: frameIndex), duration: 0.3) + let item = ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyTracking"), frames: .range(startFrame: state.frameIndex ?? 0, endFrame: frameIndex), duration: 0.3) self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state) self.didTryAdvancingState = false self.updateAnimation() @@ -97,13 +97,13 @@ final class ManagedMonkeyAnimationNode: ManagedAnimationNode { self.trackStack = self.trackStack.filter { $0.source != .local("TwoFactorSetupMonkeyTracking") } - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyTracking"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: frameIndex), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyTracking"), frames: .range(startFrame: 0, endFrame: frameIndex), duration: 0.3)) } } func enqueueClearTracking() { if let state = self.state, state.item.source == .local("TwoFactorSetupMonkeyTracking") { - let item = ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyTracking"), frames: ManagedAnimationFrameRange(startFrame: state.frameIndex ?? 0, endFrame: 0), duration: 0.3) + let item = ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyTracking"), frames: .range(startFrame: state.frameIndex ?? 0, endFrame: 0), duration: 0.3) self.state = ManagedAnimationState(displaySize: self.intrinsicSize, item: item, current: state) self.didTryAdvancingState = false self.updateAnimation() @@ -116,50 +116,50 @@ final class ManagedMonkeyAnimationNode: ManagedAnimationNode { case let .idle(idle): self.enqueueIdle(idle) case .eyesClosed: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: .range(startFrame: 0, endFrame: 41), duration: 0.3)) case .peeking: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: .range(startFrame: 0, endFrame: 41), duration: 0.3)) case let .tracking(value): enqueueTracking(value) } case .eyesClosed: switch monkeyState { case let .idle(idle): - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: .range(startFrame: 41, endFrame: 0), duration: 0.3)) self.enqueueIdle(idle) case .eyesClosed: break case .peeking: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyPeek"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 14), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyPeek"), frames: .range(startFrame: 0, endFrame: 14), duration: 0.3)) case let .tracking(value): - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: .range(startFrame: 41, endFrame: 0), duration: 0.3)) enqueueTracking(value) } case .peeking: switch monkeyState { case let .idle(idle): - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: .range(startFrame: 41, endFrame: 0), duration: 0.3)) self.enqueueIdle(idle) case .eyesClosed: - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyPeek"), frames: ManagedAnimationFrameRange(startFrame: 14, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyPeek"), frames: .range(startFrame: 14, endFrame: 0), duration: 0.3)) case .peeking: break case let .tracking(value): - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: ManagedAnimationFrameRange(startFrame: 41, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: .range(startFrame: 41, endFrame: 0), duration: 0.3)) enqueueTracking(value) } case let .tracking(currentValue): switch monkeyState { case let .idle(idle): enqueueClearTracking() - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 0), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyIdle"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.3)) self.enqueueIdle(idle) case .eyesClosed: enqueueClearTracking() - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyClose"), frames: .range(startFrame: 0, endFrame: 41), duration: 0.3)) case .peeking: enqueueClearTracking() - self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 41), duration: 0.3)) + self.trackTo(item: ManagedAnimationItem(source: .local("TwoFactorSetupMonkeyCloseAndPeek"), frames: .range(startFrame: 0, endFrame: 41), duration: 0.3)) case let .tracking(value): if abs(currentValue - value) > CGFloat.ulpOfOne { enqueueTracking(value) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 281915276d..f59537fc55 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -56,6 +56,26 @@ 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 @@ -77,7 +97,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } let backgroundNode: WallpaperBackgroundNode - let backgroundDisposable = MetaDisposable() + let backgroundImageDisposable = MetaDisposable() let historyNode: ChatHistoryListNode let reactionContainerNode: ReactionSelectionParentNode let historyNodeContainer: ASDisplayNode @@ -129,6 +149,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var chatPresentationInterfaceState: ChatPresentationInterfaceState var automaticMediaDownloadSettings: MediaAutoDownloadSettings + private var interactiveEmojis: [String] = [] + private var interactiveEmojisDisposable: Disposable? + private let selectedMessagesPromise = Promise?>(nil) var selectedMessages: Set? { didSet { @@ -288,11 +311,24 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } - self.backgroundDisposable.set(chatControllerBackgroundImageSignal(wallpaper: chatPresentationInterfaceState.chatWallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, accountMediaBox: context.account.postbox.mediaBox).start(next: { [weak self] image in - if let strongSelf = self, let (image, final) = image { + self.backgroundImageDisposable.set(chatControllerBackgroundImageSignal(wallpaper: chatPresentationInterfaceState.chatWallpaper, mediaBox: context.sharedContext.accountManager.mediaBox, accountMediaBox: context.account.postbox.mediaBox).start(next: { [weak self] image in + if let strongSelf = self, let (image, _) = image { strongSelf.backgroundNode.image = image } })) + + self.interactiveEmojisDisposable = (self.context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]) + |> map { preferencesView -> [String] in + let appConfiguration: AppConfiguration = preferencesView.values[PreferencesKeys.appConfiguration] as? AppConfiguration ?? .defaultValue + let configuration = InteractiveEmojiConfiguration.with(appConfiguration: appConfiguration) + return configuration.emojis + } + |> deliverOnMainQueue).start(next: { [weak self] emojis in + if let strongSelf = self { + strongSelf.interactiveEmojis = emojis + } + }) + if case .gradient = chatPresentationInterfaceState.chatWallpaper { self.backgroundNode.imageContentMode = .scaleToFill } else { @@ -350,6 +386,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } deinit { + self.backgroundImageDisposable.dispose() + self.interactiveEmojisDisposable?.dispose() self.openStickersDisposable?.dispose() self.displayVideoUnmuteTipDisposable?.dispose() } @@ -1468,7 +1506,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let themeUpdated = self.chatPresentationInterfaceState.theme !== chatPresentationInterfaceState.theme if self.chatPresentationInterfaceState.chatWallpaper != chatPresentationInterfaceState.chatWallpaper { - self.backgroundDisposable.set(chatControllerBackgroundImageSignal(wallpaper: chatPresentationInterfaceState.chatWallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, accountMediaBox: self.context.account.postbox.mediaBox).start(next: { [weak self] image in + self.backgroundImageDisposable.set(chatControllerBackgroundImageSignal(wallpaper: chatPresentationInterfaceState.chatWallpaper, mediaBox: self.context.sharedContext.accountManager.mediaBox, accountMediaBox: self.context.account.postbox.mediaBox).start(next: { [weak self] image in if let strongSelf = self, let (image, final) = image { strongSelf.backgroundNode.image = image } @@ -2261,7 +2299,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, ["🎲", "🎯"].contains(trimmedInputText) { + if case let .peer(peerId) = effectivePresentationInterfaceState.chatLocation, peerId.namespace != Namespaces.Peer.SecretChat, self.interactiveEmojis.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) diff --git a/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift b/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift index e8ece51236..08655dedf7 100644 --- a/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift +++ b/submodules/TelegramUI/Sources/ManagedDiceAnimationNode.swift @@ -14,14 +14,57 @@ enum ManagedDiceAnimationState: Equatable { case value(Int32, Bool) } -private func rollingAnimationItem(emoji: String) -> ManagedAnimationItem? { +private func animationItem(account: Account, emojis: Signal<[TelegramMediaFile], NoError>, emoji: String, value: Int32?, immediate: Bool = false, roll: Bool = false, loop: Bool = false) -> Signal { + return emojis + |> mapToSignal { diceEmojis -> Signal in + if let value = value, value >= diceEmojis.count { + return .complete() + } + let file = diceEmojis[Int(value ?? 0)] + + if let _ = account.postbox.mediaBox.completedResourcePath(file.resource) { + if immediate { + return .single(ManagedAnimationItem(source: .resource(account.postbox.mediaBox, file.resource), frames: .still(.end), duration: 0)) + } else { + return .single(ManagedAnimationItem(source: .resource(account.postbox.mediaBox, file.resource), loop: loop)) + } + } else { + let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512) + let fittedSize = dimensions.cgSize.aspectFilled(CGSize(width: 384.0, height: 384.0)) + + let fetched = freeMediaFileInteractiveFetched(account: account, fileReference: .standalone(media: file)) + let animationItem = Signal { subscriber in + let fetchedDisposable = fetched.start() + let resourceDisposable = (chatMessageAnimationData(postbox: account.postbox, resource: file.resource, fitzModifier: nil, width: Int(fittedSize.width), height: Int(fittedSize.height), synchronousLoad: false) + |> filter { data in + return data.complete + }).start(next: { next in + subscriber.putNext(ManagedAnimationItem(source: .resource(account.postbox.mediaBox, file.resource), loop: loop)) + }) + + return ActionDisposable { + fetchedDisposable.dispose() + resourceDisposable.dispose() + } + } + + if roll { + return rollingAnimationItem(account: account, emojis: emojis, emoji: emoji) |> then(animationItem) + } else { + return animationItem + } + } + } +} + +private func rollingAnimationItem(account: Account, emojis: Signal<[TelegramMediaFile], NoError>, emoji: String) -> Signal { switch emoji { case "🎲": - return ManagedAnimationItem(source: .local("Dice_Rolling"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 60), duration: 1.0, loop: true) + return .single(ManagedAnimationItem(source: .local("Dice_Rolling"), loop: true)) case "🎯": - return ManagedAnimationItem(source: .local("Darts_Aiming"), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: 90), duration: 1.5, loop: true) + return .single(ManagedAnimationItem(source: .local("Darts_Aiming"), loop: true)) default: - return nil + return animationItem(account: account, emojis: emojis, emoji: emoji, value: nil, loop: true) } } @@ -63,20 +106,7 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick let previousState = self.diceState self.diceState = diceState - let frameCount: Int - let duration: Double - - switch dice.emoji { - case "🎲": - frameCount = 180 - duration = 3.0 - case "🎯": - frameCount = 100 - duration = 1.6 - default: - frameCount = 180 - duration = 1.6 - } + var item: Signal? = nil let context = self.context if let previousState = previousState { @@ -84,47 +114,14 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick case .rolling: switch diceState { case let .value(value, _): - let animationItem: Signal = self.emojis.get() - |> mapToSignal { emojis -> Signal in - guard emojis.count >= value else { - return .complete() - } - let file = emojis[Int(value) - 1] - let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512) - let fittedSize = dimensions.cgSize.aspectFilled(CGSize(width: 384.0, height: 384.0)) - - let fetched = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)) - let animationItem = Signal { subscriber in - let fetchedDisposable = fetched.start() - let resourceDisposable = (chatMessageAnimationData(postbox: context.account.postbox, resource: file.resource, fitzModifier: nil, width: Int(fittedSize.width), height: Int(fittedSize.height), synchronousLoad: false) - |> filter { data in - return data.complete - }).start(next: { next in - subscriber.putNext(ManagedAnimationItem(source: .resource(context.account.postbox.mediaBox, file.resource), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: frameCount), duration: duration)) - }) - - return ActionDisposable { - fetchedDisposable.dispose() - resourceDisposable.dispose() - } - } - return animationItem - } - - self.disposable.set((animationItem |> deliverOnMainQueue).start(next: { [weak self] item in - if let strongSelf = self { - strongSelf.trackTo(item: item) - } - })) + item = animationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji, value: value) case .rolling: break } case .value: switch diceState { case .rolling: - if let item = rollingAnimationItem(emoji: self.dice.emoji) { - self.trackTo(item: item) - } + item = rollingAnimationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji) case .value: break } @@ -132,58 +129,18 @@ final class ManagedDiceAnimationNode: ManagedAnimationNode, GenericAnimatedStick } else { switch diceState { case let .value(value, immediate): - let animationItem: Signal = self.emojis.get() - |> mapToSignal { emojis -> Signal in - guard emojis.count >= value else { - return .complete() - } - let file = emojis[Int(value) - 1] - - if let _ = context.account.postbox.mediaBox.completedResourcePath(file.resource) { - if immediate { - return .single(ManagedAnimationItem(source: .resource(context.account.postbox.mediaBox, file.resource), frames: ManagedAnimationFrameRange(startFrame: frameCount, endFrame: frameCount), duration: 0.0)) - } else { - return .single(ManagedAnimationItem(source: .resource(context.account.postbox.mediaBox, file.resource), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: frameCount), duration: duration)) - } - } else { - let dimensions = file.dimensions ?? PixelDimensions(width: 512, height: 512) - let fittedSize = dimensions.cgSize.aspectFilled(CGSize(width: 384.0, height: 384.0)) - - let fetched = freeMediaFileInteractiveFetched(account: self.context.account, fileReference: .standalone(media: file)) - let animationItem = Signal { subscriber in - let fetchedDisposable = fetched.start() - let resourceDisposable = (chatMessageAnimationData(postbox: self.context.account.postbox, resource: file.resource, fitzModifier: nil, width: Int(fittedSize.width), height: Int(fittedSize.height), synchronousLoad: false) - |> filter { data in - return data.complete - }).start(next: { next in - subscriber.putNext(ManagedAnimationItem(source: .resource(context.account.postbox.mediaBox, file.resource), frames: ManagedAnimationFrameRange(startFrame: 0, endFrame: frameCount), duration: duration)) - subscriber.putCompletion() - }) - - return ActionDisposable { - fetchedDisposable.dispose() - resourceDisposable.dispose() - } - } - - if let item = rollingAnimationItem(emoji: self.dice.emoji) { - return .single(item) |> then(animationItem) - } else { - return animationItem - } - } - } - - self.disposable.set((animationItem |> deliverOnMainQueue).start(next: { [weak self] item in - if let strongSelf = self { - strongSelf.trackTo(item: item) - } - })) + item = animationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji, value: value, immediate: immediate, roll: true) case .rolling: - if let item = rollingAnimationItem(emoji: self.dice.emoji) { - self.trackTo(item: item) - } + item = rollingAnimationItem(account: context.account, emojis: self.emojis.get(), emoji: self.dice.emoji) } } + + if let item = item { + self.disposable.set((item |> deliverOnMainQueue).start(next: { [weak self] item in + if let strongSelf = self, let item = item { + strongSelf.trackTo(item: item) + } + })) + } } } diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index 2ad760abfb..1031a3806c 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -311,7 +311,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { if let value = dice.value { switch stickerPack { case let .result(_, items, _): - let item = items[Int(value) - 1] + let item = items[Int(value)] if let item = item as? StickerPackItem { animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: account, resource: item.file.resource), width: 120, height: 120, playbackMode: .once, mode: .direct) } From c3f2fa5bc36d073853033b870b53f4460ba852eb Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 18 Apr 2020 12:48:32 +0400 Subject: [PATCH 2/2] Remove mic button waves decoration --- .../Sources/TGModernConversationInputMicButton.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m b/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m index 79c693110b..cf50004ae4 100644 --- a/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m +++ b/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m @@ -379,11 +379,11 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius _innerCircleView.alpha = 0.0f; [[_presentation view] addSubview:_innerCircleView]; - if ([_delegate respondsToSelector:@selector(micButtonDecoration)]) { - UIView *decoration = [_delegate micButtonDecoration]; - _decoration = decoration; - [[_presentation view] addSubview:_decoration]; - } +// if ([_delegate respondsToSelector:@selector(micButtonDecoration)]) { +// UIView *decoration = [_delegate micButtonDecoration]; +// _decoration = decoration; +// [[_presentation view] addSubview:_decoration]; +// } _outerCircleView = [[UIImageView alloc] initWithImage:[self outerCircleImage:self.pallete != nil ? self.pallete.buttonColor : TGAccentColor()]]; _outerCircleView.alpha = 0.0f;