mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Stories
This commit is contained in:
parent
3c16e9c215
commit
cb0a327dd9
@ -2019,6 +2019,11 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
tabsNode = value
|
tabsNode = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var effectiveStorySubscriptions: EngineStorySubscriptions?
|
||||||
|
if let controller = self.controller, let storySubscriptions = controller.orderedStorySubscriptions, shouldDisplayStoriesInChatListHeader(storySubscriptions: storySubscriptions, isHidden: controller.location == .chatList(groupId: .archive)) {
|
||||||
|
effectiveStorySubscriptions = controller.orderedStorySubscriptions
|
||||||
|
}
|
||||||
|
|
||||||
let navigationBarSize = self.navigationBarView.update(
|
let navigationBarSize = self.navigationBarView.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(ChatListNavigationBar(
|
component: AnyComponent(ChatListNavigationBar(
|
||||||
@ -2031,7 +2036,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
|||||||
primaryContent: headerContent?.primaryContent,
|
primaryContent: headerContent?.primaryContent,
|
||||||
secondaryContent: headerContent?.secondaryContent,
|
secondaryContent: headerContent?.secondaryContent,
|
||||||
secondaryTransition: self.inlineStackContainerTransitionFraction,
|
secondaryTransition: self.inlineStackContainerTransitionFraction,
|
||||||
storySubscriptions: self.controller?.orderedStorySubscriptions,
|
storySubscriptions: effectiveStorySubscriptions,
|
||||||
storiesIncludeHidden: self.location == .chatList(groupId: .archive),
|
storiesIncludeHidden: self.location == .chatList(groupId: .archive),
|
||||||
uploadProgress: self.controller?.storyUploadProgress,
|
uploadProgress: self.controller?.storyUploadProgress,
|
||||||
tabsNode: tabsNode,
|
tabsNode: tabsNode,
|
||||||
@ -2685,8 +2690,10 @@ func shouldDisplayStoriesInChatListHeader(storySubscriptions: EngineStorySubscri
|
|||||||
if !storySubscriptions.items.isEmpty {
|
if !storySubscriptions.items.isEmpty {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if !isHidden, let _ = storySubscriptions.accountItem {
|
if !isHidden, let accountItem = storySubscriptions.accountItem {
|
||||||
return true
|
if accountItem.hasPending || accountItem.storyCount != 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -557,7 +557,9 @@ public final class TextNodeLayout: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if index >= 0 && index < attributedString.length {
|
if index >= 0 && index < attributedString.length {
|
||||||
return (index, attributedString.attributes(at: index, effectiveRange: nil))
|
if index < line.range.location + line.range.length {
|
||||||
|
return (index, attributedString.attributes(at: index, effectiveRange: nil))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -632,7 +634,9 @@ public final class TextNodeLayout: NSObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if index >= 0 && index < attributedString.length {
|
if index >= 0 && index < attributedString.length {
|
||||||
return (index, attributedString.attributes(at: index, effectiveRange: nil))
|
if index < line.range.location + line.range.length {
|
||||||
|
return (index, attributedString.attributes(at: index, effectiveRange: nil))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1250,7 +1254,9 @@ open class TextNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
let truncationToken = CTLineCreateWithAttributedString(truncatedTokenString)
|
let truncationToken = CTLineCreateWithAttributedString(truncatedTokenString)
|
||||||
|
|
||||||
if CTLineGetTypographicBounds(originalLine, nil, nil, nil) - CTLineGetTrailingWhitespaceWidth(originalLine) < Double(lineConstrainedSize.width) {
|
var effectiveLineRange = brokenLineRange
|
||||||
|
|
||||||
|
if lineRange.length == 0 || CTLineGetTypographicBounds(originalLine, nil, nil, nil) - CTLineGetTrailingWhitespaceWidth(originalLine) < Double(lineConstrainedSize.width) {
|
||||||
if didClipLinebreak {
|
if didClipLinebreak {
|
||||||
let mergedLine = NSMutableAttributedString()
|
let mergedLine = NSMutableAttributedString()
|
||||||
mergedLine.append(attributedString.attributedSubstring(from: NSRange(location: lineRange.location, length: lineRange.length)))
|
mergedLine.append(attributedString.attributedSubstring(from: NSRange(location: lineRange.location, length: lineRange.length)))
|
||||||
@ -1269,6 +1275,7 @@ open class TextNode: ASDisplayNode {
|
|||||||
if brokenLineRange.location + brokenLineRange.length > attributedString.length {
|
if brokenLineRange.location + brokenLineRange.length > attributedString.length {
|
||||||
brokenLineRange.length = attributedString.length - brokenLineRange.location
|
brokenLineRange.length = attributedString.length - brokenLineRange.location
|
||||||
}
|
}
|
||||||
|
effectiveLineRange = brokenLineRange
|
||||||
|
|
||||||
truncated = true
|
truncated = true
|
||||||
} else {
|
} else {
|
||||||
@ -1284,9 +1291,24 @@ open class TextNode: ASDisplayNode {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if customTruncationToken != nil {
|
||||||
|
assert(true)
|
||||||
|
}
|
||||||
|
effectiveLineRange = CFRange(location: effectiveLineRange.location, length: 0)
|
||||||
|
for run in runs {
|
||||||
|
let runRange = CTRunGetStringRange(run)
|
||||||
|
if runRange.location + runRange.length > brokenLineRange.location + brokenLineRange.length {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
effectiveLineRange.length = max(effectiveLineRange.length, (runRange.location + runRange.length) - effectiveLineRange.location)
|
||||||
|
}
|
||||||
|
|
||||||
if brokenLineRange.location + brokenLineRange.length > attributedString.length {
|
if brokenLineRange.location + brokenLineRange.length > attributedString.length {
|
||||||
brokenLineRange.length = attributedString.length - brokenLineRange.location
|
brokenLineRange.length = attributedString.length - brokenLineRange.location
|
||||||
}
|
}
|
||||||
|
if effectiveLineRange.location + effectiveLineRange.length > attributedString.length {
|
||||||
|
effectiveLineRange.length = attributedString.length - effectiveLineRange.location
|
||||||
|
}
|
||||||
truncated = true
|
truncated = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1369,7 +1391,7 @@ open class TextNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.append(TextNodeLine(line: coreTextLine, frame: lineFrame, range: NSMakeRange(lineRange.location, lineRange.length), isRTL: isRTL, strikethroughs: strikethroughs, spoilers: spoilers, spoilerWords: spoilerWords, embeddedItems: embeddedItems, attachments: attachments))
|
lines.append(TextNodeLine(line: coreTextLine, frame: lineFrame, range: NSMakeRange(effectiveLineRange.location, effectiveLineRange.length), isRTL: isRTL, strikethroughs: strikethroughs, spoilers: spoilers, spoilerWords: spoilerWords, embeddedItems: embeddedItems, attachments: attachments))
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
if lineCharacterCount > 0 {
|
if lineCharacterCount > 0 {
|
||||||
|
@ -40,6 +40,14 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class InternalTransitionHint {
|
||||||
|
let bounceScrolling: Bool
|
||||||
|
|
||||||
|
init(bounceScrolling: Bool) {
|
||||||
|
self.bounceScrolling = bounceScrolling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let externalState: ExternalState
|
let externalState: ExternalState
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let strings: PresentationStrings
|
let strings: PresentationStrings
|
||||||
@ -107,17 +115,18 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ContentItem {
|
private final class ContentItem: UIView {
|
||||||
var textNode: TextNodeWithEntities?
|
var textNode: TextNodeWithEntities?
|
||||||
var spoilerTextNode: TextNodeWithEntities?
|
var spoilerTextNode: TextNodeWithEntities?
|
||||||
var linkHighlightingNode: LinkHighlightingNode?
|
var linkHighlightingNode: LinkHighlightingNode?
|
||||||
var dustNode: InvisibleInkDustNode?
|
var dustNode: InvisibleInkDustNode?
|
||||||
|
|
||||||
init() {
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
func update() {
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,8 +202,8 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
], locations: [0.0, 1.0]))
|
], locations: [0.0, 1.0]))
|
||||||
self.scrollMaskContainer.addSubview(self.scrollTopMaskView)
|
self.scrollMaskContainer.addSubview(self.scrollTopMaskView)
|
||||||
|
|
||||||
self.collapsedText = ContentItem()
|
self.collapsedText = ContentItem(frame: CGRect())
|
||||||
self.expandedText = ContentItem()
|
self.expandedText = ContentItem(frame: CGRect())
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
@ -204,6 +213,9 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
self.scrollView.delegate = self
|
self.scrollView.delegate = self
|
||||||
self.addSubview(self.scrollViewContainer)
|
self.addSubview(self.scrollViewContainer)
|
||||||
|
|
||||||
|
self.scrollView.addSubview(self.collapsedText)
|
||||||
|
self.scrollView.addSubview(self.expandedText)
|
||||||
|
|
||||||
self.scrollViewContainer.mask = self.scrollMaskContainer
|
self.scrollViewContainer.mask = self.scrollMaskContainer
|
||||||
|
|
||||||
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
|
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
|
||||||
@ -247,18 +259,37 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
|
|
||||||
func expand(transition: Transition) {
|
func expand(transition: Transition) {
|
||||||
self.ignoreScrolling = true
|
self.ignoreScrolling = true
|
||||||
transition.setBounds(view: self.scrollView, bounds: CGRect(origin: CGPoint(x: 0.0, y: max(0.0, self.scrollView.contentSize.height - self.scrollView.bounds.height)), size: self.scrollView.bounds.size))
|
if let textNode = self.expandedText.textNode?.textNode {
|
||||||
|
var offset = textNode.frame.minY - 8.0
|
||||||
|
offset = max(0.0, offset)
|
||||||
|
offset = min(self.scrollView.contentSize.height - self.scrollView.bounds.height, offset)
|
||||||
|
if transition.animation.isImmediate {
|
||||||
|
transition.setBounds(view: self.scrollView, bounds: CGRect(origin: CGPoint(x: 0.0, y: offset), size: self.scrollView.bounds.size))
|
||||||
|
} else {
|
||||||
|
let offsetDifference = -offset + self.scrollView.bounds.minY
|
||||||
|
self.scrollView.bounds = CGRect(origin: CGPoint(x: 0.0, y: offset), size: self.scrollView.bounds.size)
|
||||||
|
self.scrollView.layer.animateSpring(from: offsetDifference as NSNumber, to: 0.0 as NSNumber, keyPath: "bounds.origin.y", duration: 0.5, damping: 120.0, additive: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
self.ignoreScrolling = false
|
self.ignoreScrolling = false
|
||||||
|
|
||||||
self.updateScrolling(transition: transition)
|
self.updateScrolling(transition: transition.withUserData(InternalTransitionHint(bounceScrolling: true)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func collapse(transition: Transition) {
|
func collapse(transition: Transition) {
|
||||||
self.ignoreScrolling = true
|
self.ignoreScrolling = true
|
||||||
transition.setBounds(view: self.scrollView, bounds: CGRect(origin: CGPoint(), size: self.scrollView.bounds.size))
|
|
||||||
|
if transition.animation.isImmediate {
|
||||||
|
transition.setBounds(view: self.scrollView, bounds: CGRect(origin: CGPoint(), size: self.scrollView.bounds.size))
|
||||||
|
} else {
|
||||||
|
let offsetDifference = self.scrollView.bounds.minY
|
||||||
|
self.scrollView.bounds = CGRect(origin: CGPoint(), size: self.scrollView.bounds.size)
|
||||||
|
self.scrollView.layer.animateSpring(from: offsetDifference as NSNumber, to: 0.0 as NSNumber, keyPath: "bounds.origin.y", duration: 0.5, damping: 120.0, additive: true)
|
||||||
|
}
|
||||||
|
|
||||||
self.ignoreScrolling = false
|
self.ignoreScrolling = false
|
||||||
|
|
||||||
self.updateScrolling(transition: transition)
|
self.updateScrolling(transition: transition.withUserData(InternalTransitionHint(bounceScrolling: true)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateScrolling(transition: Transition) {
|
private func updateScrolling(transition: Transition) {
|
||||||
@ -266,6 +297,11 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bounce = false
|
||||||
|
if let internalTransitionHint = transition.userData(InternalTransitionHint.self) {
|
||||||
|
bounce = internalTransitionHint.bounceScrolling
|
||||||
|
}
|
||||||
|
|
||||||
var edgeDistance = self.scrollView.contentSize.height - self.scrollView.bounds.maxY
|
var edgeDistance = self.scrollView.contentSize.height - self.scrollView.bounds.maxY
|
||||||
edgeDistance = max(0.0, min(7.0, edgeDistance))
|
edgeDistance = max(0.0, min(7.0, edgeDistance))
|
||||||
|
|
||||||
@ -274,7 +310,17 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
|
|
||||||
let shadowOverflow: CGFloat = 58.0
|
let shadowOverflow: CGFloat = 58.0
|
||||||
let shadowFrame = CGRect(origin: CGPoint(x: 0.0, y: -self.scrollView.contentOffset.y + itemLayout.containerSize.height - itemLayout.visibleTextHeight - itemLayout.verticalInset - shadowOverflow), size: CGSize(width: itemLayout.containerSize.width, height: itemLayout.visibleTextHeight + itemLayout.verticalInset + shadowOverflow))
|
let shadowFrame = CGRect(origin: CGPoint(x: 0.0, y: -self.scrollView.contentOffset.y + itemLayout.containerSize.height - itemLayout.visibleTextHeight - itemLayout.verticalInset - shadowOverflow), size: CGSize(width: itemLayout.containerSize.width, height: itemLayout.visibleTextHeight + itemLayout.verticalInset + shadowOverflow))
|
||||||
transition.setFrame(view: self.shadowGradientView, frame: CGRect(origin: CGPoint(x: shadowFrame.minX, y: shadowFrame.minY), size: CGSize(width: shadowFrame.width, height: self.scrollView.contentSize.height + 1000.0)))
|
|
||||||
|
let shadowGradientFrame = CGRect(origin: CGPoint(x: shadowFrame.minX, y: shadowFrame.minY), size: CGSize(width: shadowFrame.width, height: self.scrollView.contentSize.height + 1000.0))
|
||||||
|
if self.shadowGradientView.frame != shadowGradientFrame {
|
||||||
|
if bounce, !transition.animation.isImmediate {
|
||||||
|
let offsetDifference = -shadowGradientFrame.minY + self.shadowGradientView.frame.minY
|
||||||
|
self.shadowGradientView.frame = shadowGradientFrame
|
||||||
|
self.shadowGradientView.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: 0.0, y: offsetDifference)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, damping: 120.0, additive: true)
|
||||||
|
} else {
|
||||||
|
transition.setFrame(view: self.shadowGradientView, frame: shadowGradientFrame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let expandDistance: CGFloat = 50.0
|
let expandDistance: CGFloat = 50.0
|
||||||
var expandFraction: CGFloat = self.scrollView.contentOffset.y / expandDistance
|
var expandFraction: CGFloat = self.scrollView.contentOffset.y / expandDistance
|
||||||
@ -295,6 +341,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
|
|
||||||
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
@objc func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
||||||
let contentItem = self.isExpanded ? self.expandedText : self.collapsedText
|
let contentItem = self.isExpanded ? self.expandedText : self.collapsedText
|
||||||
|
let otherContentItem = !self.isExpanded ? self.expandedText : self.collapsedText
|
||||||
|
|
||||||
switch recognizer.state {
|
switch recognizer.state {
|
||||||
case .ended:
|
case .ended:
|
||||||
@ -306,6 +353,8 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
if case .tap = gesture, let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)], !(contentItem.dustNode?.isRevealed ?? true) {
|
if case .tap = gesture, let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)], !(contentItem.dustNode?.isRevealed ?? true) {
|
||||||
let convertedPoint = recognizer.view?.convert(location, to: contentItem.dustNode?.view) ?? location
|
let convertedPoint = recognizer.view?.convert(location, to: contentItem.dustNode?.view) ?? location
|
||||||
contentItem.dustNode?.revealAtLocation(convertedPoint)
|
contentItem.dustNode?.revealAtLocation(convertedPoint)
|
||||||
|
otherContentItem.dustNode?.revealAtLocation(convertedPoint)
|
||||||
|
self.state?.updated(transition: Transition(animation: .curve(duration: 0.2, curve: .easeInOut)))
|
||||||
return
|
return
|
||||||
} else if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
} else if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String {
|
||||||
var concealed = true
|
var concealed = true
|
||||||
@ -344,6 +393,14 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if case .tap = gesture {
|
||||||
|
if self.isExpanded {
|
||||||
|
self.collapse(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)))
|
||||||
|
} else {
|
||||||
|
self.expand(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +449,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
linkHighlightingNode = LinkHighlightingNode(color: UIColor(white: 1.0, alpha: 0.5))
|
linkHighlightingNode = LinkHighlightingNode(color: UIColor(white: 1.0, alpha: 0.5))
|
||||||
contentItem.linkHighlightingNode = linkHighlightingNode
|
contentItem.linkHighlightingNode = linkHighlightingNode
|
||||||
self.scrollView.insertSubview(linkHighlightingNode.view, belowSubview: textNode.textNode.view)
|
contentItem.insertSubview(linkHighlightingNode.view, belowSubview: textNode.textNode.view)
|
||||||
}
|
}
|
||||||
linkHighlightingNode.frame = textNode.textNode.view.frame
|
linkHighlightingNode.frame = textNode.textNode.view.frame
|
||||||
linkHighlightingNode.updateRects(rects)
|
linkHighlightingNode.updateRects(rects)
|
||||||
@ -438,30 +495,32 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
attributedString: attributedText,
|
attributedString: attributedText,
|
||||||
maximumNumberOfLines: 3,
|
maximumNumberOfLines: 3,
|
||||||
truncationType: .end,
|
truncationType: .end,
|
||||||
constrainedSize: textContainerSize,
|
constrainedSize: CGSize(width: textContainerSize.width, height: 10000.0),
|
||||||
textShadowColor: UIColor(white: 0.0, alpha: 0.25),
|
textShadowColor: UIColor(white: 0.0, alpha: 0.25),
|
||||||
textShadowBlur: 4.0,
|
textShadowBlur: 4.0,
|
||||||
|
displaySpoilers: false,
|
||||||
customTruncationToken: truncationToken
|
customTruncationToken: truncationToken
|
||||||
))
|
))
|
||||||
let expandedTextLayout = TextNodeWithEntities.asyncLayout(self.expandedText.textNode)(TextNodeLayoutArguments(
|
let expandedTextLayout = TextNodeWithEntities.asyncLayout(self.expandedText.textNode)(TextNodeLayoutArguments(
|
||||||
attributedString: attributedText,
|
attributedString: attributedText,
|
||||||
maximumNumberOfLines: 0,
|
maximumNumberOfLines: 0,
|
||||||
truncationType: .end,
|
truncationType: .end,
|
||||||
constrainedSize: textContainerSize,
|
constrainedSize: CGSize(width: textContainerSize.width, height: 10000.0),
|
||||||
textShadowColor: UIColor(white: 0.0, alpha: 0.25),
|
textShadowColor: UIColor(white: 0.0, alpha: 0.25),
|
||||||
textShadowBlur: 4.0
|
textShadowBlur: 4.0,
|
||||||
|
displaySpoilers: false
|
||||||
))
|
))
|
||||||
|
|
||||||
let collapsedSpoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
let collapsedSpoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
||||||
if !collapsedTextLayout.0.spoilers.isEmpty {
|
if !collapsedTextLayout.0.spoilers.isEmpty {
|
||||||
collapsedSpoilerTextLayoutAndApply = TextNodeWithEntities.asyncLayout(self.collapsedText.spoilerTextNode)(TextNodeLayoutArguments(attributedString: attributedText, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textContainerSize, textShadowColor: UIColor(white: 0.0, alpha: 0.25), textShadowBlur: 4.0, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true))
|
collapsedSpoilerTextLayoutAndApply = TextNodeWithEntities.asyncLayout(self.collapsedText.spoilerTextNode)(TextNodeLayoutArguments(attributedString: attributedText, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: textContainerSize.width, height: 10000.0), textShadowColor: UIColor(white: 0.0, alpha: 0.25), textShadowBlur: 4.0, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true))
|
||||||
} else {
|
} else {
|
||||||
collapsedSpoilerTextLayoutAndApply = nil
|
collapsedSpoilerTextLayoutAndApply = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let expandedSpoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
let expandedSpoilerTextLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
||||||
if !expandedTextLayout.0.spoilers.isEmpty {
|
if !expandedTextLayout.0.spoilers.isEmpty {
|
||||||
expandedSpoilerTextLayoutAndApply = TextNodeWithEntities.asyncLayout(self.expandedText.spoilerTextNode)(TextNodeLayoutArguments(attributedString: attributedText, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textContainerSize, textShadowColor: UIColor(white: 0.0, alpha: 0.25), textShadowBlur: 4.0, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true))
|
expandedSpoilerTextLayoutAndApply = TextNodeWithEntities.asyncLayout(self.expandedText.spoilerTextNode)(TextNodeLayoutArguments(attributedString: attributedText, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: textContainerSize.width, height: 10000.0), textShadowColor: UIColor(white: 0.0, alpha: 0.25), textShadowBlur: 4.0, displaySpoilers: true, displayEmbeddedItemsUnderSpoilers: true))
|
||||||
} else {
|
} else {
|
||||||
expandedSpoilerTextLayoutAndApply = nil
|
expandedSpoilerTextLayoutAndApply = nil
|
||||||
}
|
}
|
||||||
@ -481,9 +540,11 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
if self.collapsedText.textNode !== collapsedTextNode {
|
if self.collapsedText.textNode !== collapsedTextNode {
|
||||||
self.collapsedText.textNode?.textNode.view.removeFromSuperview()
|
self.collapsedText.textNode?.textNode.view.removeFromSuperview()
|
||||||
|
|
||||||
|
collapsedTextNode.textNode.displaysAsynchronously = false
|
||||||
|
|
||||||
self.collapsedText.textNode = collapsedTextNode
|
self.collapsedText.textNode = collapsedTextNode
|
||||||
if collapsedTextNode.textNode.view.superview == nil {
|
if collapsedTextNode.textNode.view.superview == nil {
|
||||||
self.scrollView.addSubview(collapsedTextNode.textNode.view)
|
self.collapsedText.addSubview(collapsedTextNode.textNode.view)
|
||||||
|
|
||||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
||||||
recognizer.tapActionAtPoint = { point in
|
recognizer.tapActionAtPoint = { point in
|
||||||
@ -518,7 +579,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
collapsedSpoilerTextNode.textNode.contentMode = .topLeft
|
collapsedSpoilerTextNode.textNode.contentMode = .topLeft
|
||||||
collapsedSpoilerTextNode.textNode.contentsScale = UIScreenScale
|
collapsedSpoilerTextNode.textNode.contentsScale = UIScreenScale
|
||||||
collapsedSpoilerTextNode.textNode.displaysAsynchronously = false
|
collapsedSpoilerTextNode.textNode.displaysAsynchronously = false
|
||||||
self.scrollView.insertSubview(collapsedSpoilerTextNode.textNode.view, belowSubview: collapsedTextNode.textNode.view)
|
self.collapsedText.insertSubview(collapsedSpoilerTextNode.textNode.view, belowSubview: collapsedTextNode.textNode.view)
|
||||||
|
|
||||||
collapsedSpoilerTextNode.visibilityRect = CGRect(origin: CGPoint(), size: CGSize(width: 100000.0, height: 100000.0))
|
collapsedSpoilerTextNode.visibilityRect = CGRect(origin: CGPoint(), size: CGSize(width: 100000.0, height: 100000.0))
|
||||||
|
|
||||||
@ -533,7 +594,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
collapsedDustNode = InvisibleInkDustNode(textNode: collapsedSpoilerTextNode.textNode, enableAnimations: component.context.sharedContext.energyUsageSettings.fullTranslucency)
|
collapsedDustNode = InvisibleInkDustNode(textNode: collapsedSpoilerTextNode.textNode, enableAnimations: component.context.sharedContext.energyUsageSettings.fullTranslucency)
|
||||||
self.collapsedText.dustNode = collapsedDustNode
|
self.collapsedText.dustNode = collapsedDustNode
|
||||||
self.scrollView.insertSubview(collapsedDustNode.view, aboveSubview: collapsedSpoilerTextNode.textNode.view)
|
self.collapsedText.insertSubview(collapsedDustNode.view, aboveSubview: collapsedSpoilerTextNode.textNode.view)
|
||||||
}
|
}
|
||||||
collapsedDustNode.frame = collapsedTextFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 0.0)
|
collapsedDustNode.frame = collapsedTextFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 0.0)
|
||||||
collapsedDustNode.update(size: collapsedDustNode.frame.size, color: .white, textColor: .white, rects: collapsedTextLayout.0.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: collapsedTextLayout.0.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
|
collapsedDustNode.update(size: collapsedDustNode.frame.size, color: .white, textColor: .white, rects: collapsedTextLayout.0.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: collapsedTextLayout.0.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
|
||||||
@ -561,7 +622,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
|
|
||||||
self.expandedText.textNode = expandedTextNode
|
self.expandedText.textNode = expandedTextNode
|
||||||
if expandedTextNode.textNode.view.superview == nil {
|
if expandedTextNode.textNode.view.superview == nil {
|
||||||
self.scrollView.addSubview(expandedTextNode.textNode.view)
|
self.expandedText.addSubview(expandedTextNode.textNode.view)
|
||||||
|
|
||||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
||||||
recognizer.tapActionAtPoint = { point in
|
recognizer.tapActionAtPoint = { point in
|
||||||
@ -596,7 +657,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
expandedSpoilerTextNode.textNode.contentMode = .topLeft
|
expandedSpoilerTextNode.textNode.contentMode = .topLeft
|
||||||
expandedSpoilerTextNode.textNode.contentsScale = UIScreenScale
|
expandedSpoilerTextNode.textNode.contentsScale = UIScreenScale
|
||||||
expandedSpoilerTextNode.textNode.displaysAsynchronously = false
|
expandedSpoilerTextNode.textNode.displaysAsynchronously = false
|
||||||
self.scrollView.insertSubview(expandedSpoilerTextNode.textNode.view, belowSubview: expandedTextNode.textNode.view)
|
self.expandedText.insertSubview(expandedSpoilerTextNode.textNode.view, belowSubview: expandedTextNode.textNode.view)
|
||||||
|
|
||||||
expandedSpoilerTextNode.visibilityRect = CGRect(origin: CGPoint(), size: CGSize(width: 100000.0, height: 100000.0))
|
expandedSpoilerTextNode.visibilityRect = CGRect(origin: CGPoint(), size: CGSize(width: 100000.0, height: 100000.0))
|
||||||
|
|
||||||
@ -611,7 +672,7 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
expandedDustNode = InvisibleInkDustNode(textNode: expandedSpoilerTextNode.textNode, enableAnimations: component.context.sharedContext.energyUsageSettings.fullTranslucency)
|
expandedDustNode = InvisibleInkDustNode(textNode: expandedSpoilerTextNode.textNode, enableAnimations: component.context.sharedContext.energyUsageSettings.fullTranslucency)
|
||||||
self.expandedText.dustNode = expandedDustNode
|
self.expandedText.dustNode = expandedDustNode
|
||||||
self.scrollView.insertSubview(expandedDustNode.view, aboveSubview: expandedSpoilerTextNode.textNode.view)
|
self.expandedText.insertSubview(expandedDustNode.view, aboveSubview: expandedSpoilerTextNode.textNode.view)
|
||||||
}
|
}
|
||||||
expandedDustNode.frame = expandedTextFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 0.0)
|
expandedDustNode.frame = expandedTextFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 0.0)
|
||||||
expandedDustNode.update(size: expandedDustNode.frame.size, color: .white, textColor: .white, rects: expandedTextLayout.0.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: expandedTextLayout.0.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
|
expandedDustNode.update(size: expandedDustNode.frame.size, color: .white, textColor: .white, rects: expandedTextLayout.0.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: expandedTextLayout.0.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
|
||||||
@ -680,25 +741,35 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
isExpandedTransition = transition.withAnimation(.curve(duration: 0.25, curve: .easeInOut))
|
isExpandedTransition = transition.withAnimation(.curve(duration: 0.25, curve: .easeInOut))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let textNode = self.collapsedText.textNode {
|
isExpandedTransition.setAlpha(view: self.collapsedText, alpha: self.isExpanded ? 0.0 : 1.0)
|
||||||
isExpandedTransition.setAlpha(view: textNode.textNode.view, alpha: self.isExpanded ? 0.0 : 1.0)
|
isExpandedTransition.setAlpha(view: self.expandedText, alpha: !self.isExpanded ? 0.0 : 1.0)
|
||||||
}
|
|
||||||
if let spoilerTextNode = self.collapsedText.spoilerTextNode {
|
/*if let spoilerTextNode = self.collapsedText.spoilerTextNode {
|
||||||
isExpandedTransition.setAlpha(view: spoilerTextNode.textNode.view, alpha: self.isExpanded ? 0.0 : 1.0)
|
var spoilerAlpha = self.isExpanded ? 0.0 : 1.0
|
||||||
|
if let dustNode = self.collapsedText.dustNode, dustNode.isRevealed {
|
||||||
|
} else {
|
||||||
|
spoilerAlpha = 0.0
|
||||||
|
}
|
||||||
|
isExpandedTransition.setAlpha(view: spoilerTextNode.textNode.view, alpha: spoilerAlpha)
|
||||||
}
|
}
|
||||||
if let dustNode = self.collapsedText.dustNode {
|
if let dustNode = self.collapsedText.dustNode {
|
||||||
isExpandedTransition.setAlpha(view: dustNode.view, alpha: self.isExpanded ? 0.0 : 1.0)
|
isExpandedTransition.setAlpha(view: dustNode.view, alpha: self.isExpanded ? 0.0 : 1.0)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if let textNode = self.expandedText.textNode {
|
/*if let textNode = self.expandedText.textNode {
|
||||||
isExpandedTransition.setAlpha(view: textNode.textNode.view, alpha: !self.isExpanded ? 0.0 : 1.0)
|
isExpandedTransition.setAlpha(view: textNode.textNode.view, alpha: !self.isExpanded ? 0.0 : 1.0)
|
||||||
}
|
}
|
||||||
if let spoilerTextNode = self.expandedText.spoilerTextNode {
|
if let spoilerTextNode = self.expandedText.spoilerTextNode {
|
||||||
isExpandedTransition.setAlpha(view: spoilerTextNode.textNode.view, alpha: !self.isExpanded ? 0.0 : 1.0)
|
var spoilerAlpha = !self.isExpanded ? 0.0 : 1.0
|
||||||
|
if let dustNode = self.expandedText.dustNode, dustNode.isRevealed {
|
||||||
|
} else {
|
||||||
|
spoilerAlpha = 0.0
|
||||||
|
}
|
||||||
|
isExpandedTransition.setAlpha(view: spoilerTextNode.textNode.view, alpha: spoilerAlpha)
|
||||||
}
|
}
|
||||||
if let dustNode = self.expandedText.dustNode {
|
if let dustNode = self.expandedText.dustNode {
|
||||||
isExpandedTransition.setAlpha(view: dustNode.view, alpha: !self.isExpanded ? 0.0 : 1.0)
|
isExpandedTransition.setAlpha(view: dustNode.view, alpha: !self.isExpanded ? 0.0 : 1.0)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
isExpandedTransition.setAlpha(view: self.shadowGradientView, alpha: self.isExpanded ? 0.0 : 1.0)
|
isExpandedTransition.setAlpha(view: self.shadowGradientView, alpha: self.isExpanded ? 0.0 : 1.0)
|
||||||
|
|
||||||
|
@ -3321,7 +3321,16 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
guard let navigationController = controller.navigationController as? NavigationController else {
|
guard let navigationController = controller.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if subject != nil || chat {
|
|
||||||
|
var chat = chat
|
||||||
|
switch peer {
|
||||||
|
case .channel, .legacyGroup:
|
||||||
|
chat = true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if subject != nil || chat {
|
||||||
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peer), subject: subject, keepStack: .always, animated: true, pushController: { [weak controller, weak navigationController] chatController, animated, completion in
|
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: component.context, chatLocation: .peer(peer), subject: subject, keepStack: .always, animated: true, pushController: { [weak controller, weak navigationController] chatController, animated, completion in
|
||||||
guard let controller, let navigationController else {
|
guard let controller, let navigationController else {
|
||||||
return
|
return
|
||||||
|
Loading…
x
Reference in New Issue
Block a user