mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Stories
This commit is contained in:
@@ -32,6 +32,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/EmojiSuggestionsComponent",
|
||||
"//submodules/TelegramUI/Components/EmojiTextAttachmentView",
|
||||
"//submodules/StickerPeekUI",
|
||||
"//submodules/Components/ReactionButtonListComponent",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
||||
@@ -9,6 +9,8 @@ import TelegramPresentationData
|
||||
import ChatPresentationInterfaceState
|
||||
import MoreHeaderButton
|
||||
import ContextUI
|
||||
import ReactionButtonListComponent
|
||||
import TelegramCore
|
||||
|
||||
private extension MessageInputActionButtonComponent.Mode {
|
||||
var iconName: String? {
|
||||
@@ -19,11 +21,11 @@ private extension MessageInputActionButtonComponent.Mode {
|
||||
return "Chat/Input/Text/IconAttachment"
|
||||
case .forward:
|
||||
return "Chat/Input/Text/IconForwardSend"
|
||||
case let .like(isActive):
|
||||
if isActive {
|
||||
return "Stories/InputLikeOn"
|
||||
} else {
|
||||
case let .like(reaction, _, _):
|
||||
if reaction == nil {
|
||||
return "Stories/InputLikeOff"
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
@@ -43,7 +45,7 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
case attach
|
||||
case forward
|
||||
case more
|
||||
case like(isActive: Bool)
|
||||
case like(reaction: MessageReaction.Reaction?, file: TelegramMediaFile?, animationFileId: Int64?)
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
@@ -127,12 +129,18 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
public let referenceNode: ContextReferenceContentNode
|
||||
public let containerNode: ContextControllerSourceNode
|
||||
private let sendIconView: UIImageView
|
||||
|
||||
private var moreButton: MoreHeaderButton?
|
||||
private var reactionIconView: ReactionIconView?
|
||||
|
||||
private var component: MessageInputActionButtonComponent?
|
||||
private weak var componentState: EmptyComponentState?
|
||||
|
||||
private var acceptNextButtonPress: Bool = false
|
||||
|
||||
public var likeIconView: UIView? {
|
||||
return self.reactionIconView
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.sendIconView = UIImageView()
|
||||
|
||||
@@ -157,6 +165,7 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
guard let self, let component = self.component, let longPressAction = component.longPressAction else {
|
||||
return
|
||||
}
|
||||
self.acceptNextButtonPress = false
|
||||
longPressAction(self, gesture)
|
||||
}
|
||||
|
||||
@@ -173,8 +182,6 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
|
||||
self.button.addTarget(self, action: #selector(self.touchDown), forControlEvents: .touchDown)
|
||||
self.button.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside)
|
||||
// but.addTarget(self, action: #selector(self.touchDown), for: .touchDown)
|
||||
// self.addTarget(self, action: #selector(self.pressed), for: .touchUpInside)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -182,6 +189,8 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
}
|
||||
|
||||
@objc private func touchDown() {
|
||||
self.acceptNextButtonPress = true
|
||||
|
||||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
@@ -189,6 +198,10 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
}
|
||||
|
||||
@objc private func pressed() {
|
||||
if !self.acceptNextButtonPress {
|
||||
return
|
||||
}
|
||||
|
||||
guard let component = self.component else {
|
||||
return
|
||||
}
|
||||
@@ -318,11 +331,10 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
|
||||
if self.sendIconView.image == nil || previousComponent?.mode.iconName != component.mode.iconName {
|
||||
if let iconName = component.mode.iconName {
|
||||
var tintColor: UIColor = .white
|
||||
if case .like(true) = component.mode {
|
||||
tintColor = UIColor(rgb: 0xFF3B30)
|
||||
}
|
||||
let tintColor: UIColor = .white
|
||||
self.sendIconView.image = generateTintedImage(image: UIImage(bundleImageName: iconName), color: tintColor)
|
||||
} else if case let .like(reaction, _, _) = component.mode, reaction != nil {
|
||||
self.sendIconView.image = nil
|
||||
} else if case .apply = component.mode {
|
||||
self.sendIconView.image = generateImage(CGSize(width: 33.0, height: 33.0), contextGenerator: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
@@ -379,6 +391,36 @@ public final class MessageInputActionButtonComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if case let .like(reactionValue, reactionFile, animationFileId) = component.mode, let reaction = reactionValue {
|
||||
let reactionIconFrame = CGRect(origin: .zero, size: availableSize).insetBy(dx: 3.0, dy: 3.0)
|
||||
|
||||
let reactionIconView: ReactionIconView
|
||||
if let current = self.reactionIconView {
|
||||
reactionIconView = current
|
||||
} else {
|
||||
reactionIconView = ReactionIconView(frame: reactionIconFrame)
|
||||
reactionIconView.isUserInteractionEnabled = false
|
||||
self.reactionIconView = reactionIconView
|
||||
self.addSubview(reactionIconView)
|
||||
}
|
||||
transition.setFrame(view: reactionIconView, frame: reactionIconFrame)
|
||||
reactionIconView.update(
|
||||
size: reactionIconFrame.size,
|
||||
context: component.context,
|
||||
file: reactionFile,
|
||||
fileId: animationFileId ?? reactionFile?.fileId.id ?? 0,
|
||||
animationCache: component.context.animationCache,
|
||||
animationRenderer: component.context.animationRenderer,
|
||||
placeholderColor: UIColor(white: 1.0, alpha: 0.2),
|
||||
animateIdle: false,
|
||||
reaction: reaction,
|
||||
transition: .immediate
|
||||
)
|
||||
} else if let reactionIconView = self.reactionIconView {
|
||||
self.reactionIconView = nil
|
||||
reactionIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
transition.setFrame(view: self.button.view, frame: CGRect(origin: .zero, size: availableSize))
|
||||
transition.setFrame(view: self.containerNode.view, frame: CGRect(origin: .zero, size: availableSize))
|
||||
transition.setFrame(view: self.referenceNode.view, frame: CGRect(origin: .zero, size: availableSize))
|
||||
|
||||
@@ -44,6 +44,18 @@ public final class MessageInputPanelComponent: Component {
|
||||
case emoji
|
||||
}
|
||||
|
||||
public struct MyReaction: Equatable {
|
||||
public let reaction: MessageReaction.Reaction
|
||||
public let file: TelegramMediaFile?
|
||||
public let animationFileId: Int64?
|
||||
|
||||
public init(reaction: MessageReaction.Reaction, file: TelegramMediaFile?, animationFileId: Int64?) {
|
||||
self.reaction = reaction
|
||||
self.file = file
|
||||
self.animationFileId = animationFileId
|
||||
}
|
||||
}
|
||||
|
||||
public final class ExternalState {
|
||||
public fileprivate(set) var isEditing: Bool = false
|
||||
public fileprivate(set) var hasText: Bool = false
|
||||
@@ -79,8 +91,9 @@ public final class MessageInputPanelComponent: Component {
|
||||
public let stopAndPreviewMediaRecording: (() -> Void)?
|
||||
public let discardMediaRecordingPreview: (() -> Void)?
|
||||
public let attachmentAction: (() -> Void)?
|
||||
public let hasLike: Bool
|
||||
public let myReaction: MyReaction?
|
||||
public let likeAction: (() -> Void)?
|
||||
public let likeOptionsAction: ((UIView, ContextGesture?) -> Void)?
|
||||
public let inputModeAction: (() -> Void)?
|
||||
public let timeoutAction: ((UIView) -> Void)?
|
||||
public let forwardAction: (() -> Void)?
|
||||
@@ -126,8 +139,9 @@ public final class MessageInputPanelComponent: Component {
|
||||
stopAndPreviewMediaRecording: (() -> Void)?,
|
||||
discardMediaRecordingPreview: (() -> Void)?,
|
||||
attachmentAction: (() -> Void)?,
|
||||
hasLike: Bool,
|
||||
myReaction: MyReaction?,
|
||||
likeAction: (() -> Void)?,
|
||||
likeOptionsAction: ((UIView, ContextGesture?) -> Void)?,
|
||||
inputModeAction: (() -> Void)?,
|
||||
timeoutAction: ((UIView) -> Void)?,
|
||||
forwardAction: (() -> Void)?,
|
||||
@@ -172,8 +186,9 @@ public final class MessageInputPanelComponent: Component {
|
||||
self.stopAndPreviewMediaRecording = stopAndPreviewMediaRecording
|
||||
self.discardMediaRecordingPreview = discardMediaRecordingPreview
|
||||
self.attachmentAction = attachmentAction
|
||||
self.hasLike = hasLike
|
||||
self.myReaction = myReaction
|
||||
self.likeAction = likeAction
|
||||
self.likeOptionsAction = likeOptionsAction
|
||||
self.inputModeAction = inputModeAction
|
||||
self.timeoutAction = timeoutAction
|
||||
self.forwardAction = forwardAction
|
||||
@@ -280,12 +295,15 @@ public final class MessageInputPanelComponent: Component {
|
||||
if (lhs.attachmentAction == nil) != (rhs.attachmentAction == nil) {
|
||||
return false
|
||||
}
|
||||
if lhs.hasLike != rhs.hasLike {
|
||||
if lhs.myReaction != rhs.myReaction {
|
||||
return false
|
||||
}
|
||||
if (lhs.likeAction == nil) != (rhs.likeAction == nil) {
|
||||
return false
|
||||
}
|
||||
if (lhs.likeOptionsAction == nil) != (rhs.likeOptionsAction == nil) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -345,6 +363,10 @@ public final class MessageInputPanelComponent: Component {
|
||||
return self.likeButton.view
|
||||
}
|
||||
|
||||
public var likeIconView: UIView? {
|
||||
return (self.likeButton.view as? MessageInputActionButtonComponent.View)?.likeIconView
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.fieldBackgroundView = BlurredBackgroundView(color: UIColor(white: 0.0, alpha: 0.5), enableBlur: true)
|
||||
|
||||
@@ -1064,7 +1086,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
let likeButtonSize = self.likeButton.update(
|
||||
transition: transition,
|
||||
component: AnyComponent(MessageInputActionButtonComponent(
|
||||
mode: .like(isActive: component.hasLike),
|
||||
mode: .like(reaction: component.myReaction?.reaction, file: component.myReaction?.file, animationFileId: component.myReaction?.animationFileId),
|
||||
action: { [weak self] _, action, _ in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
@@ -1074,7 +1096,7 @@ public final class MessageInputPanelComponent: Component {
|
||||
}
|
||||
component.likeAction?()
|
||||
},
|
||||
longPressAction: nil,
|
||||
longPressAction: component.likeOptionsAction,
|
||||
switchMediaInputMode: {
|
||||
},
|
||||
updateMediaCancelFraction: { _ in
|
||||
|
||||
Reference in New Issue
Block a user