Video avatar fixes

This commit is contained in:
Ilya Laktyushin 2020-07-14 13:07:59 +03:00
parent 118422e26c
commit 65c6e51e2c
4 changed files with 53 additions and 53 deletions

View File

@ -437,7 +437,8 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
}) })
} else if case let .roundRect(cornerRadius) = self.sourceCorners { } else if case let .roundRect(cornerRadius) = self.sourceCorners {
let scale = scaledLocalImageViewBounds.width / transformedCopyViewFinalFrame.width let scale = scaledLocalImageViewBounds.width / transformedCopyViewFinalFrame.width
self.contentNode.layer.animate(from: (cornerRadius * scale) as NSNumber, to: 0.0 as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18, removeOnCompletion: false, completion: { [weak self] value in let selfScale = transformedCopyViewFinalFrame.width / transformedSelfFrame.width
self.contentNode.layer.animate(from: (cornerRadius * scale * selfScale) as NSNumber, to: 0.0 as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18, removeOnCompletion: false, completion: { [weak self] value in
if value { if value {
self?.contentNode.clipsToBounds = false self?.contentNode.clipsToBounds = false
} }
@ -466,13 +467,19 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
let copyView = maybeCopyView! let copyView = maybeCopyView!
if case .round = self.sourceCorners { var sourceHasRoundCorners = false
if case .none = self.sourceCorners {
} else {
sourceHasRoundCorners = true
}
if sourceHasRoundCorners {
self.view.insertSubview(copyView, belowSubview: self.scrollNode.view) self.view.insertSubview(copyView, belowSubview: self.scrollNode.view)
} }
copyView.frame = transformedSelfFrame copyView.frame = transformedSelfFrame
let surfaceCopyView = node.2().0! let surfaceCopyView = node.2().0!
if case .none = self.sourceCorners { if !sourceHasRoundCorners {
addToTransitionSurface(surfaceCopyView) addToTransitionSurface(surfaceCopyView)
} }
@ -539,7 +546,8 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
self.contentNode.layer.animate(from: 0.0 as NSNumber, to: (self.contentNode.frame.width / 2.0) as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18 * durationFactor, removeOnCompletion: false) self.contentNode.layer.animate(from: 0.0 as NSNumber, to: (self.contentNode.frame.width / 2.0) as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18 * durationFactor, removeOnCompletion: false)
} else if case let .roundRect(cornerRadius) = self.sourceCorners { } else if case let .roundRect(cornerRadius) = self.sourceCorners {
let scale = scaledLocalImageViewBounds.width / transformedCopyViewInitialFrame.width let scale = scaledLocalImageViewBounds.width / transformedCopyViewInitialFrame.width
self.contentNode.layer.animate(from: 0.0 as NSNumber, to: (cornerRadius * scale) as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18 * durationFactor, removeOnCompletion: false) let selfScale = transformedCopyViewInitialFrame.width / transformedSelfFrame.width
self.contentNode.layer.animate(from: 0.0 as NSNumber, to: (cornerRadius * scale * selfScale) as NSNumber, keyPath: "cornerRadius", timingFunction: CAMediaTimingFunctionName.default.rawValue, duration: 0.18 * durationFactor, removeOnCompletion: false)
} }
self.statusNodeContainer.layer.animatePosition(from: self.statusNodeContainer.position, to: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) self.statusNodeContainer.layer.animatePosition(from: self.statusNodeContainer.position, to: CGPoint(x: transformedSuperFrame.midX, y: transformedSuperFrame.midY), duration: 0.25, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)

View File

@ -263,11 +263,12 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan
} }
} }
|> mapToSignal { result, resource, videoResource -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in |> mapToSignal { result, resource, videoResource -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
if case .complete = result, let videoResource = videoResource { if case .complete = result {
return fetchAndUpdateCachedPeerData(accountPeerId: accountPeerId, peerId: peer.id, network: network, postbox: postbox) return fetchAndUpdateCachedPeerData(accountPeerId: accountPeerId, peerId: peer.id, network: network, postbox: postbox)
|> castError(UploadPeerPhotoError.self) |> castError(UploadPeerPhotoError.self)
|> mapToSignal { status -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in |> mapToSignal { status -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
return postbox.transaction { transaction in return postbox.transaction { transaction in
if let videoResource = videoResource {
let cachedData = transaction.getPeerCachedData(peerId: peer.id) let cachedData = transaction.getPeerCachedData(peerId: peer.id)
if let cachedData = cachedData as? CachedChannelData { if let cachedData = cachedData as? CachedChannelData {
if let photo = cachedData.photo { if let photo = cachedData.photo {
@ -282,6 +283,7 @@ public func updatePeerPhotoInternal(postbox: Postbox, network: Network, stateMan
} }
} }
} }
}
return result return result
} }
|> castError(UploadPeerPhotoError.self) |> castError(UploadPeerPhotoError.self)

View File

@ -1237,7 +1237,6 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode {
self.addSubnode(self.imageNode) self.addSubnode(self.imageNode)
self.addSubnode(self.updatingAvatarOverlay) self.addSubnode(self.updatingAvatarOverlay)
self.addSubnode(self.statusNode) self.addSubnode(self.statusNode)
self.addSubnode(self.iconNode)
} }
func updateTransitionFraction(_ fraction: CGFloat, transition: ContainedViewLayoutTransition) { func updateTransitionFraction(_ fraction: CGFloat, transition: ContainedViewLayoutTransition) {
@ -1255,11 +1254,9 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode {
let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .linear) let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .linear)
if canEditPeerInfo(context: self.context, peer: peer) { if canEditPeerInfo(context: self.context, peer: peer) {
var overlayHidden = false var overlayHidden = true
var iconHidden = false
if let updatingAvatar = updatingAvatar { if let updatingAvatar = updatingAvatar {
overlayHidden = false overlayHidden = false
iconHidden = true
self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: max(0.027, uploadProgress ?? 0.0), cancelEnabled: true)) self.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: max(0.027, uploadProgress ?? 0.0), cancelEnabled: true))
@ -1272,38 +1269,21 @@ final class PeerInfoEditingAvatarOverlayNode: ASDisplayNode {
} }
} }
transition.updateAlpha(node: self.iconNode, alpha: iconHidden ? 0.0 : 1.0)
transition.updateAlpha(node: self.updatingAvatarOverlay, alpha: overlayHidden ? 0.0 : 1.0) transition.updateAlpha(node: self.updatingAvatarOverlay, alpha: overlayHidden ? 0.0 : 1.0)
} else { } else {
var immediately = self.currentRepresentation == nil
if isEditing {
immediately = immediately || peer.profileImageRepresentations.isEmpty
iconHidden = peer.profileImageRepresentations.isEmpty
overlayHidden = peer.profileImageRepresentations.isEmpty
} else {
iconHidden = true
overlayHidden = true
}
let targetIconAlpha: CGFloat = iconHidden ? 0.0 : 1.0
let targetOverlayAlpha: CGFloat = overlayHidden ? 0.0 : 1.0 let targetOverlayAlpha: CGFloat = overlayHidden ? 0.0 : 1.0
if self.updatingAvatarOverlay.alpha != targetOverlayAlpha || self.iconNode.alpha != targetIconAlpha { if self.updatingAvatarOverlay.alpha != targetOverlayAlpha {
let update = { let update = {
self.statusNode.transitionToState(.none) self.statusNode.transitionToState(.none)
self.currentRepresentation = nil self.currentRepresentation = nil
self.imageNode.setSignal(.single(nil)) self.imageNode.setSignal(.single(nil))
transition.updateAlpha(node: self.iconNode, alpha: iconHidden ? 0.0 : 1.0)
transition.updateAlpha(node: self.updatingAvatarOverlay, alpha: overlayHidden ? 0.0 : 1.0) transition.updateAlpha(node: self.updatingAvatarOverlay, alpha: overlayHidden ? 0.0 : 1.0)
} }
if immediately {
update()
} else {
Queue.mainQueue().after(0.3) { Queue.mainQueue().after(0.3) {
update() update()
} }
} }
} }
}
if !overlayHidden && self.updatingAvatarOverlay.image == nil { if !overlayHidden && self.updatingAvatarOverlay.image == nil {
self.updatingAvatarOverlay.image = generateFilledCircleImage(diameter: avatarSize, color: UIColor(white: 0.0, alpha: 0.4), backgroundColor: nil) self.updatingAvatarOverlay.image = generateFilledCircleImage(diameter: avatarSize, color: UIColor(white: 0.0, alpha: 0.4), backgroundColor: nil)
} }
@ -2121,6 +2101,8 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode {
private let context: AccountContext private let context: AccountContext
private let requestUpdateLayout: () -> Void private let requestUpdateLayout: () -> Void
var requestEditing: (() -> Void)?
let avatarNode: PeerInfoEditingAvatarNode let avatarNode: PeerInfoEditingAvatarNode
let avatarTextNode: ImmediateTextNode let avatarTextNode: ImmediateTextNode
let avatarButtonNode: HighlightableButtonNode let avatarButtonNode: HighlightableButtonNode
@ -2145,7 +2127,7 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode {
} }
@objc private func textPressed() { @objc private func textPressed() {
self.avatarNode.tapped?(true) self.requestEditing?()
} }
func editingTextForKey(_ key: PeerInfoHeaderTextFieldNodeKey) -> String? { func editingTextForKey(_ key: PeerInfoHeaderTextFieldNodeKey) -> String? {
@ -2414,10 +2396,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.addSubnode(self.separatorNode) self.addSubnode(self.separatorNode)
self.avatarListNode.avatarContainerNode.tapped = { [weak self] in self.avatarListNode.avatarContainerNode.tapped = { [weak self] in
self?.initiateAvatarExpansion() self?.initiateAvatarExpansion(gallery: false)
} }
self.editingContentNode.avatarNode.tapped = { [weak self] confirm in self.editingContentNode.avatarNode.tapped = { [weak self] confirm in
self?.requestOpenAvatarForEditing?(confirm) self?.initiateAvatarExpansion(gallery: true)
}
self.editingContentNode.requestEditing = { [weak self] in
self?.requestOpenAvatarForEditing?(true)
} }
self.avatarListNode.itemsUpdated = { [weak self] items in self.avatarListNode.itemsUpdated = { [weak self] items in
@ -2450,8 +2435,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} }
} }
func initiateAvatarExpansion() { func initiateAvatarExpansion(gallery: Bool) {
if self.isAvatarExpanded { if self.isAvatarExpanded || gallery {
if let currentEntry = self.avatarListNode.listContainerNode.currentEntry { if let currentEntry = self.avatarListNode.listContainerNode.currentEntry {
self.requestAvatarExpansion?(true, self.avatarListNode.listContainerNode.galleryEntries, self.avatarListNode.listContainerNode.currentEntry, self.avatarTransitionArguments(entry: currentEntry)) self.requestAvatarExpansion?(true, self.avatarListNode.listContainerNode.galleryEntries, self.avatarListNode.listContainerNode.currentEntry, self.avatarTransitionArguments(entry: currentEntry))
} }
@ -2493,8 +2478,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
func updateAvatarIsHidden(entry: AvatarGalleryEntry?) { func updateAvatarIsHidden(entry: AvatarGalleryEntry?) {
if let entry = entry { if let entry = entry {
self.avatarListNode.avatarContainerNode.avatarNode.isHidden = entry == self.avatarListNode.listContainerNode.galleryEntries.first self.avatarListNode.avatarContainerNode.avatarNode.isHidden = entry == self.avatarListNode.listContainerNode.galleryEntries.first
self.editingContentNode.avatarNode.isHidden = entry == self.avatarListNode.listContainerNode.galleryEntries.first
} else { } else {
self.avatarListNode.avatarContainerNode.avatarNode.isHidden = false self.avatarListNode.avatarContainerNode.avatarNode.isHidden = false
self.editingContentNode.avatarNode.isHidden = false
} }
self.avatarListNode.listContainerNode.updateEntryIsHidden(entry: entry) self.avatarListNode.listContainerNode.updateEntryIsHidden(entry: entry)
} }

View File

@ -2074,7 +2074,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
} }
self.headerNode.requestAvatarExpansion = { [weak self] gallery, entries, centralEntry, _ in self.headerNode.requestAvatarExpansion = { [weak self] gallery, entries, centralEntry, _ in
guard let strongSelf = self, let peer = strongSelf.data?.peer, peer.smallProfileImage != nil else { guard let strongSelf = self, let peer = strongSelf.data?.peer else {
return return
} }
@ -2085,7 +2085,13 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false)
} }
return return
} else if !gallery { }
guard peer.smallProfileImage != nil else {
return
}
if !gallery {
let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring)
strongSelf.headerNode.updateIsAvatarExpanded(true, transition: transition) strongSelf.headerNode.updateIsAvatarExpanded(true, transition: transition)
strongSelf.updateNavigationExpansionPresentation(isExpanded: true, animated: true) strongSelf.updateNavigationExpansionPresentation(isExpanded: true, animated: true)
@ -5282,20 +5288,17 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, transition: transition, additive: additive) let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: layout.safeInsets.left, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, transition: transition, additive: additive)
} }
let effectiveAreaExpansionFraction: CGFloat
if self.isSettings {
let paneAreaExpansionDistance: CGFloat = 32.0 let paneAreaExpansionDistance: CGFloat = 32.0
let effectiveAreaExpansionFraction: CGFloat
if self.state.isEditing {
effectiveAreaExpansionFraction = 0.0
} else if self.isSettings {
var paneAreaExpansionDelta = (self.headerNode.frame.maxY - navigationHeight) - self.scrollNode.view.contentOffset.y var paneAreaExpansionDelta = (self.headerNode.frame.maxY - navigationHeight) - self.scrollNode.view.contentOffset.y
paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance))
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
} else if self.state.isEditing {
effectiveAreaExpansionFraction = 0.0
} else { } else {
let paneAreaExpansionDistance: CGFloat = 32.0
var paneAreaExpansionDelta = (self.paneContainerNode.frame.minY - navigationHeight) - self.scrollNode.view.contentOffset.y var paneAreaExpansionDelta = (self.paneContainerNode.frame.minY - navigationHeight) - self.scrollNode.view.contentOffset.y
paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance)) paneAreaExpansionDelta = max(0.0, min(paneAreaExpansionDelta, paneAreaExpansionDistance))
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
} }
@ -5396,7 +5399,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
self.canOpenAvatarByDragging = false self.canOpenAvatarByDragging = false
let contentOffset = scrollView.contentOffset.y let contentOffset = scrollView.contentOffset.y
scrollView.panGestureRecognizer.isEnabled = false scrollView.panGestureRecognizer.isEnabled = false
self.headerNode.initiateAvatarExpansion() self.headerNode.initiateAvatarExpansion(gallery: true)
scrollView.panGestureRecognizer.isEnabled = true scrollView.panGestureRecognizer.isEnabled = true
scrollView.contentOffset = CGPoint(x: 0.0, y: contentOffset) scrollView.contentOffset = CGPoint(x: 0.0, y: contentOffset)
UIView.animate(withDuration: 0.1) { UIView.animate(withDuration: 0.1) {