Shared media improvements

This commit is contained in:
Ali
2021-10-19 22:14:00 +04:00
parent 021f3c57b3
commit fe82f7020e
25 changed files with 1669 additions and 729 deletions

View File

@@ -184,7 +184,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
private let playbackStatusDisposable = MetaDisposable()
private let playbackStatus = Promise<MediaPlayerStatus>()
private var downloadStatusIconNode: DownloadIconNode
private var downloadStatusIconNode: DownloadIconNode?
private var linearProgressNode: LinearProgressNode?
private var context: AccountContext?
@@ -216,15 +216,19 @@ public final class ListMessageFileItemNode: ListMessageNode {
self.highlightedBackgroundNode.isLayerBacked = true
self.titleNode = TextNode()
self.titleNode.displaysAsynchronously = false
self.titleNode.isUserInteractionEnabled = false
self.textNode = TextNode()
self.textNode.displaysAsynchronously = false
self.textNode.isUserInteractionEnabled = false
self.descriptionNode = TextNode()
self.descriptionNode.displaysAsynchronously = false
self.descriptionNode.isUserInteractionEnabled = false
self.descriptionProgressNode = ImmediateTextNode()
self.descriptionProgressNode.displaysAsynchronously = false
self.descriptionProgressNode.isUserInteractionEnabled = false
self.descriptionProgressNode.maximumNumberOfLines = 1
@@ -237,6 +241,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
self.extensionIconNode.displayWithoutProcessing = true
self.extensionIconText = TextNode()
self.extensionIconText.displaysAsynchronously = false
self.extensionIconText.isUserInteractionEnabled = false
self.iconImageNode = TransformImageNode()
@@ -246,8 +251,6 @@ public final class ListMessageFileItemNode: ListMessageNode {
self.iconStatusNode = SemanticStatusNode(backgroundNodeColor: .clear, foregroundNodeColor: .white)
self.iconStatusNode.isUserInteractionEnabled = false
self.downloadStatusIconNode = DownloadIconNode()
self.restrictionNode = ASDisplayNode()
self.restrictionNode.isHidden = true
@@ -275,6 +278,8 @@ public final class ListMessageFileItemNode: ListMessageNode {
guard let strongSelf = self, let item = strongSelf.item else {
return
}
cancelParentGestures(view: strongSelf.view)
item.interaction.openMessageContextMenu(item.message, false, strongSelf.contextSourceNode, strongSelf.contextSourceNode.bounds, gesture)
}
@@ -647,9 +652,9 @@ public final class ListMessageFileItemNode: ListMessageNode {
let (dateNodeLayout, dateNodeApply) = dateNodeMakeLayout(TextNodeLayoutArguments(attributedString: dateAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 12.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleNodeLayout, titleNodeApply) = titleNodeMakeLayout(TextNodeLayoutArguments(attributedString: titleText, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .middle, constrainedSize: CGSize(width: params.width - leftInset - leftOffset - rightInset - dateNodeLayout.size.width - 4.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleNodeLayout, titleNodeApply) = titleNodeMakeLayout(TextNodeLayoutArguments(attributedString: titleText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .middle, constrainedSize: CGSize(width: params.width - leftInset - leftOffset - rightInset - dateNodeLayout.size.width - 4.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (textNodeLayout, textNodeApply) = textNodeMakeLayout(TextNodeLayoutArguments(attributedString: captionText, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 30.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (textNodeLayout, textNodeApply) = textNodeMakeLayout(TextNodeLayoutArguments(attributedString: captionText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 30.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (descriptionNodeLayout, descriptionNodeApply) = descriptionNodeMakeLayout(TextNodeLayoutArguments(attributedString: descriptionText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 30.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@@ -700,6 +705,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
return (nodeLayout, { animation in
if let strongSelf = self {
if strongSelf.downloadStatusIconNode == nil {
strongSelf.downloadStatusIconNode = DownloadIconNode(theme: item.presentationData.theme.theme)
}
let transition: ContainedViewLayoutTransition
if animation.isAnimated {
transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)
@@ -742,8 +751,8 @@ public final class ListMessageFileItemNode: ListMessageNode {
strongSelf.linearProgressNode?.updateTheme(theme: item.presentationData.theme.theme)
strongSelf.restrictionNode.backgroundColor = item.presentationData.theme.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.6)
strongSelf.downloadStatusIconNode.customColor = item.presentationData.theme.theme.list.itemAccentColor
strongSelf.downloadStatusIconNode?.updateTheme(theme: item.presentationData.theme.theme)
}
if let (selectionWidth, selectionApply) = selectionNodeWidthAndApply {
@@ -854,8 +863,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
}
}))
}
transition.updateFrame(node: strongSelf.downloadStatusIconNode, frame: CGRect(origin: CGPoint(x: leftOffset + leftInset - 3.0, y: strongSelf.descriptionNode.frame.minY + floor((strongSelf.descriptionNode.frame.height - 18.0) / 2.0)), size: CGSize(width: 18.0, height: 18.0)))
if let downloadStatusIconNode = strongSelf.downloadStatusIconNode {
transition.updateFrame(node: downloadStatusIconNode, frame: CGRect(origin: CGPoint(x: leftOffset + leftInset - 3.0, y: strongSelf.descriptionNode.frame.minY + floor((strongSelf.descriptionNode.frame.height - 18.0) / 2.0)), size: CGSize(width: 18.0, height: 18.0)))
}
if let updatedFetchControls = updatedFetchControls {
let _ = strongSelf.fetchControls.swap(updatedFetchControls)
@@ -981,6 +992,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
override public func updateSelectionState(animated: Bool) {
}
public func cancelPreviewGesture() {
self.containerNode.cancelGesture()
}
private func updateProgressFrame(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
guard let item = self.appliedItem else {
@@ -1025,11 +1040,13 @@ public final class ListMessageFileItemNode: ListMessageNode {
linearProgressNode.updateProgress(value: CGFloat(progress), completion: {})
var animated = true
if self.downloadStatusIconNode.supernode == nil {
animated = false
self.offsetContainerNode.addSubnode(self.downloadStatusIconNode)
if let downloadStatusIconNode = self.downloadStatusIconNode {
if downloadStatusIconNode.supernode == nil {
animated = false
self.offsetContainerNode.addSubnode(downloadStatusIconNode)
}
downloadStatusIconNode.enqueueState(.pause, animated: animated)
}
self.downloadStatusIconNode.enqueueState(.pause, animated: animated)
case .Local:
if let linearProgressNode = self.linearProgressNode {
self.linearProgressNode = nil
@@ -1039,8 +1056,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
})
})
}
if self.downloadStatusIconNode.supernode != nil {
self.downloadStatusIconNode.removeFromSupernode()
if let downloadStatusIconNode = self.downloadStatusIconNode {
if downloadStatusIconNode.supernode != nil {
downloadStatusIconNode.removeFromSupernode()
}
}
case .Remote:
if let linearProgressNode = self.linearProgressNode {
@@ -1049,12 +1068,14 @@ public final class ListMessageFileItemNode: ListMessageNode {
linearProgressNode?.removeFromSupernode()
})
}
var animated = true
if self.downloadStatusIconNode.supernode == nil {
animated = false
self.offsetContainerNode.addSubnode(self.downloadStatusIconNode)
if let downloadStatusIconNode = self.downloadStatusIconNode {
var animated = true
if downloadStatusIconNode.supernode == nil {
animated = false
self.offsetContainerNode.addSubnode(downloadStatusIconNode)
}
downloadStatusIconNode.enqueueState(.download, animated: animated)
}
self.downloadStatusIconNode.enqueueState(.download, animated: animated)
}
} else {
if let linearProgressNode = self.linearProgressNode {
@@ -1063,8 +1084,10 @@ public final class ListMessageFileItemNode: ListMessageNode {
linearProgressNode?.removeFromSupernode()
})
}
if self.downloadStatusIconNode.supernode != nil {
self.downloadStatusIconNode.removeFromSupernode()
if let downloadStatusIconNode = self.downloadStatusIconNode {
if downloadStatusIconNode.supernode != nil {
downloadStatusIconNode.removeFromSupernode()
}
}
}
@@ -1090,7 +1113,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
transition.updateFrame(node: self.descriptionProgressNode, frame: CGRect(origin: self.descriptionNode.frame.origin, size: descriptionSize))
}
func activateMedia() {
public func activateMedia() {
self.progressPressed()
}
@@ -1288,20 +1311,55 @@ private enum DownloadIconNodeState: Equatable {
case pause
}
private final class DownloadIconNode: ManagedAnimationNode {
private func generateDownloadIcon(color: UIColor) -> UIImage? {
let animation = ManagedAnimationNode(size: CGSize(width: 18.0, height: 18.0))
animation.customColor = color
animation.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.01))
return animation.image
}
private final class DownloadIconNode: ASImageNode {
private var customColor: UIColor
private let duration: Double = 0.3
private var iconState: DownloadIconNodeState = .download
private var animationNode: ManagedAnimationNode?
init() {
super.init(size: CGSize(width: 18.0, height: 18.0))
self.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.01))
init(theme: PresentationTheme) {
self.customColor = theme.list.itemAccentColor
super.init()
self.image = PresentationResourcesChat.sharedMediaFileDownloadStartIcon(theme, generate: {
return generateDownloadIcon(color: theme.list.itemAccentColor)
})
self.contentMode = .center
}
func updateTheme(theme: PresentationTheme) {
self.image = PresentationResourcesChat.sharedMediaFileDownloadStartIcon(theme, generate: {
return generateDownloadIcon(color: theme.list.itemAccentColor)
})
self.customColor = theme.list.itemAccentColor
self.animationNode?.customColor = self.customColor
}
func enqueueState(_ state: DownloadIconNodeState, animated: Bool) {
guard self.iconState != state else {
return
}
if self.animationNode == nil {
let animationNode = ManagedAnimationNode(size: CGSize(width: 18.0, height: 18.0))
self.animationNode = animationNode
animationNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 18.0, height: 18.0))
animationNode.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.01))
self.addSubnode(animationNode)
self.image = nil
}
guard let animationNode = self.animationNode else {
return
}
let previousState = self.iconState
self.iconState = state
@@ -1311,9 +1369,9 @@ private final class DownloadIconNode: ManagedAnimationNode {
switch state {
case .download:
if animated {
self.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 100, endFrame: 120), duration: self.duration))
animationNode.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 100, endFrame: 120), duration: self.duration))
} else {
self.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.01))
animationNode.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.01))
}
case .pause:
break
@@ -1322,9 +1380,9 @@ private final class DownloadIconNode: ManagedAnimationNode {
switch state {
case .pause:
if animated {
self.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 20), duration: self.duration))
animationNode.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 0, endFrame: 20), duration: self.duration))
} else {
self.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 60, endFrame: 60), duration: 0.01))
animationNode.trackTo(item: ManagedAnimationItem(source: .local("anim_shareddownload"), frames: .range(startFrame: 60, endFrame: 60), duration: 0.01))
}
case .download:
break