mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 11:23:48 +00:00
Video avatar fixes
This commit is contained in:
parent
8b970a676a
commit
a0a2847eef
@ -352,6 +352,15 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest
|
||||
self.items[i].updateNode(node: itemNode, synchronous: synchronous)
|
||||
}
|
||||
}
|
||||
for i in (0 ..< self.itemNodes.count).reversed() {
|
||||
let node = self.itemNodes[i]
|
||||
if node.index > self.items.count - 1 {
|
||||
node.removeFromSupernode()
|
||||
self.itemNodes.remove(at: i)
|
||||
}
|
||||
}
|
||||
|
||||
self.updateCentralIndexOffset(transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ private let maxWidth: CGFloat = 75.0
|
||||
|
||||
public protocol GalleryThumbnailItem {
|
||||
func isEqual(to: GalleryThumbnailItem) -> Bool
|
||||
var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) { get }
|
||||
func image(synchronous: Bool) -> (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize)
|
||||
}
|
||||
|
||||
private final class GalleryThumbnailItemNode: ASDisplayNode {
|
||||
@ -19,19 +19,19 @@ private final class GalleryThumbnailItemNode: ASDisplayNode {
|
||||
|
||||
private let imageSize: CGSize
|
||||
|
||||
init(item: GalleryThumbnailItem) {
|
||||
init(item: GalleryThumbnailItem, synchronous: Bool) {
|
||||
self.imageNode = TransformImageNode()
|
||||
self.imageContainerNode = ASDisplayNode()
|
||||
self.imageContainerNode.clipsToBounds = true
|
||||
self.imageContainerNode.cornerRadius = 2.0
|
||||
let (signal, imageSize) = item.image
|
||||
let (signal, imageSize) = item.image(synchronous: synchronous)
|
||||
self.imageSize = imageSize
|
||||
|
||||
super.init()
|
||||
|
||||
self.imageContainerNode.addSubnode(self.imageNode)
|
||||
self.addSubnode(self.imageContainerNode)
|
||||
self.imageNode.setSignal(signal)
|
||||
self.imageNode.setSignal(signal, attemptSynchronously: synchronous)
|
||||
}
|
||||
|
||||
func updateLayout(height: CGFloat, progress: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
@ -57,6 +57,7 @@ public final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDel
|
||||
private var itemNodes: [GalleryThumbnailItemNode] = []
|
||||
private var centralIndexAndProgress: (Int, CGFloat?)?
|
||||
private var currentLayout: CGSize?
|
||||
public var updateSynchronously: Bool = false
|
||||
|
||||
private var isPanning: Bool = false
|
||||
|
||||
@ -96,7 +97,6 @@ public final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDel
|
||||
for i in 0 ..< self.items.count {
|
||||
if !self.items[i].isEqual(to: items[i]) {
|
||||
updated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -108,7 +108,7 @@ public final class GalleryThumbnailContainerNode: ASDisplayNode, UIScrollViewDel
|
||||
if let index = self.items.firstIndex(where: { $0.isEqual(to: item) }) {
|
||||
itemNodes.append(self.itemNodes[index])
|
||||
} else {
|
||||
itemNodes.append(GalleryThumbnailItemNode(item: item))
|
||||
itemNodes.append(GalleryThumbnailItemNode(item: item, synchronous: self.updateSynchronously))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ final class ChatMediaGalleryThumbnailItem: GalleryThumbnailItem {
|
||||
}
|
||||
}
|
||||
|
||||
var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) {
|
||||
func image(synchronous: Bool) -> (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) {
|
||||
switch self.thumbnail {
|
||||
case let .image(imageReference):
|
||||
if let representation = largestImageRepresentation(imageReference.media.representations) {
|
||||
|
@ -15,7 +15,7 @@ private struct InstantImageGalleryThumbnailItem: GalleryThumbnailItem {
|
||||
let account: Account
|
||||
let mediaReference: AnyMediaReference
|
||||
|
||||
var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) {
|
||||
func image(synchronous: Bool) -> (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) {
|
||||
if let imageReferene = mediaReference.concrete(TelegramMediaImage.self), let representation = largestImageRepresentation(imageReferene.media.representations) {
|
||||
return (mediaGridMessagePhoto(account: self.account, photoReference: imageReferene), representation.dimensions.cgSize)
|
||||
} else if let fileReference = mediaReference.concrete(TelegramMediaFile.self), let dimensions = fileReference.media.dimensions {
|
||||
|
@ -656,6 +656,19 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
return canDelete
|
||||
}
|
||||
|
||||
private func replaceEntries(_ entries: [AvatarGalleryEntry]) {
|
||||
self.galleryNode.currentThumbnailContainerNode?.updateSynchronously = true
|
||||
self.galleryNode.pager.replaceItems(entries.map({ entry in PeerAvatarImageGalleryItem(context: self.context, peer: self.peer, presentationData: presentationData, entry: entry, sourceCorners: self.sourceCorners, delete: self.canDelete ? { [weak self] in
|
||||
self?.deleteEntry(entry)
|
||||
} : nil, setMain: { [weak self] in
|
||||
self?.setMainEntry(entry)
|
||||
}, edit: { [weak self] in
|
||||
self?.editEntry(entry)
|
||||
}) }), centralItemIndex: 0, synchronous: true)
|
||||
self.entries = entries
|
||||
self.galleryNode.currentThumbnailContainerNode?.updateSynchronously = false
|
||||
}
|
||||
|
||||
private func setMainEntry(_ rawEntry: AvatarGalleryEntry) {
|
||||
var entry = rawEntry
|
||||
if case .topImage = entry, !self.entries.isEmpty {
|
||||
@ -668,9 +681,33 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
} else {
|
||||
}
|
||||
case let .image(_, reference, _, _, _, _, _, _, _, _):
|
||||
if self.peer.id == self.context.account.peerId {
|
||||
if self.peer.id == self.context.account.peerId, let peerReference = PeerReference(self.peer) {
|
||||
if let reference = reference {
|
||||
let _ = updatePeerPhotoExisting(network: self.context.account.network, reference: reference).start()
|
||||
let _ = (updatePeerPhotoExisting(network: self.context.account.network, reference: reference)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] photo in
|
||||
if let strongSelf = self, let photo = photo, let firstEntry = strongSelf.entries.first, case let .image(image) = firstEntry {
|
||||
let updatedEntry = AvatarGalleryEntry.image(photo.imageId, photo.reference, photo.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatar(peer: peerReference, resource: $0.resource)) }), photo.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), strongSelf.peer, image.5, image.6, image.7, photo.immediateThumbnailData, image.9)
|
||||
|
||||
for (lhs, rhs) in zip(firstEntry.representations, updatedEntry.representations) {
|
||||
if lhs.representation.dimensions == rhs.representation.dimensions {
|
||||
strongSelf.context.account.postbox.mediaBox.copyResourceData(from: lhs.representation.resource.id, to: rhs.representation.resource.id, synchronous: true)
|
||||
}
|
||||
}
|
||||
for (lhs, rhs) in zip(firstEntry.videoRepresentations, updatedEntry.videoRepresentations) {
|
||||
if lhs.representation.dimensions == rhs.representation.dimensions {
|
||||
strongSelf.context.account.postbox.mediaBox.copyResourceData(from: lhs.representation.resource.id, to: rhs.representation.resource.id, synchronous: true)
|
||||
}
|
||||
}
|
||||
|
||||
var entries = strongSelf.entries
|
||||
entries.remove(at: 0)
|
||||
entries.insert(updatedEntry, at: 0)
|
||||
strongSelf.replaceEntries(normalizeEntries(entries))
|
||||
if let firstEntry = strongSelf.entries.first {
|
||||
strongSelf._hiddenMedia.set(.single(firstEntry))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if let index = self.entries.firstIndex(of: entry) {
|
||||
@ -684,35 +721,12 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
entries.insert(previousFirstEntry, at: index)
|
||||
}
|
||||
|
||||
entries = normalizeEntries(entries)
|
||||
self.galleryNode.pager.replaceItems(entries.map({ entry in PeerAvatarImageGalleryItem(context: self.context, peer: self.peer, presentationData: presentationData, entry: entry, sourceCorners: self.sourceCorners, delete: self.canDelete ? { [weak self] in
|
||||
self?.deleteEntry(entry)
|
||||
} : nil, setMain: { [weak self] in
|
||||
self?.setMainEntry(entry)
|
||||
}, edit: { [weak self] in
|
||||
self?.editEntry(entry)
|
||||
}) }), centralItemIndex: 0, synchronous: true)
|
||||
self.entries = entries
|
||||
|
||||
self.replaceEntries(normalizeEntries(entries))
|
||||
if let firstEntry = self.entries.first {
|
||||
self._hiddenMedia.set(.single(firstEntry))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if let messageId = messageId {
|
||||
// let _ = deleteMessagesInteractively(account: self.context.account, messageIds: [messageId], type: .forEveryone).start()
|
||||
// }
|
||||
//
|
||||
// if entry == self.entries.first {
|
||||
// let _ = updatePeerPhoto(postbox: self.context.account.postbox, network: self.context.account.network, stateManager: self.context.account.stateManager, accountPeerId: self.context.account.peerId, peerId: self.peer.id, photo: nil, mapResourceToAvatarSizes: { _, _ in .single([:]) }).start()
|
||||
// self.dismiss(forceAway: true)
|
||||
// } else {
|
||||
// if let index = self.entries.firstIndex(of: entry) {
|
||||
// self.entries.remove(at: index)
|
||||
// self.galleryNode.pager.transaction(GalleryPagerTransaction(deleteItems: [index], insertItems: [], updateItems: [], focusOnItem: index - 1))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,9 +25,9 @@ private struct PeerAvatarImageGalleryThumbnailItem: GalleryThumbnailItem {
|
||||
self.content = content
|
||||
}
|
||||
|
||||
var image: (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) {
|
||||
func image(synchronous: Bool) -> (Signal<(TransformImageArguments) -> DrawingContext?, NoError>, CGSize) {
|
||||
if let representation = largestImageRepresentation(self.content.map({ $0.representation })) {
|
||||
return (avatarGalleryThumbnailPhoto(account: self.account, representations: self.content), representation.dimensions.cgSize)
|
||||
return (avatarGalleryThumbnailPhoto(account: self.account, representations: self.content, synchronousLoad: synchronous), representation.dimensions.cgSize)
|
||||
} else {
|
||||
return (.single({ _ in return nil }), CGSize(width: 128.0, height: 128.0))
|
||||
}
|
||||
|
@ -1000,9 +1000,9 @@ public func chatSecretPhoto(account: Account, photoReference: ImageMediaReferenc
|
||||
}
|
||||
}
|
||||
|
||||
private func avatarGalleryThumbnailDatas(postbox: Postbox, representations: [ImageRepresentationWithReference], fullRepresentationSize: CGSize = CGSize(width: 1280.0, height: 1280.0), autoFetchFullSize: Bool = false) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
||||
private func avatarGalleryThumbnailDatas(postbox: Postbox, representations: [ImageRepresentationWithReference], fullRepresentationSize: CGSize = CGSize(width: 1280.0, height: 1280.0), autoFetchFullSize: Bool = false, synchronousLoad: Bool) -> Signal<Tuple3<Data?, Data?, Bool>, NoError> {
|
||||
if let smallestRepresentation = smallestImageRepresentation(representations.map({ $0.representation })), let largestRepresentation = imageRepresentationLargerThan(representations.map({ $0.representation }), size: PixelDimensions(width: Int32(fullRepresentationSize.width), height: Int32(fullRepresentationSize.height))), let smallestIndex = representations.firstIndex(where: { $0.representation == smallestRepresentation }), let largestIndex = representations.firstIndex(where: { $0.representation == largestRepresentation }) {
|
||||
let maybeFullSize = postbox.mediaBox.resourceData(largestRepresentation.resource)
|
||||
let maybeFullSize = postbox.mediaBox.resourceData(largestRepresentation.resource, attemptSynchronously: synchronousLoad)
|
||||
|
||||
let signal = maybeFullSize
|
||||
|> take(1)
|
||||
@ -1070,8 +1070,8 @@ private func avatarGalleryThumbnailDatas(postbox: Postbox, representations: [Ima
|
||||
}
|
||||
}
|
||||
|
||||
public func avatarGalleryThumbnailPhoto(account: Account, representations: [ImageRepresentationWithReference]) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||
let signal = avatarGalleryThumbnailDatas(postbox: account.postbox, representations: representations, fullRepresentationSize: CGSize(width: 127.0, height: 127.0), autoFetchFullSize: true)
|
||||
public func avatarGalleryThumbnailPhoto(account: Account, representations: [ImageRepresentationWithReference], synchronousLoad: Bool) -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
|
||||
let signal = avatarGalleryThumbnailDatas(postbox: account.postbox, representations: representations, fullRepresentationSize: CGSize(width: 127.0, height: 127.0), autoFetchFullSize: true, synchronousLoad: synchronousLoad)
|
||||
return signal
|
||||
|> map { value in
|
||||
let thumbnailData = value._0
|
||||
@ -1079,7 +1079,6 @@ public func avatarGalleryThumbnailPhoto(account: Account, representations: [Imag
|
||||
let fullSizeComplete = value._2
|
||||
|
||||
return { arguments in
|
||||
assertNotOnMainThread()
|
||||
let context = DrawingContext(size: arguments.drawingSize, clear: true)
|
||||
|
||||
let drawingRect = arguments.drawingRect
|
||||
|
@ -339,15 +339,19 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan
|
||||
}
|
||||
}
|
||||
|
||||
public func updatePeerPhotoExisting(network: Network, reference: TelegramMediaImageReference) -> Signal<Void, NoError> {
|
||||
public func updatePeerPhotoExisting(network: Network, reference: TelegramMediaImageReference) -> Signal<TelegramMediaImage?, NoError> {
|
||||
switch reference {
|
||||
case let .cloud(imageId, accessHash, fileReference):
|
||||
return network.request(Api.functions.photos.updateProfilePhoto(id: .inputPhoto(id: imageId, accessHash: accessHash, fileReference: Buffer(data: fileReference))))
|
||||
|> `catch` { _ -> Signal<Api.photos.Photo, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|> mapToSignal { _ -> Signal<Void, NoError> in
|
||||
return .complete()
|
||||
|> mapToSignal { photo -> Signal<TelegramMediaImage?, NoError> in
|
||||
if case let .photo(photo, _) = photo {
|
||||
return .single(telegramMediaImageFromApiPhoto(photo))
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -634,7 +634,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
if let size = self.validLayout {
|
||||
self.playbackProgress = position
|
||||
self.loading = loading
|
||||
self.updateItems(size: size, transition: .immediate, stripTransition: .animated(duration: 0.3, curve: .spring))
|
||||
self.updateStrips(size: size, itemsAdded: false, stripTransition: .animated(duration: 0.3, curve: .spring))
|
||||
}
|
||||
}
|
||||
|
||||
@ -911,17 +911,19 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
case .cancelled, .ended:
|
||||
let translation = recognizer.translation(in: self.view)
|
||||
let velocity = recognizer.velocity(in: self.view)
|
||||
var directionIsToRight = false
|
||||
var directionIsToRight: Bool?
|
||||
if abs(velocity.x) > 10.0 {
|
||||
directionIsToRight = velocity.x < 0.0
|
||||
} else {
|
||||
directionIsToRight = translation.x > self.bounds.width / 2.0
|
||||
} else if abs(transitionFraction) > 0.5 {
|
||||
directionIsToRight = transitionFraction < 0.0
|
||||
}
|
||||
var updatedIndex = self.currentIndex
|
||||
if directionIsToRight {
|
||||
updatedIndex = min(updatedIndex + 1, self.items.count - 1)
|
||||
} else {
|
||||
updatedIndex = max(updatedIndex - 1, 0)
|
||||
if let directionIsToRight = directionIsToRight {
|
||||
if directionIsToRight {
|
||||
updatedIndex = min(updatedIndex + 1, self.items.count - 1)
|
||||
} else {
|
||||
updatedIndex = max(updatedIndex - 1, 0)
|
||||
}
|
||||
}
|
||||
let previousIndex = self.currentIndex
|
||||
self.currentIndex = updatedIndex
|
||||
@ -1089,6 +1091,80 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
self.updateItems(size: size, transition: transition, stripTransition: transition)
|
||||
}
|
||||
|
||||
private func updateStrips(size: CGSize, itemsAdded: Bool, stripTransition: ContainedViewLayoutTransition) {
|
||||
let hadOneStripNode = self.stripNodes.count == 1
|
||||
if self.stripNodes.count != self.items.count {
|
||||
if self.stripNodes.count < self.items.count {
|
||||
for _ in 0 ..< self.items.count - self.stripNodes.count {
|
||||
let stripNode = ASImageNode()
|
||||
stripNode.displaysAsynchronously = false
|
||||
stripNode.displayWithoutProcessing = true
|
||||
stripNode.image = self.activeStripImage
|
||||
stripNode.alpha = 0.2
|
||||
self.stripNodes.append(stripNode)
|
||||
self.stripContainerNode.addSubnode(stripNode)
|
||||
}
|
||||
} else {
|
||||
for i in (self.items.count ..< self.stripNodes.count).reversed() {
|
||||
self.stripNodes[i].removeFromSupernode()
|
||||
self.stripNodes.remove(at: i)
|
||||
}
|
||||
}
|
||||
self.stripContainerNode.addSubnode(self.activeStripNode)
|
||||
self.stripContainerNode.addSubnode(self.loadingStripNode)
|
||||
}
|
||||
if self.appliedStripNodeCurrentIndex != self.currentIndex || itemsAdded {
|
||||
if !self.itemNodes.isEmpty {
|
||||
self.appliedStripNodeCurrentIndex = self.currentIndex
|
||||
}
|
||||
|
||||
if let currentItemNode = self.currentItemNode {
|
||||
self.positionDisposable.set((currentItemNode.mediaStatus
|
||||
|> deliverOnMainQueue).start(next: { [weak self] statusAndVideoStartTimestamp in
|
||||
if let strongSelf = self {
|
||||
strongSelf.playerStatus = statusAndVideoStartTimestamp
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.positionDisposable.set(nil)
|
||||
}
|
||||
}
|
||||
if hadOneStripNode && self.stripNodes.count > 1 {
|
||||
self.stripContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
}
|
||||
let stripInset: CGFloat = 8.0
|
||||
let stripSpacing: CGFloat = 4.0
|
||||
let stripWidth: CGFloat = max(5.0, floor((size.width - stripInset * 2.0 - stripSpacing * CGFloat(self.stripNodes.count - 1)) / CGFloat(self.stripNodes.count)))
|
||||
let currentStripMinX = stripInset + CGFloat(self.currentIndex) * (stripWidth + stripSpacing)
|
||||
let currentStripMidX = floor(currentStripMinX + stripWidth / 2.0)
|
||||
let lastStripMaxX = stripInset + CGFloat(self.stripNodes.count - 1) * (stripWidth + stripSpacing) + stripWidth
|
||||
let stripOffset: CGFloat = min(0.0, max(size.width - stripInset - lastStripMaxX, size.width / 2.0 - currentStripMidX))
|
||||
for i in 0 ..< self.stripNodes.count {
|
||||
let stripX: CGFloat = stripInset + CGFloat(i) * (stripWidth + stripSpacing)
|
||||
if i == 0 && self.stripNodes.count == 1 {
|
||||
self.stripNodes[i].isHidden = true
|
||||
} else {
|
||||
self.stripNodes[i].isHidden = false
|
||||
}
|
||||
let stripFrame = CGRect(origin: CGPoint(x: stripOffset + stripX, y: 0.0), size: CGSize(width: stripWidth + 1.0, height: 2.0))
|
||||
stripTransition.updateFrame(node: self.stripNodes[i], frame: stripFrame)
|
||||
}
|
||||
|
||||
if self.currentIndex >= 0 && self.currentIndex < self.stripNodes.count {
|
||||
var frame = self.stripNodes[self.currentIndex].frame
|
||||
stripTransition.updateFrame(node: self.loadingStripNode, frame: frame)
|
||||
if let playbackProgress = self.playbackProgress {
|
||||
frame.size.width = max(frame.size.height, frame.size.width * playbackProgress)
|
||||
}
|
||||
stripTransition.updateFrameAdditive(node: self.activeStripNode, frame: frame)
|
||||
stripTransition.updateAlpha(node: self.activeStripNode, alpha: self.loading ? 0.0 : 1.0)
|
||||
stripTransition.updateAlpha(node: self.loadingStripNode, alpha: self.loading ? 1.0 : 0.0)
|
||||
|
||||
self.activeStripNode.isHidden = self.stripNodes.count < 2
|
||||
self.loadingStripNode.isHidden = self.stripNodes.count < 2 || !self.loading
|
||||
}
|
||||
}
|
||||
|
||||
private func updateItems(size: CGSize, update: Bool = false, transition: ContainedViewLayoutTransition, stripTransition: ContainedViewLayoutTransition, synchronous: Bool = false) {
|
||||
var validIds: [WrappedMediaResourceId] = []
|
||||
var addedItemNodesForAdditiveTransition: [PeerInfoAvatarListItemNode] = []
|
||||
@ -1149,77 +1225,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
let hadOneStripNode = self.stripNodes.count == 1
|
||||
if self.stripNodes.count != self.items.count {
|
||||
if self.stripNodes.count < self.items.count {
|
||||
for _ in 0 ..< self.items.count - self.stripNodes.count {
|
||||
let stripNode = ASImageNode()
|
||||
stripNode.displaysAsynchronously = false
|
||||
stripNode.displayWithoutProcessing = true
|
||||
stripNode.image = self.activeStripImage
|
||||
stripNode.alpha = 0.2
|
||||
self.stripNodes.append(stripNode)
|
||||
self.stripContainerNode.addSubnode(stripNode)
|
||||
}
|
||||
} else {
|
||||
for i in (self.items.count ..< self.stripNodes.count).reversed() {
|
||||
self.stripNodes[i].removeFromSupernode()
|
||||
self.stripNodes.remove(at: i)
|
||||
}
|
||||
}
|
||||
self.stripContainerNode.addSubnode(self.activeStripNode)
|
||||
self.stripContainerNode.addSubnode(self.loadingStripNode)
|
||||
}
|
||||
if self.appliedStripNodeCurrentIndex != self.currentIndex || itemsAdded {
|
||||
if !self.itemNodes.isEmpty {
|
||||
self.appliedStripNodeCurrentIndex = self.currentIndex
|
||||
}
|
||||
|
||||
if let currentItemNode = self.currentItemNode {
|
||||
self.positionDisposable.set((currentItemNode.mediaStatus
|
||||
|> deliverOnMainQueue).start(next: { [weak self] statusAndVideoStartTimestamp in
|
||||
if let strongSelf = self {
|
||||
strongSelf.playerStatus = statusAndVideoStartTimestamp
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
self.positionDisposable.set(nil)
|
||||
}
|
||||
}
|
||||
if hadOneStripNode && self.stripNodes.count > 1 {
|
||||
self.stripContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
}
|
||||
let stripInset: CGFloat = 8.0
|
||||
let stripSpacing: CGFloat = 4.0
|
||||
let stripWidth: CGFloat = max(5.0, floor((size.width - stripInset * 2.0 - stripSpacing * CGFloat(self.stripNodes.count - 1)) / CGFloat(self.stripNodes.count)))
|
||||
let currentStripMinX = stripInset + CGFloat(self.currentIndex) * (stripWidth + stripSpacing)
|
||||
let currentStripMidX = floor(currentStripMinX + stripWidth / 2.0)
|
||||
let lastStripMaxX = stripInset + CGFloat(self.stripNodes.count - 1) * (stripWidth + stripSpacing) + stripWidth
|
||||
let stripOffset: CGFloat = min(0.0, max(size.width - stripInset - lastStripMaxX, size.width / 2.0 - currentStripMidX))
|
||||
for i in 0 ..< self.stripNodes.count {
|
||||
let stripX: CGFloat = stripInset + CGFloat(i) * (stripWidth + stripSpacing)
|
||||
if i == 0 && self.stripNodes.count == 1 {
|
||||
self.stripNodes[i].isHidden = true
|
||||
} else {
|
||||
self.stripNodes[i].isHidden = false
|
||||
}
|
||||
let stripFrame = CGRect(origin: CGPoint(x: stripOffset + stripX, y: 0.0), size: CGSize(width: stripWidth + 1.0, height: 2.0))
|
||||
stripTransition.updateFrame(node: self.stripNodes[i], frame: stripFrame)
|
||||
}
|
||||
|
||||
if self.currentIndex >= 0 && self.currentIndex < self.stripNodes.count {
|
||||
var frame = self.stripNodes[self.currentIndex].frame
|
||||
stripTransition.updateFrame(node: self.loadingStripNode, frame: frame)
|
||||
if let playbackProgress = self.playbackProgress {
|
||||
frame.size.width = max(frame.size.height, frame.size.width * playbackProgress)
|
||||
}
|
||||
stripTransition.updateFrameAdditive(node: self.activeStripNode, frame: frame)
|
||||
stripTransition.updateAlpha(node: self.activeStripNode, alpha: self.loading ? 0.0 : 1.0)
|
||||
stripTransition.updateAlpha(node: self.loadingStripNode, alpha: self.loading ? 1.0 : 0.0)
|
||||
|
||||
self.activeStripNode.isHidden = self.stripNodes.count < 2
|
||||
self.loadingStripNode.isHidden = self.stripNodes.count < 2 || !self.loading
|
||||
}
|
||||
self.updateStrips(size: size, itemsAdded: itemsAdded, stripTransition: stripTransition)
|
||||
|
||||
if let item = self.items.first, let itemNode = self.itemNodes[item.id] {
|
||||
if !self.didSetReady {
|
||||
|
Loading…
x
Reference in New Issue
Block a user