Remember message effect

This commit is contained in:
Isaac
2024-06-04 19:16:56 +04:00
parent b6b07f5c18
commit 6ccc9ed693
8 changed files with 144 additions and 43 deletions

View File

@@ -16,6 +16,7 @@ public enum SendMessageActionSheetControllerParams {
public let isScheduledMessages: Bool
public let mediaPreview: ChatSendMessageContextScreenMediaPreview?
public let mediaCaptionIsAbove: (Bool, (Bool) -> Void)?
public let messageEffect: (ChatSendMessageActionSheetControllerSendParameters.Effect?, (ChatSendMessageActionSheetControllerSendParameters.Effect?) -> Void)?
public let attachment: Bool
public let canSendWhenOnline: Bool
public let forwardMessageIds: [EngineMessage.Id]
@@ -24,6 +25,7 @@ public enum SendMessageActionSheetControllerParams {
isScheduledMessages: Bool,
mediaPreview: ChatSendMessageContextScreenMediaPreview?,
mediaCaptionIsAbove: (Bool, (Bool) -> Void)?,
messageEffect: (ChatSendMessageActionSheetControllerSendParameters.Effect?, (ChatSendMessageActionSheetControllerSendParameters.Effect?) -> Void)?,
attachment: Bool,
canSendWhenOnline: Bool,
forwardMessageIds: [EngineMessage.Id]
@@ -31,6 +33,7 @@ public enum SendMessageActionSheetControllerParams {
self.isScheduledMessages = isScheduledMessages
self.mediaPreview = mediaPreview
self.mediaCaptionIsAbove = mediaCaptionIsAbove
self.messageEffect = messageEffect
self.attachment = attachment
self.canSendWhenOnline = canSendWhenOnline
self.forwardMessageIds = forwardMessageIds
@@ -54,6 +57,7 @@ public enum SendMessageActionSheetControllerParams {
}
public func makeChatSendMessageActionSheetController(
initialData: ChatSendMessageContextScreen.InitialData,
context: AccountContext,
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
peerId: EnginePeer.Id?,
@@ -73,6 +77,7 @@ public func makeChatSendMessageActionSheetController(
isPremium: Bool = false
) -> ChatSendMessageActionSheetController {
return ChatSendMessageContextScreen(
initialData: initialData,
context: context,
updatedPresentationData: updatedPresentationData,
peerId: peerId,

View File

@@ -53,6 +53,7 @@ public protocol ChatSendMessageContextScreenMediaPreview: AnyObject {
final class ChatSendMessageContextScreenComponent: Component {
typealias EnvironmentType = ViewControllerComponentContainer.Environment
let initialData: ChatSendMessageContextScreen.InitialData
let context: AccountContext
let updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?
let peerId: EnginePeer.Id?
@@ -72,6 +73,7 @@ final class ChatSendMessageContextScreenComponent: Component {
let isPremium: Bool
init(
initialData: ChatSendMessageContextScreen.InitialData,
context: AccountContext,
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
peerId: EnginePeer.Id?,
@@ -90,6 +92,7 @@ final class ChatSendMessageContextScreenComponent: Component {
availableMessageEffects: AvailableMessageEffects?,
isPremium: Bool
) {
self.initialData = initialData
self.context = context
self.updatedPresentationData = updatedPresentationData
self.peerId = peerId
@@ -319,6 +322,8 @@ final class ChatSendMessageContextScreenComponent: Component {
switch component.params {
case let .sendMessage(sendMessage):
self.mediaCaptionIsAbove = sendMessage.mediaCaptionIsAbove?.0 ?? false
self.selectedMessageEffect = component.initialData.messageEffect
case let .editMessage(editMessage):
self.mediaCaptionIsAbove = editMessage.mediaCaptionIsAbove?.0 ?? false
}
@@ -841,6 +846,12 @@ final class ChatSendMessageContextScreenComponent: Component {
if !self.isUpdating {
self.state?.updated(transition: .easeInOut(duration: 0.2))
}
if case let .sendMessage(sendMessage) = component.params {
let mappedEffect = self.selectedMessageEffect.flatMap {
return ChatSendMessageActionSheetControllerSendParameters.Effect(id: $0.id)
}
sendMessage.messageEffect?.1(mappedEffect)
}
return
} else {
self.selectedMessageEffect = messageEffect
@@ -849,6 +860,13 @@ final class ChatSendMessageContextScreenComponent: Component {
self.state?.updated(transition: .easeInOut(duration: 0.2))
}
if case let .sendMessage(sendMessage) = component.params {
let mappedEffect = self.selectedMessageEffect.flatMap {
return ChatSendMessageActionSheetControllerSendParameters.Effect(id: $0.id)
}
sendMessage.messageEffect?.1(mappedEffect)
}
HapticFeedback().tap()
}
} else {
@@ -858,6 +876,13 @@ final class ChatSendMessageContextScreenComponent: Component {
self.state?.updated(transition: .easeInOut(duration: 0.2))
}
if case let .sendMessage(sendMessage) = component.params {
let mappedEffect = self.selectedMessageEffect.flatMap {
return ChatSendMessageActionSheetControllerSendParameters.Effect(id: $0.id)
}
sendMessage.messageEffect?.1(mappedEffect)
}
HapticFeedback().tap()
}
@@ -1319,6 +1344,14 @@ final class ChatSendMessageContextScreenComponent: Component {
}
public class ChatSendMessageContextScreen: ViewControllerComponentContainer, ChatSendMessageActionSheetController {
public final class InitialData {
fileprivate let messageEffect: AvailableMessageEffects.MessageEffect?
init(messageEffect: AvailableMessageEffects.MessageEffect?) {
self.messageEffect = messageEffect
}
}
private let context: AccountContext
private var processedDidAppear: Bool = false
@@ -1335,6 +1368,7 @@ public class ChatSendMessageContextScreen: ViewControllerComponentContainer, Cha
}
public init(
initialData: InitialData,
context: AccountContext,
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?,
peerId: EnginePeer.Id?,
@@ -1358,6 +1392,7 @@ public class ChatSendMessageContextScreen: ViewControllerComponentContainer, Cha
super.init(
context: context,
component: ChatSendMessageContextScreenComponent(
initialData: initialData,
context: context,
updatedPresentationData: updatedPresentationData,
peerId: peerId,
@@ -1439,4 +1474,30 @@ public class ChatSendMessageContextScreen: ViewControllerComponentContainer, Cha
}
}
}
public static func initialData(context: AccountContext, currentMessageEffectId: Int64?) -> Signal<InitialData, NoError> {
let messageEffect: Signal<AvailableMessageEffects.MessageEffect?, NoError>
if let currentMessageEffectId {
messageEffect = context.engine.stickers.availableMessageEffects()
|> take(1)
|> map { availableMessageEffects -> AvailableMessageEffects.MessageEffect? in
guard let availableMessageEffects else {
return nil
}
for messageEffect in availableMessageEffects.messageEffects {
if messageEffect.id == currentMessageEffectId || messageEffect.effectSticker.fileId.id == currentMessageEffectId {
return messageEffect
}
}
return nil
}
} else {
messageEffect = .single(nil)
}
return messageEffect
|> map { messageEffect -> InitialData in
return InitialData(messageEffect: messageEffect)
}
}
}

View File

@@ -20,16 +20,16 @@ import MultilineTextComponent
import ChatInputTextNode
import EmojiTextAttachmentView
private final class EffectIcon: Component {
enum Content: Equatable {
public final class ChatSendMessageScreenEffectIcon: Component {
public enum Content: Equatable {
case file(TelegramMediaFile)
case text(String)
}
let context: AccountContext
let content: Content
public let context: AccountContext
public let content: Content
init(
public init(
context: AccountContext,
content: Content
) {
@@ -37,7 +37,7 @@ private final class EffectIcon: Component {
self.content = content
}
static func ==(lhs: EffectIcon, rhs: EffectIcon) -> Bool {
public static func ==(lhs: ChatSendMessageScreenEffectIcon, rhs: ChatSendMessageScreenEffectIcon) -> Bool {
if lhs.context !== rhs.context {
return false
}
@@ -47,19 +47,19 @@ private final class EffectIcon: Component {
return true
}
final class View: UIView {
public final class View: UIView {
private var fileView: ReactionIconView?
private var textView: ComponentView<Empty>?
override init(frame: CGRect) {
override public init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func update(component: EffectIcon, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
func update(component: ChatSendMessageScreenEffectIcon, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
if case let .file(file) = component.content {
let fileView: ReactionIconView
if let current = self.fileView {
@@ -126,11 +126,11 @@ private final class EffectIcon: Component {
}
}
func makeView() -> View {
public func makeView() -> View {
return View(frame: CGRect())
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}
@@ -307,7 +307,7 @@ final class MessageItemView: UIView {
effectIcon = ComponentView()
self.effectIcon = effectIcon
}
let effectIconContent: EffectIcon.Content
let effectIconContent: ChatSendMessageScreenEffectIcon.Content
if let staticIcon = effect.staticIcon {
effectIconContent = .file(staticIcon)
} else {
@@ -315,7 +315,7 @@ final class MessageItemView: UIView {
}
effectIconSize = effectIcon.update(
transition: .immediate,
component: AnyComponent(EffectIcon(
component: AnyComponent(ChatSendMessageScreenEffectIcon(
context: context,
content: effectIconContent
)),

View File

@@ -32,7 +32,7 @@ final class SendButton: HighlightTrackingButton {
private let iconView: UIImageView
private var activityIndicator: RadialStatusNode?
private var didProcessSourceCustomContent: Bool = false
private var previousIsAnimatedIn: Bool?
private var sourceCustomContentView: UIView?
init(kind: Kind) {
@@ -70,7 +70,8 @@ final class SendButton: HighlightTrackingButton {
transition: Transition
) {
let innerSize = CGSize(width: size.width - 5.5 * 2.0, height: 33.0)
transition.setFrame(view: self.containerView, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - innerSize.width) * 0.5), y: floorToScreenPixels((size.height - innerSize.height) * 0.5)), size: innerSize))
let containerFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - innerSize.width) * 0.5), y: floorToScreenPixels((size.height - innerSize.height) * 0.5)), size: innerSize)
transition.setFrame(view: self.containerView, frame: containerFrame)
transition.setCornerRadius(layer: self.containerView.layer, cornerRadius: innerSize.height * 0.5)
if self.window != nil {
@@ -97,13 +98,21 @@ final class SendButton: HighlightTrackingButton {
self.backgroundLayer.backgroundColor = presentationData.theme.chat.inputPanel.actionControlFillColor.cgColor
transition.setFrame(layer: self.backgroundLayer, frame: CGRect(origin: CGPoint(), size: innerSize))
if !self.didProcessSourceCustomContent {
self.didProcessSourceCustomContent = true
if self.previousIsAnimatedIn != isAnimatedIn {
self.previousIsAnimatedIn = isAnimatedIn
var sourceCustomContentViewAlpha: CGFloat = 1.0
if let sourceCustomContentView = self.sourceCustomContentView {
sourceCustomContentViewAlpha = sourceCustomContentView.alpha
sourceCustomContentView.removeFromSuperview()
self.sourceCustomContentView = nil
}
if let sourceSendButton = sourceSendButton as? ChatSendMessageActionSheetControllerSourceSendButtonNode {
if let sourceCustomContentView = sourceSendButton.makeCustomContents() {
self.sourceCustomContentView = sourceCustomContentView
self.iconView.superview?.insertSubview(sourceCustomContentView, belowSubview: self.iconView)
sourceCustomContentView.alpha = sourceCustomContentViewAlpha
self.addSubview(sourceCustomContentView)
}
}
}
@@ -118,11 +127,16 @@ final class SendButton: HighlightTrackingButton {
}
if let sourceCustomContentView = self.sourceCustomContentView {
var sourceCustomContentTransition = transition
if sourceCustomContentView.bounds.isEmpty {
sourceCustomContentTransition = .immediate
}
let sourceCustomContentSize = sourceCustomContentView.bounds.size
let sourceCustomContentFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((innerSize.width - sourceCustomContentSize.width) * 0.5) + UIScreenPixel, y: floorToScreenPixels((innerSize.height - sourceCustomContentSize.height) * 0.5)), size: sourceCustomContentSize)
transition.setPosition(view: sourceCustomContentView, position: sourceCustomContentFrame.center)
transition.setBounds(view: sourceCustomContentView, bounds: CGRect(origin: CGPoint(), size: sourceCustomContentFrame.size))
transition.setAlpha(view: sourceCustomContentView, alpha: isAnimatedIn ? 0.0 : 1.0)
let sourceCustomContentFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((innerSize.width - sourceCustomContentSize.width) * 0.5) + UIScreenPixel, y: floorToScreenPixels((innerSize.height - sourceCustomContentSize.height) * 0.5)), size: sourceCustomContentSize).offsetBy(dx: containerFrame.minX, dy: containerFrame.minY)
sourceCustomContentTransition.setPosition(view: sourceCustomContentView, position: sourceCustomContentFrame.center)
sourceCustomContentTransition.setBounds(view: sourceCustomContentView, bounds: CGRect(origin: CGPoint(), size: sourceCustomContentFrame.size))
sourceCustomContentTransition.setAlpha(view: sourceCustomContentView, alpha: isAnimatedIn ? 0.0 : 1.0)
}
if let icon = self.iconView.image {