mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-05 05:51:42 +00:00
Stories
This commit is contained in:
parent
ff32f34405
commit
029654c14a
@ -1994,7 +1994,7 @@ public class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDeleg
|
|||||||
if let image = commentsButtonCenterIcon.image {
|
if let image = commentsButtonCenterIcon.image {
|
||||||
commentsButtonCenterIcon.bounds = image.size.centered(in: iconFrame)
|
commentsButtonCenterIcon.bounds = image.size.centered(in: iconFrame)
|
||||||
}
|
}
|
||||||
transition.updateTransformRotation(view: commentsButtonCenterIcon, angle: !isExpanded ? (CGFloat.pi * 3.0 / 4.0) : 0.0)
|
transition.updateTransformRotation(view: commentsButtonCenterIcon, angle: isExpanded ? (CGFloat.pi * 3.0 / 4.0) : 0.0)
|
||||||
|
|
||||||
commentsButtonIcon.contentsLayer.position = CGRect(origin: CGPoint(), size: iconFrame.size).center
|
commentsButtonIcon.contentsLayer.position = CGRect(origin: CGPoint(), size: iconFrame.size).center
|
||||||
commentsButtonIcon.contentsLayer.bounds = CGRect(origin: CGPoint(), size: iconFrame.size)
|
commentsButtonIcon.contentsLayer.bounds = CGRect(origin: CGPoint(), size: iconFrame.size)
|
||||||
|
|||||||
@ -1032,7 +1032,7 @@ public final class MessageInputPanelComponent: Component {
|
|||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
chatPeerId: component.chatLocation?.peerId ?? component.context.account.peerId,
|
chatPeerId: component.chatLocation?.peerId ?? component.context.account.peerId,
|
||||||
inlineActions: inlineActions,
|
inlineActions: inlineActions,
|
||||||
leftAction: ChatTextInputPanelComponent.LeftAction(kind: .toggleExpanded(isVisible: component.liveChatState?.isEnabled == true, isExpanded: component.liveChatState?.isExpanded ?? true, hasUnseen: component.liveChatState?.hasUnseenMessages ?? false), action: { [weak self] in
|
leftAction: ChatTextInputPanelComponent.LeftAction(kind: .toggleExpanded(isVisible: component.liveChatState?.isEnabled == true, isExpanded: component.liveChatState?.isExpanded ?? true && component.liveChatState?.isEmpty == false, hasUnseen: component.liveChatState?.hasUnseenMessages ?? false), action: { [weak self] in
|
||||||
guard let self, let component = self.component else {
|
guard let self, let component = self.component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -88,6 +88,8 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
private let contentContainer: UIView
|
private let contentContainer: UIView
|
||||||
private var avatarNode: AvatarNode?
|
private var avatarNode: AvatarNode?
|
||||||
private let textExternal = MultilineTextWithEntitiesComponent.External()
|
private let textExternal = MultilineTextWithEntitiesComponent.External()
|
||||||
|
private let authorTitle = ComponentView<Empty>()
|
||||||
|
private var adminBadgeText: ComponentView<Empty>?
|
||||||
private let text = ComponentView<Empty>()
|
private let text = ComponentView<Empty>()
|
||||||
private var crownIcon: UIImageView?
|
private var crownIcon: UIImageView?
|
||||||
private var backgroundView: UIImageView?
|
private var backgroundView: UIImageView?
|
||||||
@ -232,13 +234,11 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let textString = NSMutableAttributedString()
|
let textString = NSMutableAttributedString()
|
||||||
textString.append(NSAttributedString(string: component.message.author?.displayTitle(strings: component.strings, displayOrder: .firstLast) ?? " ", font: Font.semibold(15.0), textColor: secondaryTextColor))
|
|
||||||
if !component.message.text.isEmpty {
|
if !component.message.text.isEmpty {
|
||||||
textString.append(NSAttributedString(string: " ", font: Font.semibold(15.0), textColor: secondaryTextColor))
|
|
||||||
textString.append(NSAttributedString(string: component.message.text, font: Font.regular(15.0), textColor: primaryTextColor))
|
textString.append(NSAttributedString(string: component.message.text, font: Font.regular(15.0), textColor: primaryTextColor))
|
||||||
}
|
}
|
||||||
|
|
||||||
var textTopLeftCutout: CGFloat?
|
var textTopLeftCutout: CGFloat = 0.0
|
||||||
if let topPlace = component.topPlace {
|
if let topPlace = component.topPlace {
|
||||||
let crownIcon: UIImageView
|
let crownIcon: UIImageView
|
||||||
if let current = self.crownIcon {
|
if let current = self.crownIcon {
|
||||||
@ -254,7 +254,9 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
crownIcon.tintColor = secondaryTextColor
|
crownIcon.tintColor = secondaryTextColor
|
||||||
|
|
||||||
if let image = crownIcon.image {
|
if let image = crownIcon.image {
|
||||||
textTopLeftCutout = image.size.width + 4.0
|
if !component.message.isFromAdmin {
|
||||||
|
textTopLeftCutout = image.size.width + 4.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let crownIcon = self.crownIcon {
|
if let crownIcon = self.crownIcon {
|
||||||
@ -268,17 +270,58 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
textBottomRightCutout = starsAmountTextSize.width + 20.0
|
textBottomRightCutout = starsAmountTextSize.width + 20.0
|
||||||
}
|
}
|
||||||
|
|
||||||
var textCutout: TextNodeCutout?
|
|
||||||
if textBottomRightCutout != nil || textTopLeftCutout != nil {
|
|
||||||
textCutout = TextNodeCutout(topLeft: textTopLeftCutout.flatMap({ CGSize(width: $0, height: 8.0) }), bottomRight: textBottomRightCutout.flatMap({ CGSize(width: $0, height: 8.0) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxTextWidth: CGFloat = availableSize.width - insets.left - insets.right - avatarSize - avatarSpacing
|
var maxTextWidth: CGFloat = availableSize.width - insets.left - insets.right - avatarSize - avatarSpacing
|
||||||
if let starsAmountTextSize, displayStarsAmountBackground {
|
if let starsAmountTextSize, displayStarsAmountBackground {
|
||||||
var cutoutWidth: CGFloat = starsAmountTextSize.width + 20.0
|
var cutoutWidth: CGFloat = starsAmountTextSize.width + 20.0
|
||||||
cutoutWidth += 30.0
|
cutoutWidth += 30.0
|
||||||
maxTextWidth -= cutoutWidth
|
maxTextWidth -= cutoutWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let authorTitleSize = self.authorTitle.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(MultilineTextWithEntitiesComponent(
|
||||||
|
context: component.context,
|
||||||
|
animationCache: component.context.animationCache,
|
||||||
|
animationRenderer: component.context.animationRenderer,
|
||||||
|
placeholderColor: .gray,
|
||||||
|
text: .plain(NSAttributedString(string: component.message.author?.displayTitle(strings: component.strings, displayOrder: .firstLast) ?? " ", font: Font.semibold(15.0), textColor: secondaryTextColor)),
|
||||||
|
maximumNumberOfLines: 1,
|
||||||
|
lineSpacing: 0.1
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: min(maxTextWidth - 80.0, 180.0), height: 100000.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
if !component.message.isFromAdmin {
|
||||||
|
textTopLeftCutout += authorTitleSize.width + 6.0
|
||||||
|
}
|
||||||
|
|
||||||
|
var adminBadgeTextSize: CGSize?
|
||||||
|
if component.message.isFromAdmin && !displayStarsAmountBackground {
|
||||||
|
let adminBadgeText: ComponentView<Empty>
|
||||||
|
if let current = self.adminBadgeText {
|
||||||
|
adminBadgeText = current
|
||||||
|
} else {
|
||||||
|
adminBadgeText = ComponentView()
|
||||||
|
self.adminBadgeText = adminBadgeText
|
||||||
|
}
|
||||||
|
adminBadgeTextSize = adminBadgeText.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(string: component.strings.ChatAdmins_AdminLabel, font: Font.regular(11.0), textColor: secondaryTextColor))
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: 200.0, height: 100.0)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
if let adminBadgeText = self.adminBadgeText {
|
||||||
|
self.adminBadgeText = nil
|
||||||
|
adminBadgeText.view?.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let textCutout = TextNodeCutout(topLeft: CGSize(width: textTopLeftCutout, height: 8.0), bottomRight: textBottomRightCutout.flatMap({ CGSize(width: $0, height: 8.0) }))
|
||||||
|
|
||||||
let textSize = self.text.update(
|
let textSize = self.text.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextWithEntitiesComponent(
|
component: AnyComponent(MultilineTextWithEntitiesComponent(
|
||||||
@ -320,23 +363,48 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
avatarNode.setPeer(context: component.context, theme: component.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
avatarNode.setPeer(context: component.context, theme: component.theme, peer: peer, displayDimensions: CGSize(width: avatarSize, height: avatarSize))
|
||||||
}
|
}
|
||||||
|
if component.message.isFromAdmin {
|
||||||
|
avatarNode.setStoryStats(storyStats: AvatarNode.StoryStats(totalCount: 1, unseenCount: 1, hasUnseenCloseFriendsItems: false, hasLiveItems: true), presentationParams: AvatarNode.StoryPresentationParams(colors: AvatarNode.Colors(theme: component.theme), lineWidth: 1.0, inactiveLineWidth: 1.0), transition: .immediate)
|
||||||
|
} else {
|
||||||
|
avatarNode.setStoryStats(storyStats: nil, presentationParams: AvatarNode.StoryPresentationParams(colors: AvatarNode.Colors(theme: component.theme), lineWidth: 1.0, inactiveLineWidth: 1.0), transition: .immediate)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
avatarNode.setCustomLetters([" "])
|
avatarNode.setCustomLetters([" "])
|
||||||
|
avatarNode.setStoryStats(storyStats: nil, presentationParams: AvatarNode.StoryPresentationParams(colors: AvatarNode.Colors(theme: component.theme), lineWidth: 2.0, inactiveLineWidth: 2.0), transition: .immediate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let textFrame = CGRect(origin: CGPoint(x: insets.left + avatarSize + avatarSpacing, y: avatarFrame.minY + 3.0), size: textSize)
|
var authorTitleFrame = CGRect(origin: CGPoint(x: insets.left + avatarSize + avatarSpacing, y: avatarFrame.minY + 3.0), size: authorTitleSize)
|
||||||
|
if let image = self.crownIcon?.image {
|
||||||
|
authorTitleFrame.origin.x += image.size.width + 4.0
|
||||||
|
}
|
||||||
|
if let authorTitleView = self.authorTitle.view {
|
||||||
|
if authorTitleView.superview == nil {
|
||||||
|
authorTitleView.layer.anchorPoint = CGPoint()
|
||||||
|
self.extractedContainerNode.contentNode.view.addSubview(authorTitleView)
|
||||||
|
}
|
||||||
|
transition.setPosition(view: authorTitleView, position: authorTitleFrame.origin)
|
||||||
|
authorTitleView.bounds = CGRect(origin: CGPoint(), size: authorTitleFrame.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
var textFrame = CGRect(origin: CGPoint(x: insets.left + avatarSize + avatarSpacing, y: avatarFrame.minY + 3.0), size: textSize)
|
||||||
|
if component.message.isFromAdmin {
|
||||||
|
textFrame.origin.y = authorTitleFrame.maxY
|
||||||
|
textFrame.size.width = max(textFrame.width, authorTitleFrame.maxX - textFrame.minX)
|
||||||
|
textFrame.size.height = max(textFrame.height, authorTitleFrame.height)
|
||||||
|
}
|
||||||
|
textFrame.size.width = max(textFrame.width, textTopLeftCutout + (textBottomRightCutout ?? 0.0))
|
||||||
if let textView = self.text.view {
|
if let textView = self.text.view {
|
||||||
if textView.superview == nil {
|
if textView.superview == nil {
|
||||||
textView.layer.anchorPoint = CGPoint()
|
textView.layer.anchorPoint = CGPoint()
|
||||||
self.extractedContainerNode.contentNode.view.addSubview(textView)
|
self.extractedContainerNode.contentNode.view.addSubview(textView)
|
||||||
}
|
}
|
||||||
transition.setPosition(view: textView, position: textFrame.origin)
|
transition.setPosition(view: textView, position: textFrame.origin)
|
||||||
textView.bounds = CGRect(origin: CGPoint(), size: textFrame.size)
|
textView.bounds = CGRect(origin: CGPoint(), size: textSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let crownIcon = self.crownIcon, let image = crownIcon.image {
|
if let crownIcon = self.crownIcon, let image = crownIcon.image {
|
||||||
crownIcon.frame = CGRect(origin: CGPoint(x: textFrame.minX, y: textFrame.minY - 1.0), size: image.size)
|
crownIcon.frame = CGRect(origin: CGPoint(x: authorTitleFrame.minX - 4.0 - image.size.width, y: authorTitleFrame.minY - 1.0), size: image.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
let backgroundOrigin = CGPoint(x: avatarFrame.minX - avatarBackgroundInset, y: avatarFrame.minY - avatarBackgroundInset)
|
let backgroundOrigin = CGPoint(x: avatarFrame.minX - avatarBackgroundInset, y: avatarFrame.minY - avatarBackgroundInset)
|
||||||
@ -344,8 +412,11 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
if let starsAmountTextSize, displayStarsAmountBackground {
|
if let starsAmountTextSize, displayStarsAmountBackground {
|
||||||
backgroundFrame.size.width += starsAmountTextSize.width + 30.0
|
backgroundFrame.size.width += starsAmountTextSize.width + 30.0
|
||||||
}
|
}
|
||||||
|
if let adminBadgeTextSize {
|
||||||
|
backgroundFrame.size.width = max(backgroundFrame.width, authorTitleFrame.maxX + 4.0 + adminBadgeTextSize.width + 10.0)
|
||||||
|
}
|
||||||
if let textLayout = self.textExternal.layout {
|
if let textLayout = self.textExternal.layout {
|
||||||
if textLayout.numberOfLines > 1 {
|
if textLayout.numberOfLines > 1 || (component.message.isFromAdmin && !displayStarsAmountBackground) {
|
||||||
backgroundFrame.size.height = max(backgroundFrame.size.height, textFrame.maxY + 8.0 - backgroundOrigin.y)
|
backgroundFrame.size.height = max(backgroundFrame.size.height, textFrame.maxY + 8.0 - backgroundOrigin.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,7 +451,14 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
|
|
||||||
let backgroundCornerRadius = (avatarSize + avatarBackgroundInset * 2.0) * 0.5
|
let backgroundCornerRadius = (avatarSize + avatarBackgroundInset * 2.0) * 0.5
|
||||||
|
|
||||||
if let paidStars = component.message.paidStars, let baseColor = GroupCallMessagesContext.getStarAmountParamMapping(params: LiveChatMessageParams(appConfig: component.context.currentAppConfiguration.with({ $0 })), value: paidStars).color {
|
var displayBackground = false
|
||||||
|
if component.message.paidStars != nil {
|
||||||
|
displayBackground = true
|
||||||
|
} else if component.message.isFromAdmin {
|
||||||
|
displayBackground = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if displayBackground {
|
||||||
let backgroundView: UIImageView
|
let backgroundView: UIImageView
|
||||||
if let current = self.backgroundView {
|
if let current = self.backgroundView {
|
||||||
backgroundView = current
|
backgroundView = current
|
||||||
@ -392,19 +470,30 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
}
|
}
|
||||||
transition.setFrame(view: backgroundView, frame: backgroundFrame)
|
transition.setFrame(view: backgroundView, frame: backgroundFrame)
|
||||||
|
|
||||||
backgroundView.tintColor = StoryLiveChatMessageComponent.getMessageColor(color: baseColor).withAlphaComponent(component.layout.transparentBackground ? 0.7 : 1.0)
|
if let paidStars = component.message.paidStars, let baseColor = GroupCallMessagesContext.getStarAmountParamMapping(params: LiveChatMessageParams(appConfig: component.context.currentAppConfiguration.with({ $0 })), value: paidStars).color {
|
||||||
|
backgroundView.tintColor = StoryLiveChatMessageComponent.getMessageColor(color: baseColor).withAlphaComponent(component.layout.transparentBackground ? 0.7 : 1.0)
|
||||||
let effectLayer: StarsParticleEffectLayer
|
|
||||||
if let current = self.effectLayer {
|
|
||||||
effectLayer = current
|
|
||||||
} else {
|
} else {
|
||||||
effectLayer = StarsParticleEffectLayer()
|
backgroundView.tintColor = UIColor(white: 0.0, alpha: 0.3)
|
||||||
self.effectLayer = effectLayer
|
|
||||||
backgroundView.layer.addSublayer(effectLayer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
transition.setFrame(layer: effectLayer, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
if component.message.paidStars != nil {
|
||||||
effectLayer.update(color: UIColor(white: 1.0, alpha: 0.5), size: backgroundFrame.size, cornerRadius: backgroundCornerRadius, transition: transition)
|
let effectLayer: StarsParticleEffectLayer
|
||||||
|
if let current = self.effectLayer {
|
||||||
|
effectLayer = current
|
||||||
|
} else {
|
||||||
|
effectLayer = StarsParticleEffectLayer()
|
||||||
|
self.effectLayer = effectLayer
|
||||||
|
backgroundView.layer.addSublayer(effectLayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
transition.setFrame(layer: effectLayer, frame: CGRect(origin: CGPoint(), size: backgroundFrame.size))
|
||||||
|
effectLayer.update(color: UIColor(white: 1.0, alpha: 0.5), size: backgroundFrame.size, cornerRadius: backgroundCornerRadius, transition: transition)
|
||||||
|
} else {
|
||||||
|
if let effectLayer = self.effectLayer {
|
||||||
|
self.effectLayer = nil
|
||||||
|
effectLayer.removeFromSuperlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if let backgroundView = self.backgroundView {
|
} else if let backgroundView = self.backgroundView {
|
||||||
self.backgroundView = nil
|
self.backgroundView = nil
|
||||||
backgroundView.removeFromSuperview()
|
backgroundView.removeFromSuperview()
|
||||||
@ -415,6 +504,14 @@ public final class StoryLiveChatMessageComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let adminBadgeTextView = self.adminBadgeText?.view, let adminBadgeTextSize {
|
||||||
|
let adminBadgeTextFrame = CGRect(origin: CGPoint(x: backgroundFrame.maxX - 10.0 - adminBadgeTextSize.width, y: backgroundFrame.minY + 9.0), size: adminBadgeTextSize)
|
||||||
|
if adminBadgeTextView.superview == nil {
|
||||||
|
self.extractedContainerNode.contentNode.view.addSubview(adminBadgeTextView)
|
||||||
|
}
|
||||||
|
transition.setFrame(view: adminBadgeTextView, frame: adminBadgeTextFrame)
|
||||||
|
}
|
||||||
|
|
||||||
let contentFrame = CGRect(origin: CGPoint(), size: size)
|
let contentFrame = CGRect(origin: CGPoint(), size: size)
|
||||||
transition.setPosition(view: self.contentContainer, position: contentFrame.center)
|
transition.setPosition(view: self.contentContainer, position: contentFrame.center)
|
||||||
transition.setBounds(view: self.contentContainer, bounds: CGRect(origin: CGPoint(), size: contentFrame.size))
|
transition.setBounds(view: self.contentContainer, bounds: CGRect(origin: CGPoint(), size: contentFrame.size))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user