mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-04 20:22:50 +00:00
Remember message effect
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user