mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 17:30:12 +00:00
Various fixes
This commit is contained in:
parent
37002ab90d
commit
74af8d17e1
@ -3563,10 +3563,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
|||||||
headerNode = current
|
headerNode = current
|
||||||
switch transition.0 {
|
switch transition.0 {
|
||||||
case .immediate:
|
case .immediate:
|
||||||
headerNode.frame = headerFrame
|
headerNode.updateFrame(headerFrame, within: self.visibleSize)
|
||||||
case let .animated(duration, curve):
|
case let .animated(duration, curve):
|
||||||
let previousFrame = headerNode.frame
|
let previousFrame = headerNode.frame
|
||||||
headerNode.frame = headerFrame
|
headerNode.updateFrame(headerFrame, within: self.visibleSize)
|
||||||
var offset = headerFrame.minY - previousFrame.minY + transition.2
|
var offset = headerFrame.minY - previousFrame.minY + transition.2
|
||||||
if headerNode.isRotated {
|
if headerNode.isRotated {
|
||||||
offset = -offset
|
offset = -offset
|
||||||
|
|||||||
@ -141,4 +141,17 @@ open class ListViewItemHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
open func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
open func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateFrame(_ frame: CGRect, within containerSize: CGSize, updateFrame: Bool = true) {
|
||||||
|
if updateFrame {
|
||||||
|
self.frame = frame
|
||||||
|
}
|
||||||
|
if frame.maxY < 0.0 || frame.minY > containerSize.height {
|
||||||
|
} else {
|
||||||
|
self.updateAbsoluteRect(frame, within: containerSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -378,7 +378,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
|
|
||||||
let belowKeyboardOverlayLayout = layout
|
let belowKeyboardOverlayLayout = layout
|
||||||
var globalOverlayLayout = layout
|
var globalOverlayLayout = layout
|
||||||
globalOverlayLayout.inputHeight = nil
|
// globalOverlayLayout.inputHeight = nil
|
||||||
|
|
||||||
if let globalOverlayBelowKeyboardContainerParent = self.globalOverlayBelowKeyboardContainerParent {
|
if let globalOverlayBelowKeyboardContainerParent = self.globalOverlayBelowKeyboardContainerParent {
|
||||||
if globalOverlayBelowKeyboardContainerParent.view.superview != self.displayNode.view {
|
if globalOverlayBelowKeyboardContainerParent.view.superview != self.displayNode.view {
|
||||||
|
|||||||
@ -1014,11 +1014,15 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
func setupItem(_ item: UniversalVideoGalleryItem) {
|
func setupItem(_ item: UniversalVideoGalleryItem) {
|
||||||
if self.item?.content.id != item.content.id {
|
if self.item?.content.id != item.content.id {
|
||||||
func parseChapters(_ string: NSAttributedString) -> [MediaPlayerScrubbingChapter] {
|
func parseChapters(_ string: NSAttributedString) -> [MediaPlayerScrubbingChapter] {
|
||||||
|
var existingTimecodes = Set<Double>()
|
||||||
var timecodeRanges: [(NSRange, TelegramTimecode)] = []
|
var timecodeRanges: [(NSRange, TelegramTimecode)] = []
|
||||||
var lineRanges: [NSRange] = []
|
var lineRanges: [NSRange] = []
|
||||||
string.enumerateAttributes(in: NSMakeRange(0, string.length), options: [], using: { attributes, range, _ in
|
string.enumerateAttributes(in: NSMakeRange(0, string.length), options: [], using: { attributes, range, _ in
|
||||||
if let timecode = attributes[NSAttributedString.Key(TelegramTextAttributes.Timecode)] as? TelegramTimecode {
|
if let timecode = attributes[NSAttributedString.Key(TelegramTextAttributes.Timecode)] as? TelegramTimecode {
|
||||||
timecodeRanges.append((range, timecode))
|
if !existingTimecodes.contains(timecode.time) {
|
||||||
|
timecodeRanges.append((range, timecode))
|
||||||
|
existingTimecodes.insert(timecode.time)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
(string.string as NSString).enumerateSubstrings(in: NSMakeRange(0, string.length), options: .byLines, using: { _, range, _, _ in
|
(string.string as NSString).enumerateSubstrings(in: NSMakeRange(0, string.length), options: .byLines, using: { _, range, _, _ in
|
||||||
@ -1029,7 +1033,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
for (timecodeRange, timecode) in timecodeRanges {
|
for (timecodeRange, timecode) in timecodeRanges {
|
||||||
inner: for lineRange in lineRanges {
|
inner: for lineRange in lineRanges {
|
||||||
if lineRange.contains(timecodeRange.location) {
|
if lineRange.contains(timecodeRange.location) {
|
||||||
if lineRange.length > timecodeRange.length {
|
if lineRange.length > timecodeRange.length && timecodeRange.location < lineRange.location + 4 {
|
||||||
var title = ((string.string as NSString).substring(with: lineRange) as NSString).replacingCharacters(in: NSMakeRange(timecodeRange.location - lineRange.location, timecodeRange.length), with: "")
|
var title = ((string.string as NSString).substring(with: lineRange) as NSString).replacingCharacters(in: NSMakeRange(timecodeRange.location - lineRange.location, timecodeRange.length), with: "")
|
||||||
title = title.trimmingCharacters(in: .whitespacesAndNewlines).trimmingCharacters(in: .punctuationCharacters)
|
title = title.trimmingCharacters(in: .whitespacesAndNewlines).trimmingCharacters(in: .punctuationCharacters)
|
||||||
chapters.append(MediaPlayerScrubbingChapter(title: title, start: timecode.time))
|
chapters.append(MediaPlayerScrubbingChapter(title: title, start: timecode.time))
|
||||||
@ -1038,6 +1042,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapters
|
return chapters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -877,7 +877,7 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
let endPosition: CGFloat = max(startPosition, floor(backgroundFrame.width * CGFloat(chapter.start / duration)) - lineWidth / 2.0)
|
let endPosition: CGFloat = max(startPosition, floor(backgroundFrame.width * CGFloat(chapter.start / duration)) - lineWidth / 2.0)
|
||||||
let width = endPosition - startPosition
|
let width = endPosition - startPosition
|
||||||
if width < lineWidth * 2.0 {
|
if width < lineWidth * 0.5 {
|
||||||
previousChapterNode.frame = CGRect()
|
previousChapterNode.frame = CGRect()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
@ -602,7 +602,7 @@ public func makeDefaultDarkPresentationTheme(extendingThemeReference: Presentati
|
|||||||
)
|
)
|
||||||
|
|
||||||
let serviceMessage = PresentationThemeServiceMessage(
|
let serviceMessage = PresentationThemeServiceMessage(
|
||||||
components: PresentationThemeServiceMessageColor(withDefaultWallpaper: PresentationThemeServiceMessageColorComponents(fill: UIColor(rgb: 0x1f1f1f, alpha: 1.0), primaryText: UIColor(rgb: 0xffffff), linkHighlight: UIColor(rgb: 0xffffff, alpha: 0.12), scam: UIColor(rgb: 0xeb5545), dateFillStatic: UIColor(rgb: 0x000000, alpha: 0.6), dateFillFloating: UIColor(rgb: 0x000000, alpha: 0.2)), withCustomWallpaper: PresentationThemeServiceMessageColorComponents(fill: UIColor(rgb: 0x1f1f1f, alpha: 1.0), primaryText: UIColor(rgb: 0xffffff), linkHighlight: UIColor(rgb: 0xffffff, alpha: 0.12), scam: UIColor(rgb: 0xeb5545), dateFillStatic: UIColor(rgb: 0x000000, alpha: 0.6), dateFillFloating: UIColor(rgb: 0x000000, alpha: 0.2))),
|
components: PresentationThemeServiceMessageColor(withDefaultWallpaper: PresentationThemeServiceMessageColorComponents(fill: UIColor(rgb: 0x1f1f1f, alpha: 1.0), primaryText: UIColor(rgb: 0xffffff), linkHighlight: UIColor(rgb: 0xffffff, alpha: 0.12), scam: UIColor(rgb: 0xeb5545), dateFillStatic: UIColor(rgb: 0x000000, alpha: 0.2), dateFillFloating: UIColor(rgb: 0x000000, alpha: 0.2)), withCustomWallpaper: PresentationThemeServiceMessageColorComponents(fill: UIColor(rgb: 0x1f1f1f, alpha: 1.0), primaryText: UIColor(rgb: 0xffffff), linkHighlight: UIColor(rgb: 0xffffff, alpha: 0.12), scam: UIColor(rgb: 0xeb5545), dateFillStatic: UIColor(rgb: 0x000000, alpha: 0.2), dateFillFloating: UIColor(rgb: 0x000000, alpha: 0.2))),
|
||||||
unreadBarFillColor: UIColor(rgb: 0x1b1b1b),
|
unreadBarFillColor: UIColor(rgb: 0x1b1b1b),
|
||||||
unreadBarStrokeColor: UIColor(rgb: 0x1b1b1b),
|
unreadBarStrokeColor: UIColor(rgb: 0x1b1b1b),
|
||||||
unreadBarTextColor: UIColor(rgb: 0xffffff),
|
unreadBarTextColor: UIColor(rgb: 0xffffff),
|
||||||
|
|||||||
@ -740,7 +740,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.emptyNode = emptyNode
|
self.emptyNode = emptyNode
|
||||||
self.historyNodeContainer.supernode?.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer)
|
self.historyNodeContainer.supernode?.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer)
|
||||||
if let (size, insets) = self.validEmptyNodeLayout {
|
if let (size, insets) = self.validEmptyNodeLayout {
|
||||||
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, size: size, insets: insets, transition: .immediate)
|
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, backgroundNode: self.backgroundNode, size: size, insets: insets, transition: .immediate)
|
||||||
}
|
}
|
||||||
if animated {
|
if animated {
|
||||||
emptyNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
emptyNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||||
@ -1513,8 +1513,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
emptyNodeInsets.bottom += inputPanelsHeight
|
emptyNodeInsets.bottom += inputPanelsHeight
|
||||||
self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets)
|
self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets)
|
||||||
if let emptyNode = self.emptyNode, let emptyType = self.emptyType {
|
if let emptyNode = self.emptyNode, let emptyType = self.emptyType {
|
||||||
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: nil, size: contentBounds.size, insets: emptyNodeInsets, transition: transition)
|
emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: nil, backgroundNode: self.backgroundNode, size: contentBounds.size, insets: emptyNodeInsets, transition: transition)
|
||||||
transition.updateFrame(node: emptyNode, frame: contentBounds)
|
transition.updateFrame(node: emptyNode, frame: contentBounds)
|
||||||
|
emptyNode.update(rect: contentBounds, within: contentBounds.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentBottomInset: CGFloat = inputPanelsHeight + 4.0
|
var contentBottomInset: CGFloat = inputPanelsHeight + 4.0
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import LocalizedPeerData
|
|||||||
import TelegramStringFormatting
|
import TelegramStringFormatting
|
||||||
import AccountContext
|
import AccountContext
|
||||||
import ChatPresentationInterfaceState
|
import ChatPresentationInterfaceState
|
||||||
|
import WallpaperBackgroundNode
|
||||||
|
|
||||||
private protocol ChatEmptyNodeContent {
|
private protocol ChatEmptyNodeContent {
|
||||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize
|
func updateLayout(interfaceState: ChatPresentationInterfaceState, size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize
|
||||||
@ -789,6 +790,11 @@ final class ChatEmptyNode: ASDisplayNode {
|
|||||||
|
|
||||||
private let backgroundNode: NavigationBackgroundNode
|
private let backgroundNode: NavigationBackgroundNode
|
||||||
|
|
||||||
|
private var wallpaperBackgroundNode: WallpaperBackgroundNode?
|
||||||
|
private var backgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
|
|
||||||
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
private var currentTheme: PresentationTheme?
|
private var currentTheme: PresentationTheme?
|
||||||
private var currentStrings: PresentationStrings?
|
private var currentStrings: PresentationStrings?
|
||||||
|
|
||||||
@ -820,12 +826,21 @@ final class ChatEmptyNode: ASDisplayNode {
|
|||||||
let targetFrame = self.backgroundNode.frame
|
let targetFrame = self.backgroundNode.frame
|
||||||
let initialFrame = loadingNode.convert(loadingNode.progressFrame, to: self)
|
let initialFrame = loadingNode.convert(loadingNode.progressFrame, to: self)
|
||||||
|
|
||||||
|
let transition = ContainedViewLayoutTransition.animated(duration: duration, curve: .easeInOut)
|
||||||
self.backgroundNode.layer.animateFrame(from: initialFrame, to: targetFrame, duration: duration)
|
self.backgroundNode.layer.animateFrame(from: initialFrame, to: targetFrame, duration: duration)
|
||||||
self.backgroundNode.update(size: initialFrame.size, cornerRadius: initialFrame.size.width / 2.0, transition: .immediate)
|
self.backgroundNode.update(size: initialFrame.size, cornerRadius: initialFrame.size.width / 2.0, transition: .immediate)
|
||||||
self.backgroundNode.update(size: targetFrame.size, cornerRadius: targetCornerRadius, transition: .animated(duration: duration, curve: .easeInOut))
|
self.backgroundNode.update(size: targetFrame.size, cornerRadius: targetCornerRadius, transition: transition)
|
||||||
|
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
backgroundContent.layer.animateFrame(from: initialFrame, to: targetFrame, duration: duration)
|
||||||
|
backgroundContent.cornerRadius = initialFrame.size.width / 2.0
|
||||||
|
transition.updateCornerRadius(layer: backgroundContent.layer, cornerRadius: targetCornerRadius)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateLayout(interfaceState: ChatPresentationInterfaceState, emptyType: ChatHistoryNodeLoadState.EmptyType, loadingNode: ChatLoadingNode?, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
|
func updateLayout(interfaceState: ChatPresentationInterfaceState, emptyType: ChatHistoryNodeLoadState.EmptyType, loadingNode: ChatLoadingNode?, backgroundNode: WallpaperBackgroundNode?, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) {
|
||||||
|
self.wallpaperBackgroundNode = backgroundNode
|
||||||
|
|
||||||
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings {
|
||||||
self.currentTheme = interfaceState.theme
|
self.currentTheme = interfaceState.theme
|
||||||
self.currentStrings = interfaceState.strings
|
self.currentStrings = interfaceState.strings
|
||||||
@ -833,6 +848,8 @@ final class ChatEmptyNode: ASDisplayNode {
|
|||||||
self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper), enableBlur: dateFillNeedsBlur(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper), transition: .immediate)
|
self.backgroundNode.updateColor(color: selectDateFillStaticColor(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper), enableBlur: dateFillNeedsBlur(theme: interfaceState.theme, wallpaper: interfaceState.chatWallpaper), transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var isScheduledMessages = false
|
var isScheduledMessages = false
|
||||||
if case .scheduledMessages = interfaceState.subject {
|
if case .scheduledMessages = interfaceState.subject {
|
||||||
isScheduledMessages = true
|
isScheduledMessages = true
|
||||||
@ -923,8 +940,45 @@ final class ChatEmptyNode: ASDisplayNode {
|
|||||||
transition.updateFrame(node: self.backgroundNode, frame: contentFrame)
|
transition.updateFrame(node: self.backgroundNode, frame: contentFrame)
|
||||||
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(20.0, self.backgroundNode.bounds.height / 2.0), transition: transition)
|
self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(20.0, self.backgroundNode.bounds.height / 2.0), transition: transition)
|
||||||
|
|
||||||
|
if backgroundNode?.hasExtraBubbleBackground() == true {
|
||||||
|
if self.backgroundContent == nil, let backgroundContent = backgroundNode?.makeBubbleBackground(for: .free) {
|
||||||
|
backgroundContent.clipsToBounds = true
|
||||||
|
|
||||||
|
self.backgroundContent = backgroundContent
|
||||||
|
self.insertSubnode(backgroundContent, at: 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.backgroundContent?.removeFromSupernode()
|
||||||
|
self.backgroundContent = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
self.backgroundNode.isHidden = true
|
||||||
|
backgroundContent.cornerRadius = min(20.0, self.backgroundNode.bounds.height / 2.0)
|
||||||
|
backgroundContent.frame = contentFrame
|
||||||
|
if let (rect, containerSize) = self.absolutePosition {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.backgroundNode.isHidden = false
|
||||||
|
}
|
||||||
|
|
||||||
if let loadingNode = loadingNode {
|
if let loadingNode = loadingNode {
|
||||||
self.animateFromLoadingNode(loadingNode)
|
self.animateFromLoadingNode(loadingNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public func update(rect: CGRect, within containerSize: CGSize, transition: ContainedViewLayoutTransition = .immediate) {
|
||||||
|
self.absolutePosition = (rect, containerSize)
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: transition)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -244,7 +244,7 @@ private func mappedInsertEntries(context: AccountContext, chatLocation: ChatLoca
|
|||||||
}
|
}
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
|
||||||
case let .UnreadEntry(_, presentationData):
|
case let .UnreadEntry(_, presentationData):
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, controllerInteraction: controllerInteraction, context: context), directionHint: entry.directionHint)
|
||||||
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
||||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction), directionHint: entry.directionHint)
|
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction), directionHint: entry.directionHint)
|
||||||
case let .ChatInfoEntry(title, text, photo, video, presentationData):
|
case let .ChatInfoEntry(title, text, photo, video, presentationData):
|
||||||
@ -289,7 +289,7 @@ private func mappedUpdateEntries(context: AccountContext, chatLocation: ChatLoca
|
|||||||
}
|
}
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: item, directionHint: entry.directionHint)
|
||||||
case let .UnreadEntry(_, presentationData):
|
case let .UnreadEntry(_, presentationData):
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, context: context), directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatUnreadItem(index: entry.entry.index, presentationData: presentationData, controllerInteraction: controllerInteraction, context: context), directionHint: entry.directionHint)
|
||||||
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
case let .ReplyCountEntry(_, isComments, count, presentationData):
|
||||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction), directionHint: entry.directionHint)
|
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatReplyCountItem(index: entry.entry.index, isComments: isComments, count: count, presentationData: presentationData, context: context, controllerInteraction: controllerInteraction), directionHint: entry.directionHint)
|
||||||
case let .ChatInfoEntry(title, text, photo, video, presentationData):
|
case let .ChatInfoEntry(title, text, photo, video, presentationData):
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import Postbox
|
|||||||
import Display
|
import Display
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
import WallpaperBackgroundNode
|
||||||
|
|
||||||
private let titleFont = Font.medium(16.0)
|
private let titleFont = Font.medium(16.0)
|
||||||
|
|
||||||
@ -16,6 +17,12 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
private var iconNode: ASImageNode?
|
private var iconNode: ASImageNode?
|
||||||
private var buttonView: HighlightTrackingButton?
|
private var buttonView: HighlightTrackingButton?
|
||||||
|
|
||||||
|
private var wallpaperBackgroundNode: WallpaperBackgroundNode?
|
||||||
|
private var backgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
|
private var backgroundColorNode: ASDisplayNode?
|
||||||
|
|
||||||
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
private var button: ReplyMarkupButton?
|
private var button: ReplyMarkupButton?
|
||||||
var pressed: ((ReplyMarkupButton) -> Void)?
|
var pressed: ((ReplyMarkupButton) -> Void)?
|
||||||
var longTapped: ((ReplyMarkupButton) -> Void)?
|
var longTapped: ((ReplyMarkupButton) -> Void)?
|
||||||
@ -58,9 +65,15 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
if highlighted {
|
if highlighted {
|
||||||
strongSelf.backgroundBlurNode.layer.removeAnimation(forKey: "opacity")
|
strongSelf.backgroundBlurNode.layer.removeAnimation(forKey: "opacity")
|
||||||
strongSelf.backgroundBlurNode.alpha = 0.55
|
strongSelf.backgroundBlurNode.alpha = 0.55
|
||||||
|
|
||||||
|
strongSelf.backgroundContent?.layer.removeAnimation(forKey: "opacity")
|
||||||
|
strongSelf.backgroundContent?.alpha = 0.55
|
||||||
} else {
|
} else {
|
||||||
strongSelf.backgroundBlurNode.alpha = 1.0
|
strongSelf.backgroundBlurNode.alpha = 1.0
|
||||||
strongSelf.backgroundBlurNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
strongSelf.backgroundBlurNode.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
||||||
|
|
||||||
|
strongSelf.backgroundContent?.alpha = 1.0
|
||||||
|
strongSelf.backgroundContent?.layer.animateAlpha(from: 0.55, to: 1.0, duration: 0.2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,10 +96,21 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class func asyncLayout(_ maybeNode: ChatMessageActionButtonNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ bubbleCorners: PresentationChatBubbleCorners, _ strings: PresentationStrings, _ message: Message, _ button: ReplyMarkupButton, _ constrainedWidth: CGFloat, _ position: MessageBubbleActionButtonPosition) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonNode))) {
|
func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.absolutePosition = (rect, containerSize)
|
||||||
|
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class func asyncLayout(_ maybeNode: ChatMessageActionButtonNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ bubbleCorners: PresentationChatBubbleCorners, _ strings: PresentationStrings, _ backgroundNode: WallpaperBackgroundNode?, _ message: Message, _ button: ReplyMarkupButton, _ constrainedWidth: CGFloat, _ position: MessageBubbleActionButtonPosition) -> (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonNode))) {
|
||||||
let titleLayout = TextNode.asyncLayout(maybeNode?.titleNode)
|
let titleLayout = TextNode.asyncLayout(maybeNode?.titleNode)
|
||||||
|
|
||||||
return { context, theme, bubbleCorners, strings, message, button, constrainedWidth, position in
|
return { context, theme, bubbleCorners, strings, backgroundNode, message, button, constrainedWidth, position in
|
||||||
let incoming = message.effectivelyIncoming(context.account.peerId)
|
let incoming = message.effectivelyIncoming(context.account.peerId)
|
||||||
let graphics = PresentationResourcesChat.additionalGraphics(theme.theme, wallpaper: theme.wallpaper, bubbleCorners: bubbleCorners)
|
let graphics = PresentationResourcesChat.additionalGraphics(theme.theme, wallpaper: theme.wallpaper, bubbleCorners: bubbleCorners)
|
||||||
|
|
||||||
@ -159,6 +183,8 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
animation = .None
|
animation = .None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node.wallpaperBackgroundNode = backgroundNode
|
||||||
|
|
||||||
node.button = button
|
node.button = button
|
||||||
|
|
||||||
switch button.action {
|
switch button.action {
|
||||||
@ -175,6 +201,44 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
node.backgroundBlurNode.update(size: node.backgroundBlurNode.bounds.size, cornerRadius: bubbleCorners.auxiliaryRadius, animator: animation.animator)
|
node.backgroundBlurNode.update(size: node.backgroundBlurNode.bounds.size, cornerRadius: bubbleCorners.auxiliaryRadius, animator: animation.animator)
|
||||||
node.backgroundBlurNode.updateColor(color: selectDateFillStaticColor(theme: theme.theme, wallpaper: theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: theme.theme, wallpaper: theme.wallpaper), transition: .immediate)
|
node.backgroundBlurNode.updateColor(color: selectDateFillStaticColor(theme: theme.theme, wallpaper: theme.wallpaper), enableBlur: dateFillNeedsBlur(theme: theme.theme, wallpaper: theme.wallpaper), transition: .immediate)
|
||||||
|
|
||||||
|
if backgroundNode?.hasExtraBubbleBackground() == true {
|
||||||
|
if node.backgroundContent == nil, let backgroundContent = backgroundNode?.makeBubbleBackground(for: .free) {
|
||||||
|
backgroundContent.clipsToBounds = true
|
||||||
|
backgroundContent.allowsGroupOpacity = true
|
||||||
|
|
||||||
|
node.backgroundContent = backgroundContent
|
||||||
|
node.insertSubnode(backgroundContent, at: 0)
|
||||||
|
|
||||||
|
let backgroundColorNode = ASDisplayNode()
|
||||||
|
backgroundColorNode.backgroundColor = UIColor(rgb: 0x000000, alpha: 0.4)
|
||||||
|
backgroundContent.addSubnode(backgroundColorNode)
|
||||||
|
node.backgroundColorNode = backgroundColorNode
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.backgroundContent?.removeFromSupernode()
|
||||||
|
node.backgroundContent = nil
|
||||||
|
|
||||||
|
node.backgroundColorNode?.removeFromSupernode()
|
||||||
|
node.backgroundColorNode = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let backgroundContent = node.backgroundContent {
|
||||||
|
node.backgroundBlurNode.isHidden = true
|
||||||
|
backgroundContent.frame = node.backgroundBlurNode.frame
|
||||||
|
backgroundContent.cornerRadius = bubbleCorners.auxiliaryRadius
|
||||||
|
|
||||||
|
node.backgroundColorNode?.frame = backgroundContent.bounds
|
||||||
|
|
||||||
|
if let (rect, containerSize) = node.absolutePosition {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.backgroundBlurNode.isHidden = false
|
||||||
|
}
|
||||||
|
|
||||||
if iconImage != nil {
|
if iconImage != nil {
|
||||||
if node.iconNode == nil {
|
if node.iconNode == nil {
|
||||||
let iconNode = ASImageNode()
|
let iconNode = ASImageNode()
|
||||||
@ -206,6 +270,10 @@ private final class ChatMessageActionButtonNode: ASDisplayNode {
|
|||||||
animation.animator.updateFrame(layer: iconNode.layer, frame: CGRect(x: width - 16.0, y: 4.0, width: 12.0, height: 12.0), completion: nil)
|
animation.animator.updateFrame(layer: iconNode.layer, frame: CGRect(x: width - 16.0, y: 4.0, width: 12.0, height: 12.0), completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let (rect, size) = node.absolutePosition {
|
||||||
|
node.updateAbsoluteRect(rect, within: size)
|
||||||
|
}
|
||||||
|
|
||||||
node.accessibilityArea.accessibilityLabel = title
|
node.accessibilityArea.accessibilityLabel = title
|
||||||
node.accessibilityArea.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: 42.0))
|
node.accessibilityArea.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: 42.0))
|
||||||
|
|
||||||
@ -224,6 +292,8 @@ final class ChatMessageActionButtonsNode: ASDisplayNode {
|
|||||||
var buttonPressed: ((ReplyMarkupButton) -> Void)?
|
var buttonPressed: ((ReplyMarkupButton) -> Void)?
|
||||||
var buttonLongTapped: ((ReplyMarkupButton) -> Void)?
|
var buttonLongTapped: ((ReplyMarkupButton) -> Void)?
|
||||||
|
|
||||||
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
@ -240,10 +310,21 @@ final class ChatMessageActionButtonsNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class func asyncLayout(_ maybeNode: ChatMessageActionButtonsNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ chatBubbleCorners: PresentationChatBubbleCorners, _ strings: PresentationStrings, _ replyMarkup: ReplyMarkupMessageAttribute, _ message: Message, _ constrainedWidth: CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode)) {
|
func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.absolutePosition = (rect, containerSize)
|
||||||
|
|
||||||
|
for button in buttonNodes {
|
||||||
|
var buttonFrame = button.frame
|
||||||
|
buttonFrame.origin.x += rect.minX
|
||||||
|
buttonFrame.origin.y += rect.minY
|
||||||
|
button.updateAbsoluteRect(buttonFrame, within: containerSize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class func asyncLayout(_ maybeNode: ChatMessageActionButtonsNode?) -> (_ context: AccountContext, _ theme: ChatPresentationThemeData, _ chatBubbleCorners: PresentationChatBubbleCorners, _ strings: PresentationStrings, _ backgroundNode: WallpaperBackgroundNode?, _ replyMarkup: ReplyMarkupMessageAttribute, _ message: Message, _ constrainedWidth: CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode)) {
|
||||||
let currentButtonLayouts = maybeNode?.buttonNodes.map { ChatMessageActionButtonNode.asyncLayout($0) } ?? []
|
let currentButtonLayouts = maybeNode?.buttonNodes.map { ChatMessageActionButtonNode.asyncLayout($0) } ?? []
|
||||||
|
|
||||||
return { context, theme, chatBubbleCorners, strings, replyMarkup, message, constrainedWidth in
|
return { context, theme, chatBubbleCorners, strings, backgroundNode, replyMarkup, message, constrainedWidth in
|
||||||
let buttonHeight: CGFloat = 42.0
|
let buttonHeight: CGFloat = 42.0
|
||||||
let buttonSpacing: CGFloat = 4.0
|
let buttonSpacing: CGFloat = 4.0
|
||||||
|
|
||||||
@ -276,9 +357,9 @@ final class ChatMessageActionButtonsNode: ASDisplayNode {
|
|||||||
|
|
||||||
let prepareButtonLayout: (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonNode)))
|
let prepareButtonLayout: (minimumWidth: CGFloat, layout: ((CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonNode)))
|
||||||
if buttonIndex < currentButtonLayouts.count {
|
if buttonIndex < currentButtonLayouts.count {
|
||||||
prepareButtonLayout = currentButtonLayouts[buttonIndex](context, theme, chatBubbleCorners, strings, message, button, maximumButtonWidth, buttonPosition)
|
prepareButtonLayout = currentButtonLayouts[buttonIndex](context, theme, chatBubbleCorners, strings, backgroundNode, message, button, maximumButtonWidth, buttonPosition)
|
||||||
} else {
|
} else {
|
||||||
prepareButtonLayout = ChatMessageActionButtonNode.asyncLayout(nil)(context, theme, chatBubbleCorners, strings, message, button, maximumButtonWidth, buttonPosition)
|
prepareButtonLayout = ChatMessageActionButtonNode.asyncLayout(nil)(context, theme, chatBubbleCorners, strings, backgroundNode, message, button, maximumButtonWidth, buttonPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
maximumRowButtonWidth = max(maximumRowButtonWidth, prepareButtonLayout.minimumWidth)
|
maximumRowButtonWidth = max(maximumRowButtonWidth, prepareButtonLayout.minimumWidth)
|
||||||
@ -363,6 +444,10 @@ final class ChatMessageActionButtonsNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
node.buttonNodes = updatedButtons
|
node.buttonNodes = updatedButtons
|
||||||
|
|
||||||
|
if let (rect, size) = node.absolutePosition {
|
||||||
|
node.updateAbsoluteRect(rect, within: size)
|
||||||
|
}
|
||||||
|
|
||||||
return node
|
return node
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -57,6 +57,8 @@ extension SlotMachineAnimationNode: GenericAnimatedStickerNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessageShareButton: HighlightableButtonNode {
|
class ChatMessageShareButton: HighlightableButtonNode {
|
||||||
|
private var backgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
|
|
||||||
private let backgroundNode: NavigationBackgroundNode
|
private let backgroundNode: NavigationBackgroundNode
|
||||||
private let iconNode: ASImageNode
|
private let iconNode: ASImageNode
|
||||||
private var iconOffset = CGPoint()
|
private var iconOffset = CGPoint()
|
||||||
@ -66,6 +68,8 @@ class ChatMessageShareButton: HighlightableButtonNode {
|
|||||||
|
|
||||||
private var textNode: ImmediateTextNode?
|
private var textNode: ImmediateTextNode?
|
||||||
|
|
||||||
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
self.backgroundNode = NavigationBackgroundNode(color: .clear)
|
self.backgroundNode = NavigationBackgroundNode(color: .clear)
|
||||||
self.iconNode = ASImageNode()
|
self.iconNode = ASImageNode()
|
||||||
@ -80,7 +84,7 @@ class ChatMessageShareButton: HighlightableButtonNode {
|
|||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(presentationData: ChatPresentationData, chatLocation: ChatLocation, subject: ChatControllerSubject?, message: Message, account: Account, disableComments: Bool = false) -> CGSize {
|
func update(presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction, chatLocation: ChatLocation, subject: ChatControllerSubject?, message: Message, account: Account, disableComments: Bool = false) -> CGSize {
|
||||||
var isReplies = false
|
var isReplies = false
|
||||||
var replyCount = 0
|
var replyCount = 0
|
||||||
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
|
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
|
||||||
@ -160,8 +164,46 @@ class ChatMessageShareButton: HighlightableButtonNode {
|
|||||||
if let image = self.iconNode.image {
|
if let image = self.iconNode.image {
|
||||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0) + self.iconOffset.x, y: floor((size.width - image.size.width) / 2.0) - (offsetIcon ? 1.0 : 0.0) + self.iconOffset.y), size: image.size)
|
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0) + self.iconOffset.x, y: floor((size.width - image.size.width) / 2.0) - (offsetIcon ? 1.0 : 0.0) + self.iconOffset.y), size: image.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true {
|
||||||
|
if self.backgroundContent == nil, let backgroundContent = controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||||
|
backgroundContent.clipsToBounds = true
|
||||||
|
backgroundContent.allowsGroupOpacity = true
|
||||||
|
self.backgroundContent = backgroundContent
|
||||||
|
self.insertSubnode(backgroundContent, at: 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.backgroundContent?.removeFromSupernode()
|
||||||
|
self.backgroundContent = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
self.backgroundNode.isHidden = true
|
||||||
|
backgroundContent.cornerRadius = min(self.backgroundNode.bounds.width, self.backgroundNode.bounds.height) / 2.0
|
||||||
|
backgroundContent.frame = self.backgroundNode.frame
|
||||||
|
if let (rect, containerSize) = self.absolutePosition {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.backgroundNode.isHidden = false
|
||||||
|
}
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.absolutePosition = (rect, containerSize)
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||||
@ -1206,7 +1248,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
var maxContentWidth = imageSize.width
|
var maxContentWidth = imageSize.width
|
||||||
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
||||||
if let replyMarkup = replyMarkup {
|
if let replyMarkup = replyMarkup {
|
||||||
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth)
|
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, item.controllerInteraction.presentationContext.backgroundNode, replyMarkup, item.message, maxContentWidth)
|
||||||
maxContentWidth = max(maxContentWidth, minWidth)
|
maxContentWidth = max(maxContentWidth, minWidth)
|
||||||
actionButtonsFinalize = buttonsLayout
|
actionButtonsFinalize = buttonsLayout
|
||||||
}
|
}
|
||||||
@ -1359,7 +1401,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
strongSelf.addSubnode(updatedShareButtonNode)
|
strongSelf.addSubnode(updatedShareButtonNode)
|
||||||
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
||||||
}
|
}
|
||||||
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||||
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: updatedImageFrame.maxX + 8.0, y: updatedImageFrame.maxY - buttonSize.height - 4.0 + imageBottomPadding), size: buttonSize)
|
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: updatedImageFrame.maxX + 8.0, y: updatedImageFrame.maxY - buttonSize.height - 4.0 + imageBottomPadding), size: buttonSize)
|
||||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
shareButtonNode.removeFromSupernode()
|
shareButtonNode.removeFromSupernode()
|
||||||
|
|||||||
@ -1073,7 +1073,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
adminBadgeLayout: (TextNodeLayoutArguments) -> (TextNodeLayout, () -> TextNode),
|
||||||
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode),
|
forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode),
|
||||||
replyInfoLayout: (ChatMessageReplyInfoNode.Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode),
|
replyInfoLayout: (ChatMessageReplyInfoNode.Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode),
|
||||||
actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode)),
|
actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, WallpaperBackgroundNode?, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode)),
|
||||||
reactionButtonsLayout: (ChatMessageReactionButtonsNode.Arguments) -> (minWidth: CGFloat, layout: (CGFloat) -> (size: CGSize, apply: (ListViewItemUpdateAnimation) -> ChatMessageReactionButtonsNode)),
|
reactionButtonsLayout: (ChatMessageReactionButtonsNode.Arguments) -> (minWidth: CGFloat, layout: (CGFloat) -> (size: CGSize, apply: (ListViewItemUpdateAnimation) -> ChatMessageReactionButtonsNode)),
|
||||||
mosaicStatusLayout: (ChatMessageDateAndStatusNode.Arguments) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)),
|
mosaicStatusLayout: (ChatMessageDateAndStatusNode.Arguments) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation) -> ChatMessageDateAndStatusNode)),
|
||||||
layoutConstants: ChatMessageItemLayoutConstants,
|
layoutConstants: ChatMessageItemLayoutConstants,
|
||||||
@ -1937,7 +1937,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
|
|
||||||
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
||||||
if let replyMarkup = replyMarkup {
|
if let replyMarkup = replyMarkup {
|
||||||
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maximumNodeWidth)
|
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, item.controllerInteraction.presentationContext.backgroundNode, replyMarkup, item.message, maximumNodeWidth)
|
||||||
maxContentWidth = max(maxContentWidth, minWidth)
|
maxContentWidth = max(maxContentWidth, minWidth)
|
||||||
actionButtonsFinalize = buttonsLayout
|
actionButtonsFinalize = buttonsLayout
|
||||||
}
|
}
|
||||||
@ -2959,7 +2959,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}
|
}
|
||||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
let currentBackgroundFrame = strongSelf.backgroundNode.frame
|
let currentBackgroundFrame = strongSelf.backgroundNode.frame
|
||||||
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
|
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
|
||||||
animation.animator.updateFrame(layer: shareButtonNode.layer, frame: CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize), completion: nil)
|
animation.animator.updateFrame(layer: shareButtonNode.layer, frame: CGRect(origin: CGPoint(x: currentBackgroundFrame.maxX + 8.0, y: currentBackgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize), completion: nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -2969,7 +2969,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
}*/
|
}*/
|
||||||
strongSelf.messageAccessibilityArea.frame = backgroundFrame
|
strongSelf.messageAccessibilityArea.frame = backgroundFrame
|
||||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
|
let buttonSize = shareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account, disableComments: true)
|
||||||
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
|
shareButtonNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.maxX + 8.0, y: backgroundFrame.maxY - buttonSize.width - 1.0), size: buttonSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3984,6 +3984,22 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
contentNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + contentNode.frame.minX, y: rect.minY + contentNode.frame.minY), size: rect.size), within: containerSize)
|
contentNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + contentNode.frame.minX, y: rect.minY + contentNode.frame.minY), size: rect.size), within: containerSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let shareButtonNode = self.shareButtonNode {
|
||||||
|
var shareButtonNodeFrame = shareButtonNode.frame
|
||||||
|
shareButtonNodeFrame.origin.x += rect.minX
|
||||||
|
shareButtonNodeFrame.origin.y += rect.minY
|
||||||
|
|
||||||
|
shareButtonNode.updateAbsoluteRect(shareButtonNodeFrame, within: containerSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let actionButtonsNode = self.actionButtonsNode {
|
||||||
|
var actionButtonsNodeFrame = actionButtonsNode.frame
|
||||||
|
actionButtonsNodeFrame.origin.x += rect.minX
|
||||||
|
actionButtonsNodeFrame.origin.y += rect.minY
|
||||||
|
|
||||||
|
actionButtonsNode.updateAbsoluteRect(actionButtonsNodeFrame, within: containerSize)
|
||||||
|
}
|
||||||
|
|
||||||
if let reactionButtonsNode = self.reactionButtonsNode {
|
if let reactionButtonsNode = self.reactionButtonsNode {
|
||||||
var reactionButtonsNodeFrame = reactionButtonsNode.frame
|
var reactionButtonsNodeFrame = reactionButtonsNode.frame
|
||||||
reactionButtonsNodeFrame.origin.x += rect.minX
|
reactionButtonsNodeFrame.origin.x += rect.minX
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import TelegramUniversalVideoContent
|
|||||||
import UniversalMediaPlayer
|
import UniversalMediaPlayer
|
||||||
import GalleryUI
|
import GalleryUI
|
||||||
import HierarchyTrackingLayer
|
import HierarchyTrackingLayer
|
||||||
|
import WallpaperBackgroundNode
|
||||||
|
|
||||||
private let timezoneOffset: Int32 = {
|
private let timezoneOffset: Int32 = {
|
||||||
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||||
@ -30,13 +31,15 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
|||||||
|
|
||||||
let id: ListViewItemNode.HeaderId
|
let id: ListViewItemNode.HeaderId
|
||||||
let presentationData: ChatPresentationData
|
let presentationData: ChatPresentationData
|
||||||
|
let controllerInteraction: ChatControllerInteraction?
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let action: ((Int32, Bool) -> Void)?
|
let action: ((Int32, Bool) -> Void)?
|
||||||
|
|
||||||
init(timestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) {
|
init(timestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction?, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) {
|
||||||
self.timestamp = timestamp
|
self.timestamp = timestamp
|
||||||
self.scheduled = scheduled
|
self.scheduled = scheduled
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
self.controllerInteraction = controllerInteraction
|
||||||
self.context = context
|
self.context = context
|
||||||
self.action = action
|
self.action = action
|
||||||
self.roundedTimestamp = dateHeaderTimestampId(timestamp: timestamp)
|
self.roundedTimestamp = dateHeaderTimestampId(timestamp: timestamp)
|
||||||
@ -57,7 +60,7 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
||||||
return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, scheduled: self.scheduled, presentationData: self.presentationData, context: self.context, action: self.action)
|
return ChatMessageDateHeaderNode(localTimestamp: self.roundedTimestamp, scheduled: self.scheduled, presentationData: self.presentationData, controllerInteraction: self.controllerInteraction, context: self.context, action: self.action)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) {
|
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) {
|
||||||
@ -115,8 +118,11 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
let stickBackgroundNode: ASImageNode
|
let stickBackgroundNode: ASImageNode
|
||||||
let activateArea: AccessibilityAreaNode
|
let activateArea: AccessibilityAreaNode
|
||||||
|
|
||||||
|
private var backgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
|
|
||||||
private let localTimestamp: Int32
|
private let localTimestamp: Int32
|
||||||
private var presentationData: ChatPresentationData
|
private var presentationData: ChatPresentationData
|
||||||
|
private let controllerInteraction: ChatControllerInteraction?
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let text: String
|
private let text: String
|
||||||
|
|
||||||
@ -124,8 +130,11 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
private var stickDistanceFactor: CGFloat = 0.0
|
private var stickDistanceFactor: CGFloat = 0.0
|
||||||
private var action: ((Int32, Bool) -> Void)? = nil
|
private var action: ((Int32, Bool) -> Void)? = nil
|
||||||
|
|
||||||
init(localTimestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) {
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
|
init(localTimestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction?, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) {
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
self.controllerInteraction = controllerInteraction
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
self.localTimestamp = localTimestamp
|
self.localTimestamp = localTimestamp
|
||||||
@ -135,6 +144,11 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
self.labelNode.isUserInteractionEnabled = false
|
self.labelNode.isUserInteractionEnabled = false
|
||||||
self.labelNode.displaysAsynchronously = !presentationData.isPreview
|
self.labelNode.displaysAsynchronously = !presentationData.isPreview
|
||||||
|
|
||||||
|
if controllerInteraction?.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true, let backgroundContent = controllerInteraction?.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||||
|
backgroundContent.clipsToBounds = true
|
||||||
|
self.backgroundContent = backgroundContent
|
||||||
|
}
|
||||||
|
|
||||||
self.backgroundNode = NavigationBackgroundNode(color: .clear)
|
self.backgroundNode = NavigationBackgroundNode(color: .clear)
|
||||||
self.backgroundNode.isUserInteractionEnabled = false
|
self.backgroundNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
@ -188,7 +202,11 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
self.stickBackgroundNode.image = graphics.dateFloatingBackground
|
self.stickBackgroundNode.image = graphics.dateFloatingBackground
|
||||||
self.stickBackgroundNode.alpha = 0.0
|
self.stickBackgroundNode.alpha = 0.0
|
||||||
|
|
||||||
self.addSubnode(self.backgroundNode)
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
self.addSubnode(backgroundContent)
|
||||||
|
} else {
|
||||||
|
self.addSubnode(self.backgroundNode)
|
||||||
|
}
|
||||||
self.addSubnode(self.labelNode)
|
self.addSubnode(self.labelNode)
|
||||||
|
|
||||||
self.addSubnode(self.activateArea)
|
self.addSubnode(self.activateArea)
|
||||||
@ -239,6 +257,16 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
self.backgroundNode.updateColor(color: color, enableBlur: enableBlur, transition: .immediate)
|
self.backgroundNode.updateColor(color: color, enableBlur: enableBlur, transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
self.absolutePosition = (rect, containerSize)
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += containerSize.height - rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
override func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat) {
|
||||||
let chatDateSize: CGFloat = 20.0
|
let chatDateSize: CGFloat = 20.0
|
||||||
let chatDateInset: CGFloat = 6.0
|
let chatDateInset: CGFloat = 6.0
|
||||||
@ -253,6 +281,20 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
self.labelNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + chatDateInset, y: backgroundFrame.origin.y + floorToScreenPixels((backgroundSize.height - labelSize.height) / 2.0)), size: labelSize)
|
self.labelNode.frame = CGRect(origin: CGPoint(x: backgroundFrame.origin.x + chatDateInset, y: backgroundFrame.origin.y + floorToScreenPixels((backgroundSize.height - labelSize.height) / 2.0)), size: labelSize)
|
||||||
|
|
||||||
self.activateArea.frame = backgroundFrame
|
self.activateArea.frame = backgroundFrame
|
||||||
|
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
backgroundContent.allowsGroupOpacity = true
|
||||||
|
self.backgroundNode.isHidden = true
|
||||||
|
backgroundContent.frame = self.backgroundNode.frame
|
||||||
|
backgroundContent.cornerRadius = backgroundFrame.size.height / 2.0
|
||||||
|
|
||||||
|
if let (rect, containerSize) = self.absolutePosition {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += containerSize.height - rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) {
|
override func updateStickDistanceFactor(_ factor: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
@ -285,10 +327,12 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
let previousAlpha = self.backgroundNode.alpha
|
let previousAlpha = self.backgroundNode.alpha
|
||||||
|
|
||||||
if !previousAlpha.isEqual(to: alpha) {
|
if !previousAlpha.isEqual(to: alpha) {
|
||||||
|
self.backgroundContent?.alpha = alpha
|
||||||
self.backgroundNode.alpha = alpha
|
self.backgroundNode.alpha = alpha
|
||||||
self.labelNode.alpha = alpha
|
self.labelNode.alpha = alpha
|
||||||
if animated {
|
if animated {
|
||||||
let duration: Double = flashing ? 0.3 : 0.4
|
let duration: Double = flashing ? 0.3 : 0.4
|
||||||
|
self.backgroundContent?.layer.animateAlpha(from: previousAlpha, to: alpha, duration: duration)
|
||||||
self.backgroundNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: duration)
|
self.backgroundNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: duration)
|
||||||
self.labelNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: duration)
|
self.labelNode.layer.animateAlpha(from: previousAlpha, to: alpha, duration: duration)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -532,7 +532,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
var maxContentWidth = normalDisplaySize.width
|
var maxContentWidth = normalDisplaySize.width
|
||||||
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
||||||
if let replyMarkup = replyMarkup {
|
if let replyMarkup = replyMarkup {
|
||||||
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth)
|
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, item.controllerInteraction.presentationContext.backgroundNode, replyMarkup, item.message, maxContentWidth)
|
||||||
maxContentWidth = max(maxContentWidth, minWidth)
|
maxContentWidth = max(maxContentWidth, minWidth)
|
||||||
actionButtonsFinalize = buttonsLayout
|
actionButtonsFinalize = buttonsLayout
|
||||||
}
|
}
|
||||||
@ -636,7 +636,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
strongSelf.addSubnode(updatedShareButtonNode)
|
strongSelf.addSubnode(updatedShareButtonNode)
|
||||||
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
||||||
}
|
}
|
||||||
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||||
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: min(params.width - buttonSize.width - 8.0, videoFrame.maxX - 7.0), y: videoFrame.maxY - 24.0 - buttonSize.height), size: buttonSize)
|
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: min(params.width - buttonSize.width - 8.0, videoFrame.maxX - 7.0), y: videoFrame.maxY - 24.0 - buttonSize.height), size: buttonSize)
|
||||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
shareButtonNode.removeFromSupernode()
|
shareButtonNode.removeFromSupernode()
|
||||||
|
|||||||
@ -328,7 +328,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
|||||||
isScheduledMessages = true
|
isScheduledMessages = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dateHeader = ChatMessageDateHeader(timestamp: content.index.timestamp, scheduled: isScheduledMessages, presentationData: presentationData, context: context, action: { timestamp, alreadyThere in
|
self.dateHeader = ChatMessageDateHeader(timestamp: content.index.timestamp, scheduled: isScheduledMessages, presentationData: presentationData, controllerInteraction: controllerInteraction, context: context, action: { timestamp, alreadyThere in
|
||||||
var calendar = NSCalendar.current
|
var calendar = NSCalendar.current
|
||||||
calendar.timeZone = TimeZone(abbreviation: "UTC")!
|
calendar.timeZone = TimeZone(abbreviation: "UTC")!
|
||||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
|
let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
|
||||||
|
|||||||
@ -84,7 +84,7 @@ struct ChatMessageItemLayoutConstants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileprivate static var compact: ChatMessageItemLayoutConstants {
|
fileprivate static var compact: ChatMessageItemLayoutConstants {
|
||||||
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
|
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 0.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.85), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
|
||||||
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
|
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
|
||||||
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 0.0, maxDimensions: CGSize(width: 300.0, height: 380.0), minDimensions: CGSize(width: 170.0, height: 74.0))
|
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 0.0, maxDimensions: CGSize(width: 300.0, height: 380.0), minDimensions: CGSize(width: 170.0, height: 74.0))
|
||||||
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
|
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
|
||||||
@ -96,7 +96,7 @@ struct ChatMessageItemLayoutConstants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileprivate static var regular: ChatMessageItemLayoutConstants {
|
fileprivate static var regular: ChatMessageItemLayoutConstants {
|
||||||
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 1.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
|
let bubble = ChatMessageItemBubbleLayoutConstants(edgeInset: 4.0, defaultSpacing: 2.0 + UIScreenPixel, mergedSpacing: 0.0, maximumWidthFill: ChatMessageItemWidthFill(compactInset: 36.0, compactWidthBoundary: 500.0, freeMaximumFillFactor: 0.65), minimumSize: CGSize(width: 40.0, height: 35.0), contentInsets: UIEdgeInsets(top: 0.0, left: 6.0, bottom: 0.0, right: 0.0), borderInset: UIScreenPixel, strokeInsets: UIEdgeInsets(top: 1.0, left: 1.0, bottom: 1.0, right: 1.0))
|
||||||
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
|
let text = ChatMessageItemTextLayoutConstants(bubbleInsets: UIEdgeInsets(top: 6.0 + UIScreenPixel, left: 12.0, bottom: 6.0 - UIScreenPixel, right: 12.0))
|
||||||
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0))
|
let image = ChatMessageItemImageLayoutConstants(bubbleInsets: UIEdgeInsets(top: 2.0, left: 2.0, bottom: 2.0, right: 2.0), statusInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 6.0, right: 6.0), defaultCornerRadius: 16.0, mergedCornerRadius: 8.0, contentMergedCornerRadius: 5.0, maxDimensions: CGSize(width: 440.0, height: 440.0), minDimensions: CGSize(width: 170.0, height: 74.0))
|
||||||
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
|
let video = ChatMessageItemVideoLayoutConstants(maxHorizontalHeight: 250.0, maxVerticalHeight: 360.0)
|
||||||
|
|||||||
@ -673,7 +673,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
var maxContentWidth = imageSize.width
|
var maxContentWidth = imageSize.width
|
||||||
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animation: ListViewItemUpdateAnimation) -> ChatMessageActionButtonsNode))?
|
||||||
if let replyMarkup = replyMarkup {
|
if let replyMarkup = replyMarkup {
|
||||||
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth)
|
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, item.controllerInteraction.presentationContext.backgroundNode, replyMarkup, item.message, maxContentWidth)
|
||||||
maxContentWidth = max(maxContentWidth, minWidth)
|
maxContentWidth = max(maxContentWidth, minWidth)
|
||||||
actionButtonsFinalize = buttonsLayout
|
actionButtonsFinalize = buttonsLayout
|
||||||
}
|
}
|
||||||
@ -839,7 +839,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
strongSelf.addSubnode(updatedShareButtonNode)
|
strongSelf.addSubnode(updatedShareButtonNode)
|
||||||
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
||||||
}
|
}
|
||||||
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||||
let shareButtonFrame = CGRect(origin: CGPoint(x: baseShareButtonFrame.minX, y: baseShareButtonFrame.maxY - buttonSize.height), size: buttonSize)
|
let shareButtonFrame = CGRect(origin: CGPoint(x: baseShareButtonFrame.minX, y: baseShareButtonFrame.maxY - buttonSize.height), size: buttonSize)
|
||||||
transition.updateFrame(node: updatedShareButtonNode, frame: shareButtonFrame)
|
transition.updateFrame(node: updatedShareButtonNode, frame: shareButtonFrame)
|
||||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class ChatReplyCountItem: ListViewItem {
|
|||||||
self.isComments = isComments
|
self.isComments = isComments
|
||||||
self.count = count
|
self.count = count
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.header = ChatMessageDateHeader(timestamp: index.timestamp, scheduled: false, presentationData: presentationData, context: context)
|
self.header = ChatMessageDateHeader(timestamp: index.timestamp, scheduled: false, presentationData: presentationData, controllerInteraction: controllerInteraction, context: context)
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,18 +6,21 @@ import Display
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
import AccountContext
|
import AccountContext
|
||||||
|
import WallpaperBackgroundNode
|
||||||
|
|
||||||
private let titleFont = UIFont.systemFont(ofSize: 13.0)
|
private let titleFont = UIFont.systemFont(ofSize: 13.0)
|
||||||
|
|
||||||
class ChatUnreadItem: ListViewItem {
|
class ChatUnreadItem: ListViewItem {
|
||||||
let index: MessageIndex
|
let index: MessageIndex
|
||||||
let presentationData: ChatPresentationData
|
let presentationData: ChatPresentationData
|
||||||
|
let controllerInteraction: ChatControllerInteraction
|
||||||
let header: ChatMessageDateHeader
|
let header: ChatMessageDateHeader
|
||||||
|
|
||||||
init(index: MessageIndex, presentationData: ChatPresentationData, context: AccountContext) {
|
init(index: MessageIndex, presentationData: ChatPresentationData, controllerInteraction: ChatControllerInteraction, context: AccountContext) {
|
||||||
self.index = index
|
self.index = index
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.header = ChatMessageDateHeader(timestamp: index.timestamp, scheduled: false, presentationData: presentationData, context: context)
|
self.controllerInteraction = controllerInteraction
|
||||||
|
self.header = ChatMessageDateHeader(timestamp: index.timestamp, scheduled: false, presentationData: presentationData, controllerInteraction: controllerInteraction, context: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||||
@ -61,6 +64,11 @@ class ChatUnreadItemNode: ListViewItemNode {
|
|||||||
|
|
||||||
let activateArea: AccessibilityAreaNode
|
let activateArea: AccessibilityAreaNode
|
||||||
|
|
||||||
|
private var wallpaperBackgroundNode: WallpaperBackgroundNode?
|
||||||
|
private var backgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
|
|
||||||
|
private var absolutePosition: (CGRect, CGSize)?
|
||||||
|
|
||||||
private var theme: ChatPresentationThemeData?
|
private var theme: ChatPresentationThemeData?
|
||||||
|
|
||||||
private let layoutConstants = ChatMessageItemLayoutConstants.default
|
private let layoutConstants = ChatMessageItemLayoutConstants.default
|
||||||
@ -101,7 +109,7 @@ class ChatUnreadItemNode: ListViewItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
override func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||||
if let item = item as? ChatUnreadItem {
|
if let item = item as? ChatUnreadItem {
|
||||||
let dateAtBottom = !chatItemsHaveCommonDateHeader(item, nextItem)
|
let dateAtBottom = !chatItemsHaveCommonDateHeader(item, nextItem)
|
||||||
let (layout, apply) = self.asyncLayout()(item, params, dateAtBottom)
|
let (layout, apply) = self.asyncLayout()(item, params, dateAtBottom)
|
||||||
apply()
|
apply()
|
||||||
@ -142,11 +150,48 @@ class ChatUnreadItemNode: ListViewItemNode {
|
|||||||
|
|
||||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: backgroundSize)
|
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: backgroundSize)
|
||||||
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - size.size.width) / 2.0), y: floorToScreenPixels((backgroundSize.height - size.size.height) / 2.0)), size: size.size)
|
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - size.size.width) / 2.0), y: floorToScreenPixels((backgroundSize.height - size.size.height) / 2.0)), size: size.size)
|
||||||
|
|
||||||
|
if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true {
|
||||||
|
if strongSelf.backgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {
|
||||||
|
backgroundContent.clipsToBounds = true
|
||||||
|
|
||||||
|
strongSelf.backgroundContent = backgroundContent
|
||||||
|
strongSelf.insertSubnode(backgroundContent, at: 0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.backgroundContent?.removeFromSupernode()
|
||||||
|
strongSelf.backgroundContent = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if let backgroundContent = strongSelf.backgroundContent {
|
||||||
|
strongSelf.backgroundNode.isHidden = true
|
||||||
|
backgroundContent.frame = strongSelf.backgroundNode.frame
|
||||||
|
if let (rect, containerSize) = strongSelf.absolutePosition {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
strongSelf.backgroundNode.isHidden = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) {
|
||||||
|
super.updateAbsoluteRect(rect, within: containerSize)
|
||||||
|
|
||||||
|
self.absolutePosition = (rect, containerSize)
|
||||||
|
if let backgroundContent = self.backgroundContent {
|
||||||
|
var backgroundFrame = backgroundContent.frame
|
||||||
|
backgroundFrame.origin.x += rect.minX
|
||||||
|
backgroundFrame.origin.y += rect.minY
|
||||||
|
backgroundContent.update(rect: backgroundFrame, within: containerSize, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override public func headers() -> [ListViewItemHeader]? {
|
override public func headers() -> [ListViewItemHeader]? {
|
||||||
if let item = self.item {
|
if let item = self.item {
|
||||||
return [item.header]
|
return [item.header]
|
||||||
|
|||||||
@ -1355,7 +1355,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader {
|
public func makeChatMessageDateHeaderItem(context: AccountContext, timestamp: Int32, theme: PresentationTheme, strings: PresentationStrings, wallpaper: TelegramWallpaper, fontSize: PresentationFontSize, chatBubbleCorners: PresentationChatBubbleCorners, dateTimeFormat: PresentationDateTimeFormat, nameOrder: PresentationPersonNameOrder) -> ListViewItemHeader {
|
||||||
return ChatMessageDateHeader(timestamp: timestamp, scheduled: false, presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: wallpaper), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameOrder, disableAnimations: false, largeEmoji: false, chatBubbleCorners: chatBubbleCorners, animatedEmojiScale: 1.0, isPreview: true), context: context)
|
return ChatMessageDateHeader(timestamp: timestamp, scheduled: false, presentationData: ChatPresentationData(theme: ChatPresentationThemeData(theme: theme, wallpaper: wallpaper), fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameOrder, disableAnimations: false, largeEmoji: false, chatBubbleCorners: chatBubbleCorners, animatedEmojiScale: 1.0, isPreview: true), controllerInteraction: nil, context: context)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_WALLET
|
#if ENABLE_WALLET
|
||||||
|
|||||||
@ -291,6 +291,10 @@ final class MetalWallpaperBackgroundNode: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasExtraBubbleBackground() -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode? {
|
func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,8 @@ public protocol WallpaperBackgroundNode: ASDisplayNode {
|
|||||||
func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool
|
func hasBubbleBackground(for type: WallpaperBubbleType) -> Bool
|
||||||
func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode?
|
func makeBubbleBackground(for type: WallpaperBubbleType) -> WallpaperBubbleBackgroundNode?
|
||||||
|
|
||||||
|
func hasExtraBubbleBackground() -> Bool
|
||||||
|
|
||||||
func makeDimmedNode() -> ASDisplayNode?
|
func makeDimmedNode() -> ASDisplayNode?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +395,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
if isInvertedGradient {
|
if isInvertedGradient {
|
||||||
switch self.bubbleType {
|
switch self.bubbleType {
|
||||||
case .free:
|
case .free:
|
||||||
needsCleanBackground = false
|
self.contentNode.backgroundColor = bubbleTheme.chat.message.incoming.bubble.withWallpaper.fill[0]
|
||||||
|
// needsCleanBackground = false
|
||||||
case .incoming, .outgoing:
|
case .incoming, .outgoing:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -591,6 +594,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
|
|
||||||
private struct ValidPatternImage {
|
private struct ValidPatternImage {
|
||||||
let wallpaper: TelegramWallpaper
|
let wallpaper: TelegramWallpaper
|
||||||
|
let invertPattern: Bool
|
||||||
let generate: (TransformImageArguments) -> DrawingContext?
|
let generate: (TransformImageArguments) -> DrawingContext?
|
||||||
}
|
}
|
||||||
private var validPatternImage: ValidPatternImage?
|
private var validPatternImage: ValidPatternImage?
|
||||||
@ -893,10 +897,14 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
var updated = true
|
var updated = true
|
||||||
let brightness = UIColor.average(of: file.settings.colors.map(UIColor.init(rgb:))).hsb.b
|
let brightness = UIColor.average(of: file.settings.colors.map(UIColor.init(rgb:))).hsb.b
|
||||||
patternIsLight = brightness > 0.3
|
patternIsLight = brightness > 0.3
|
||||||
|
|
||||||
|
let intensity = CGFloat(file.settings.intensity ?? 50) / 100.0
|
||||||
|
invertPattern = intensity < 0
|
||||||
|
|
||||||
if let previousWallpaper = self.validPatternImage?.wallpaper {
|
if let previousWallpaper = self.validPatternImage?.wallpaper {
|
||||||
switch previousWallpaper {
|
switch previousWallpaper {
|
||||||
case let .file(previousFile):
|
case let .file(previousFile):
|
||||||
if file.file.id == previousFile.file.id {
|
if file.file.id == previousFile.file.id && self.validPatternImage?.invertPattern == invertPattern {
|
||||||
updated = false
|
updated = false
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -908,8 +916,8 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
self.validPatternGeneratedImage = nil
|
self.validPatternGeneratedImage = nil
|
||||||
self.validPatternImage = nil
|
self.validPatternImage = nil
|
||||||
|
|
||||||
if let cachedValidPatternImage = WallpaperBackgroundNodeImpl.cachedValidPatternImage, cachedValidPatternImage.generated.wallpaper == wallpaper {
|
if let cachedValidPatternImage = WallpaperBackgroundNodeImpl.cachedValidPatternImage, cachedValidPatternImage.generated.wallpaper == wallpaper && cachedValidPatternImage.generated.invertPattern == invertPattern {
|
||||||
self.validPatternImage = ValidPatternImage(wallpaper: cachedValidPatternImage.generated.wallpaper, generate: cachedValidPatternImage.generate)
|
self.validPatternImage = ValidPatternImage(wallpaper: cachedValidPatternImage.generated.wallpaper, invertPattern: invertPattern, generate: cachedValidPatternImage.generate)
|
||||||
} else {
|
} else {
|
||||||
func reference(for resource: EngineMediaResource, media: EngineMedia) -> MediaResourceReference {
|
func reference(for resource: EngineMediaResource, media: EngineMedia) -> MediaResourceReference {
|
||||||
return .wallpaper(wallpaper: .slug(file.slug), resource: resource._asResource())
|
return .wallpaper(wallpaper: .slug(file.slug), resource: resource._asResource())
|
||||||
@ -945,7 +953,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
return context
|
return context
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
strongSelf.validPatternImage = ValidPatternImage(wallpaper: wallpaper, generate: generator)
|
strongSelf.validPatternImage = ValidPatternImage(wallpaper: wallpaper, invertPattern: invertPattern, generate: generator)
|
||||||
strongSelf.validPatternGeneratedImage = nil
|
strongSelf.validPatternGeneratedImage = nil
|
||||||
if let size = strongSelf.validLayout {
|
if let size = strongSelf.validLayout {
|
||||||
strongSelf.loadPatternForSizeIfNeeded(size: size, transition: .immediate)
|
strongSelf.loadPatternForSizeIfNeeded(size: size, transition: .immediate)
|
||||||
@ -958,8 +966,6 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let intensity = CGFloat(file.settings.intensity ?? 50) / 100.0
|
|
||||||
invertPattern = intensity < 0
|
|
||||||
default:
|
default:
|
||||||
self.updatePatternPresentation()
|
self.updatePatternPresentation()
|
||||||
}
|
}
|
||||||
@ -1165,6 +1171,19 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasExtraBubbleBackground() -> Bool {
|
||||||
|
var isInvertedGradient = false
|
||||||
|
switch self.wallpaper {
|
||||||
|
case let .file(file):
|
||||||
|
if let intensity = file.settings.intensity, intensity < 0 {
|
||||||
|
isInvertedGradient = true
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return isInvertedGradient
|
||||||
|
}
|
||||||
|
|
||||||
func makeDimmedNode() -> ASDisplayNode? {
|
func makeDimmedNode() -> ASDisplayNode? {
|
||||||
if let gradientBackgroundNode = self.gradientBackgroundNode {
|
if let gradientBackgroundNode = self.gradientBackgroundNode {
|
||||||
return GradientBackgroundNode.CloneNode(parentNode: gradientBackgroundNode)
|
return GradientBackgroundNode.CloneNode(parentNode: gradientBackgroundNode)
|
||||||
@ -1987,6 +2006,10 @@ final class WallpaperBackgroundNodeMergedImpl: ASDisplayNode, WallpaperBackgroun
|
|||||||
node.updateContents()
|
node.updateContents()
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasExtraBubbleBackground() -> Bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func makeDimmedNode() -> ASDisplayNode? {
|
func makeDimmedNode() -> ASDisplayNode? {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user