mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
Avatar upload improvements
This commit is contained in:
@@ -14,6 +14,7 @@ import GalleryUI
|
||||
import HierarchyTrackingLayer
|
||||
import WallpaperBackgroundNode
|
||||
import ChatControllerInteraction
|
||||
import AvatarVideoNode
|
||||
|
||||
private let timezoneOffset: Int32 = {
|
||||
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
@@ -446,20 +447,17 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||
|
||||
private let containerNode: ContextControllerSourceNode
|
||||
private let avatarNode: AvatarNode
|
||||
private var videoNode: UniversalVideoNode?
|
||||
|
||||
private var videoContent: NativeVideoContent?
|
||||
private let playbackStartDisposable = MetaDisposable()
|
||||
private var avatarVideoNode: AvatarVideoNode?
|
||||
|
||||
private var cachedDataDisposable = MetaDisposable()
|
||||
private var hierarchyTrackingLayer: HierarchyTrackingLayer?
|
||||
private var videoLoopCount = 0
|
||||
|
||||
private var trackingIsInHierarchy: Bool = false {
|
||||
didSet {
|
||||
if self.trackingIsInHierarchy != oldValue {
|
||||
Queue.mainQueue().justDispatch {
|
||||
if self.trackingIsInHierarchy {
|
||||
self.videoLoopCount = 0
|
||||
self.avatarVideoNode?.resetPlayback()
|
||||
}
|
||||
self.updateVideoVisibility()
|
||||
}
|
||||
@@ -507,7 +505,6 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||
|
||||
deinit {
|
||||
self.cachedDataDisposable.dispose()
|
||||
self.playbackStartDisposable.dispose()
|
||||
}
|
||||
|
||||
func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor) {
|
||||
@@ -531,16 +528,35 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let cachedPeerData = peerView.cachedData
|
||||
if let cachedPeerData = cachedPeerData as? CachedUserData, case let .known(maybePhoto) = cachedPeerData.photo {
|
||||
if let photo = maybePhoto, let video = photo.videoRepresentations.last, let peerReference = PeerReference(peer) {
|
||||
let videoId = photo.id?.id ?? peer.id.id._internalGetInt64Value()
|
||||
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
let videoContent = NativeVideoContent(id: .profileVideo(videoId, "\(Int32.random(in: 0 ..< Int32.max))"), userLocation: .other, fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: false, storeAfterDownload: nil)
|
||||
if videoContent.id != strongSelf.videoContent?.id {
|
||||
strongSelf.videoNode?.removeFromSupernode()
|
||||
strongSelf.videoContent = videoContent
|
||||
|
||||
let cachedPeerData = peerView.cachedData as? CachedUserData
|
||||
var personalPhoto: TelegramMediaImage?
|
||||
var profilePhoto: TelegramMediaImage?
|
||||
var isKnown = false
|
||||
|
||||
if let cachedPeerData = cachedPeerData {
|
||||
if case let .known(maybePersonalPhoto) = cachedPeerData.personalPhoto {
|
||||
personalPhoto = maybePersonalPhoto
|
||||
isKnown = true
|
||||
}
|
||||
if case let .known(maybePhoto) = cachedPeerData.photo {
|
||||
profilePhoto = maybePhoto
|
||||
isKnown = true
|
||||
}
|
||||
}
|
||||
|
||||
if isKnown {
|
||||
let photo = personalPhoto ?? profilePhoto
|
||||
if let photo = photo, !photo.videoRepresentations.isEmpty || photo.emojiMarkup != nil {
|
||||
let videoNode: AvatarVideoNode
|
||||
if let current = strongSelf.avatarVideoNode {
|
||||
videoNode = current
|
||||
} else {
|
||||
videoNode = AvatarVideoNode(context: context)
|
||||
strongSelf.avatarNode.addSubnode(videoNode)
|
||||
strongSelf.avatarVideoNode = videoNode
|
||||
}
|
||||
videoNode.update(peer: EnginePeer(peer), photo: photo, size: CGSize(width: 38.0, height: 38.0))
|
||||
|
||||
if strongSelf.hierarchyTrackingLayer == nil {
|
||||
let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
||||
@@ -561,23 +577,65 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||
strongSelf.layer.addSublayer(hierarchyTrackingLayer)
|
||||
}
|
||||
} else {
|
||||
strongSelf.videoContent = nil
|
||||
|
||||
if let avatarVideoNode = strongSelf.avatarVideoNode {
|
||||
avatarVideoNode.removeFromSupernode()
|
||||
strongSelf.avatarVideoNode = nil
|
||||
}
|
||||
strongSelf.hierarchyTrackingLayer?.removeFromSuperlayer()
|
||||
strongSelf.hierarchyTrackingLayer = nil
|
||||
}
|
||||
|
||||
strongSelf.updateVideoVisibility()
|
||||
} else {
|
||||
let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peer.id).start()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// let cachedPeerData = peerView.cachedData
|
||||
// if let cachedPeerData = cachedPeerData as? CachedUserData, case let .known(maybePhoto) = cachedPeerData.photo {
|
||||
// if let photo = maybePhoto, let video = photo.videoRepresentations.last, let peerReference = PeerReference(peer) {
|
||||
// let videoId = photo.id?.id ?? peer.id.id._internalGetInt64Value()
|
||||
// let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||
// let videoContent = NativeVideoContent(id: .profileVideo(videoId, "\(Int32.random(in: 0 ..< Int32.max))"), userLocation: .other, fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: false, storeAfterDownload: nil)
|
||||
// if videoContent.id != strongSelf.videoContent?.id {
|
||||
// strongSelf.videoNode?.removeFromSupernode()
|
||||
// strongSelf.videoContent = videoContent
|
||||
// }
|
||||
//
|
||||
// if strongSelf.hierarchyTrackingLayer == nil {
|
||||
// let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
||||
// hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
// strongSelf.trackingIsInHierarchy = true
|
||||
// }
|
||||
//
|
||||
// hierarchyTrackingLayer.didExitHierarchy = { [weak self] in
|
||||
// guard let strongSelf = self else {
|
||||
// return
|
||||
// }
|
||||
// strongSelf.trackingIsInHierarchy = false
|
||||
// }
|
||||
// strongSelf.hierarchyTrackingLayer = hierarchyTrackingLayer
|
||||
// strongSelf.layer.addSublayer(hierarchyTrackingLayer)
|
||||
// }
|
||||
// } else {
|
||||
// strongSelf.videoContent = nil
|
||||
//
|
||||
// strongSelf.hierarchyTrackingLayer?.removeFromSuperlayer()
|
||||
// strongSelf.hierarchyTrackingLayer = nil
|
||||
// }
|
||||
//
|
||||
// strongSelf.updateVideoVisibility()
|
||||
// } else {
|
||||
}))
|
||||
} else {
|
||||
self.cachedDataDisposable.set(nil)
|
||||
self.videoContent = nil
|
||||
|
||||
self.videoNode?.removeFromSupernode()
|
||||
self.videoNode = nil
|
||||
self.avatarVideoNode?.removeFromSupernode()
|
||||
self.avatarVideoNode = nil
|
||||
|
||||
self.hierarchyTrackingLayer?.removeFromSuperlayer()
|
||||
self.hierarchyTrackingLayer = nil
|
||||
@@ -659,74 +717,12 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||
}
|
||||
|
||||
private func updateVideoVisibility() {
|
||||
let context = self.context
|
||||
let isVisible = self.trackingIsInHierarchy
|
||||
if isVisible, let videoContent = self.videoContent, self.videoLoopCount != maxVideoLoopCount {
|
||||
if self.videoNode == nil {
|
||||
let mediaManager = context.sharedContext.mediaManager
|
||||
let videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .embedded)
|
||||
videoNode.clipsToBounds = true
|
||||
videoNode.isUserInteractionEnabled = false
|
||||
videoNode.isHidden = true
|
||||
videoNode.playbackCompleted = { [weak self] in
|
||||
Queue.mainQueue().async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.videoLoopCount += 1
|
||||
if strongSelf.videoLoopCount == maxVideoLoopCount {
|
||||
if let videoNode = strongSelf.videoNode {
|
||||
strongSelf.videoNode = nil
|
||||
videoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak videoNode] _ in
|
||||
videoNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let _ = videoContent.startTimestamp {
|
||||
self.playbackStartDisposable.set((videoNode.status
|
||||
|> map { status -> Bool in
|
||||
if let status = status, case .playing = status.status {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|> filter { playing in
|
||||
return playing
|
||||
}
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
Queue.mainQueue().after(0.15) {
|
||||
strongSelf.videoNode?.isHidden = false
|
||||
}
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.playbackStartDisposable.set(nil)
|
||||
videoNode.isHidden = false
|
||||
}
|
||||
videoNode.layer.cornerRadius = self.avatarNode.frame.size.width / 2.0
|
||||
if #available(iOS 13.0, *) {
|
||||
videoNode.layer.cornerCurve = .circular
|
||||
}
|
||||
|
||||
videoNode.canAttachContent = true
|
||||
videoNode.play()
|
||||
|
||||
self.containerNode.insertSubnode(videoNode, aboveSubnode: self.avatarNode)
|
||||
self.videoNode = videoNode
|
||||
}
|
||||
} else if let videoNode = self.videoNode {
|
||||
self.videoNode = nil
|
||||
videoNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
if let videoNode = self.videoNode {
|
||||
videoNode.updateLayout(size: self.avatarNode.frame.size, transition: .immediate)
|
||||
videoNode.frame = self.avatarNode.frame
|
||||
self.avatarVideoNode?.updateVisibility(isVisible)
|
||||
|
||||
if let videoNode = self.avatarVideoNode {
|
||||
videoNode.updateLayout(size: self.avatarNode.frame.size, cornerRadius: self.avatarNode.frame.size.width / 2.0, transition: .immediate)
|
||||
videoNode.frame = self.avatarNode.bounds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user