Merge commit 'b618777883809b306d7ff86423bf580994758ddf' into beta

This commit is contained in:
Ali 2022-01-28 21:35:19 +04:00
commit 462f2a7117
9 changed files with 200 additions and 36 deletions

View File

@ -38,13 +38,15 @@ public final class ManagedAnimationState {
guard let path = item.source.path else { guard let path = item.source.path else {
return nil return nil
} }
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else { guard var data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
return nil return nil
} }
guard let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) else { if path.hasSuffix(".json") {
return nil
} else if let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) {
data = unpackedData
} }
guard let instance = LottieInstance(data: unpackedData, fitzModifier: .none, cacheKey: item.source.cacheKey) else { guard let instance = LottieInstance(data: data, fitzModifier: .none, cacheKey: item.source.cacheKey) else {
return nil return nil
} }
resolvedInstance = instance resolvedInstance = instance
@ -92,7 +94,10 @@ public enum ManagedAnimationSource: Equatable {
var path: String? { var path: String? {
switch self { switch self {
case let .local(name): case let .local(name):
return getAppBundle().path(forResource: name, ofType: "tgs") if let tgsPath = getAppBundle().path(forResource: name, ofType: "tgs") {
return tgsPath
}
return getAppBundle().path(forResource: name, ofType: "json")
case let .resource(account, resource): case let .resource(account, resource):
return account.postbox.mediaBox.completedResourcePath(resource._asResource()) return account.postbox.mediaBox.completedResourcePath(resource._asResource())
} }

View File

@ -153,7 +153,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
if self.animationNode == nil { if self.animationNode == nil {
let animationNode = AnimatedStickerNode() let animationNode = AnimatedStickerNode()
self.animationNode = animationNode self.animationNode = animationNode
self.addSubnode(animationNode) self.insertSubnode(animationNode, aboveSubnode: self.imageNode)
animationNode.started = { [weak self] in animationNode.started = { [weak self] in
self?.imageNode.isHidden = true self?.imageNode.isHidden = true
self?.removePlaceholder(animated: false) self?.removePlaceholder(animated: false)
@ -196,16 +196,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
let bounds = self.bounds let bounds = self.bounds
let boundsSide = min(bounds.size.width - 14.0, bounds.size.height - 14.0) let boundsSide = min(bounds.size.width - 14.0, bounds.size.height - 14.0)
let boundingSize = CGSize(width: boundsSide, height: boundsSide) let boundingSize = CGSize(width: boundsSide, height: boundsSide)
if let placeholderNode = self.placeholderNode {
let placeholderFrame = CGRect(origin: CGPoint(x: floor((bounds.width - boundingSize.width) / 2.0), y: floor((bounds.height - boundingSize.height) / 2.0)), size: boundingSize)
placeholderNode.frame = bounds
if let theme = self.theme, let (_, stickerItem) = self.currentState, let item = stickerItem {
placeholderNode.update(backgroundColor: theme.list.itemBlocksBackgroundColor, foregroundColor: theme.list.mediaPlaceholderColor, shimmeringColor: theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), data: item.file.immediateThumbnailData, size: placeholderFrame.size)
}
}
if let (_, item) = self.currentState { if let (_, item) = self.currentState {
if let item = item, let dimensions = item.file.dimensions?.cgSize { if let item = item, let dimensions = item.file.dimensions?.cgSize {
let imageSize = dimensions.aspectFitted(boundingSize) let imageSize = dimensions.aspectFitted(boundingSize)
@ -218,6 +209,18 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
} }
} }
} }
if let placeholderNode = self.placeholderNode {
let imageFrame = self.imageNode.frame
// let placeholderFrame = CGRect(origin: CGPoint(x: floor((bounds.width - boundingSize.width) / 2.0), y: floor((bounds.height - boundingSize.height) / 2.0)), size: boundingSize)
let placeholderFrame = imageFrame
placeholderNode.frame = imageFrame
if let theme = self.theme, let (_, stickerItem) = self.currentState, let item = stickerItem {
placeholderNode.update(backgroundColor: theme.list.itemBlocksBackgroundColor, foregroundColor: theme.list.mediaPlaceholderColor, shimmeringColor: theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.4), data: item.file.immediateThumbnailData, size: placeholderFrame.size)
}
}
} }
override func updateAbsoluteRect(_ absoluteRect: CGRect, within containerSize: CGSize) { override func updateAbsoluteRect(_ absoluteRect: CGRect, within containerSize: CGSize) {

View File

@ -0,0 +1 @@
{"v":"5.8.1","fr":60,"ip":0,"op":46,"w":300,"h":300,"nm":"more","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"more","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2,"l":2},"a":{"a":0,"k":[150,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-55.228,0],[0,55.229],[55.229,0],[0,-55.228]],"o":[[55.229,0],[0,-55.228],[-55.228,0],[0,55.229]],"v":[[23.5,123.5],[123.5,23.5],[23.5,-76.5],[-76.5,23.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":15,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[126.5,126.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"c","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,8.284],[8.284,0],[0,-8.284]],"o":[[8.284,0],[0,-8.284],[-8.284,0],[0,8.284]],"v":[[50,15],[65,0],[50,-15],[35,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":10,"s":[200,150],"to":[0,-5],"ti":[0,-2]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":20,"s":[200,120],"to":[0,2],"ti":[0,-5]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":30,"s":[200,162],"to":[0,5],"ti":[0,2]},{"t":40,"s":[200,150]}],"ix":2},"a":{"a":0,"k":[50,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":15,"s":[100,100]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":25,"s":[125,125]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":35,"s":[95,95]},{"t":45,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"3","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,8.284],[8.284,0],[0,-8.284]],"o":[[8.284,0],[0,-8.284],[-8.284,0],[0,8.284]],"v":[[0.5,15],[15.5,0],[0.5,-15],[-14.5,0]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":5,"s":[150,150],"to":[0,-5],"ti":[0,-2]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":15,"s":[150,120],"to":[0,2],"ti":[0,-5]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":25,"s":[150,162],"to":[0,5],"ti":[0,2]},{"t":35,"s":[150,150]}],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":10,"s":[100,100]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":20,"s":[125,125]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":30,"s":[95,95]},{"t":40,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"2","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-8.284,0],[0,8.284],[8.284,0],[0,-8.284]],"o":[[8.284,0],[0,-8.284],[-8.284,0],[0,8.284]],"v":[[-49,15],[-34,0],[-49,-15],[-64,0]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":0,"s":[100,150],"to":[0,-5],"ti":[0,-2]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":10,"s":[100,120],"to":[0,2],"ti":[0,-5]},{"i":{"x":0.5,"y":1},"o":{"x":0.5,"y":0},"t":20,"s":[100,162],"to":[0,5],"ti":[0,2]},{"t":30,"s":[100,150]}],"ix":2},"a":{"a":0,"k":[-50,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":5,"s":[100,100]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":15,"s":[125,125]},{"i":{"x":[0.5,0.5],"y":[1,1]},"o":{"x":[0.5,0.5],"y":[0,0]},"t":25,"s":[95,95]},{"t":35,"s":[100,100]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"1","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":-35,"op":47,"st":-38,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

View File

@ -7573,7 +7573,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|> switchToLatest |> switchToLatest
|> deliverOnMainQueue).start(next: { [weak self] added in |> deliverOnMainQueue).start(next: { [weak self] added in
if let strongSelf = self { if let strongSelf = self {
strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, text: added ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites), elevatedLayout: false, action: { _ in return false }), in: .current) strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, text: added ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites), elevatedLayout: true, action: { _ in return false }), with: nil)
} }
}) })
} }

View File

@ -21,6 +21,9 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
case _ as TelegramMediaImage: case _ as TelegramMediaImage:
return (strings.Message_Photo, true) return (strings.Message_Photo, true)
case let file as TelegramMediaFile: case let file as TelegramMediaFile:
if file.isVideoSticker || file.isAnimatedSticker {
return (strings.Message_Sticker, true)
}
var fileName: String = strings.Message_File var fileName: String = strings.Message_File
for attribute in file.attributes { for attribute in file.attributes {
switch attribute { switch attribute {
@ -52,9 +55,6 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
break break
} }
} }
if file.isAnimatedSticker {
return (strings.Message_Sticker, true)
}
return (fileName, true) return (fileName, true)
case _ as TelegramMediaContact: case _ as TelegramMediaContact:
return (strings.Message_Contact, true) return (strings.Message_Contact, true)

View File

@ -21,6 +21,7 @@ import TelegramUIPreferences
import PeerInfoAvatarListNode import PeerInfoAvatarListNode
import AnimationUI import AnimationUI
import ContextUI import ContextUI
import ManagedAnimationNode
enum PeerInfoHeaderButtonKey: Hashable { enum PeerInfoHeaderButtonKey: Hashable {
case message case message
@ -920,13 +921,99 @@ final class PeerInfoAvatarListNode: ASDisplayNode {
} }
} }
private enum MoreIconNodeState: Equatable {
case more
case search
case moreToSearch(Float)
}
private final class MoreIconNode: ManagedAnimationNode {
private let duration: Double = 0.21
private var iconState: MoreIconNodeState = .more
init() {
super.init(size: CGSize(width: 30.0, height: 30.0))
self.trackTo(item: ManagedAnimationItem(source: .local("anim_moretosearch"), frames: .range(startFrame: 0, endFrame: 0), duration: 0.0))
}
func play() {
if case .more = self.iconState {
self.trackTo(item: ManagedAnimationItem(source: .local("anim_moredots"), frames: .range(startFrame: 0, endFrame: 46), duration: 0.76))
}
}
func enqueueState(_ state: MoreIconNodeState, animated: Bool) {
guard self.iconState != state else {
return
}
let previousState = self.iconState
self.iconState = state
let source = ManagedAnimationSource.local("anim_moretosearch")
let totalLength: Int = 90
if animated {
switch previousState {
case .more:
switch state {
case .more:
break
case .search:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: 0, endFrame: totalLength), duration: self.duration))
case let .moreToSearch(progress):
let frame = Int(progress * Float(totalLength))
let duration = self.duration * Double(progress)
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: 0, endFrame: frame), duration: duration))
}
case .search:
switch state {
case .more:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: totalLength, endFrame: 0), duration: self.duration))
case .search:
break
case let .moreToSearch(progress):
let frame = Int(progress * Float(totalLength))
let duration = self.duration * Double((1.0 - progress))
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: totalLength, endFrame: frame), duration: duration))
}
case let .moreToSearch(currentProgress):
let currentFrame = Int(currentProgress * Float(totalLength))
switch state {
case .more:
let duration = self.duration * Double(currentProgress)
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: currentFrame, endFrame: 0), duration: duration))
case .search:
let duration = self.duration * (1.0 - Double(currentProgress))
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: currentFrame, endFrame: totalLength), duration: duration))
case let .moreToSearch(progress):
let frame = Int(progress * Float(totalLength))
let duration = self.duration * Double(abs(currentProgress - progress))
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: currentFrame, endFrame: frame), duration: duration))
}
}
} else {
switch state {
case .more:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: 0, endFrame: 0), duration: 0.0))
case .search:
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: totalLength, endFrame: totalLength), duration: 0.0))
case let .moreToSearch(progress):
let frame = Int(progress * Float(totalLength))
self.trackTo(item: ManagedAnimationItem(source: source, frames: .range(startFrame: frame, endFrame: frame), duration: 0.0))
}
}
}
}
final class PeerInfoHeaderNavigationButton: HighlightableButtonNode { final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
let containerNode: ContextControllerSourceNode let containerNode: ContextControllerSourceNode
let contextSourceNode: ContextReferenceContentNode let contextSourceNode: ContextReferenceContentNode
private let regularTextNode: ImmediateTextNode private let regularTextNode: ImmediateTextNode
private let whiteTextNode: ImmediateTextNode private let whiteTextNode: ImmediateTextNode
private let iconNode: ASImageNode private let iconNode: ASImageNode
private var animationNode: AnimationNode? private var animationNode: MoreIconNode?
private var key: PeerInfoHeaderNavigationButtonKey? private var key: PeerInfoHeaderNavigationButtonKey?
private var theme: PresentationTheme? private var theme: PresentationTheme?
@ -982,11 +1069,13 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
} }
@objc private func pressed() { @objc private func pressed() {
self.animationNode?.play()
self.action?(self.contextSourceNode, nil) self.action?(self.contextSourceNode, nil)
} }
func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData, height: CGFloat) -> CGSize { func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData, height: CGFloat) -> CGSize {
let textSize: CGSize let textSize: CGSize
let isFirstTime = self.key == nil
if self.key != key || self.theme !== presentationData.theme { if self.key != key || self.theme !== presentationData.theme {
self.key = key self.key = key
self.theme = presentationData.theme self.theme = presentationData.theme
@ -995,6 +1084,8 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
var icon: UIImage? var icon: UIImage?
var isBold = false var isBold = false
var isGestureEnabled = false var isGestureEnabled = false
var isAnimation = false
var animationState: MoreIconNodeState = .more
switch key { switch key {
case .edit: case .edit:
text = presentationData.strings.Common_Edit text = presentationData.strings.Common_Edit
@ -1005,18 +1096,24 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
text = presentationData.strings.Common_Select text = presentationData.strings.Common_Select
case .search: case .search:
text = "" text = ""
icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) icon = nil// PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
isAnimation = true
animationState = .search
case .editPhoto: case .editPhoto:
text = presentationData.strings.Settings_EditPhoto text = presentationData.strings.Settings_EditPhoto
case .editVideo: case .editVideo:
text = presentationData.strings.Settings_EditVideo text = presentationData.strings.Settings_EditVideo
case .more: case .more:
text = "" text = ""
icon = PresentationResourcesRootController.navigationMoreCircledIcon(presentationData.theme) icon = nil// PresentationResourcesRootController.navigationMoreCircledIcon(presentationData.theme)
isGestureEnabled = true isGestureEnabled = true
isAnimation = true
animationState = .more
case .qrCode: case .qrCode:
text = "" text = ""
icon = PresentationResourcesRootController.navigationQrCodeIcon(presentationData.theme) icon = PresentationResourcesRootController.navigationQrCodeIcon(presentationData.theme)
case .moreToSearch:
text = ""
} }
self.accessibilityLabel = text self.accessibilityLabel = text
self.containerNode.isGestureEnabled = isGestureEnabled self.containerNode.isGestureEnabled = isGestureEnabled
@ -1027,6 +1124,26 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white) self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white)
self.iconNode.image = icon self.iconNode.image = icon
if isAnimation {
self.iconNode.isHidden = true
let animationNode: MoreIconNode
if let current = self.animationNode {
animationNode = current
} else {
animationNode = MoreIconNode()
self.animationNode = animationNode
self.contextSourceNode.addSubnode(animationNode)
}
animationNode.customColor = presentationData.theme.rootController.navigationBar.accentTextColor
animationNode.enqueueState(animationState, animated: !isFirstTime)
} else {
self.iconNode.isHidden = false
if let current = self.animationNode {
self.animationNode = nil
current.removeFromSupernode()
}
}
textSize = self.regularTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) textSize = self.regularTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude)) let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
} else { } else {
@ -1039,7 +1156,16 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
self.regularTextNode.frame = textFrame self.regularTextNode.frame = textFrame
self.whiteTextNode.frame = textFrame self.whiteTextNode.frame = textFrame
if let image = self.iconNode.image { if let animationNode = self.animationNode {
let animationSize = CGSize(width: 30.0, height: 30.0)
animationNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - animationSize.height) / 2.0)), size: animationSize)
let size = CGSize(width: animationSize.width + inset * 2.0, height: height)
self.containerNode.frame = CGRect(origin: CGPoint(), size: size)
self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: size)
return size
} else if let image = self.iconNode.image {
self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size) self.iconNode.frame = CGRect(origin: CGPoint(x: inset, y: floor((height - image.size.height) / 2.0)), size: image.size)
let size = CGSize(width: image.size.width + inset * 2.0, height: height) let size = CGSize(width: image.size.width + inset * 2.0, height: height)
@ -1066,6 +1192,7 @@ enum PeerInfoHeaderNavigationButtonKey {
case editVideo case editVideo
case more case more
case qrCode case qrCode
case moreToSearch
} }
struct PeerInfoHeaderNavigationButtonSpec: Equatable { struct PeerInfoHeaderNavigationButtonSpec: Equatable {
@ -1187,20 +1314,26 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
for spec in rightButtons.reversed() { for spec in rightButtons.reversed() {
let buttonNode: PeerInfoHeaderNavigationButton let buttonNode: PeerInfoHeaderNavigationButton
var wasAdded = false var wasAdded = false
if let current = self.rightButtonNodes[spec.key] {
var key = spec.key
if key == .more || key == .search {
key = .moreToSearch
}
if let current = self.rightButtonNodes[key] {
buttonNode = current buttonNode = current
} else { } else {
wasAdded = true wasAdded = true
buttonNode = PeerInfoHeaderNavigationButton() buttonNode = PeerInfoHeaderNavigationButton()
self.rightButtonNodes[spec.key] = buttonNode self.rightButtonNodes[key] = buttonNode
self.addSubnode(buttonNode) self.addSubnode(buttonNode)
buttonNode.isWhite = self.isWhite buttonNode.isWhite = self.isWhite
buttonNode.action = { [weak self] _, gesture in }
guard let strongSelf = self, let buttonNode = strongSelf.rightButtonNodes[spec.key] else { buttonNode.action = { [weak self] _, gesture in
return guard let strongSelf = self, let buttonNode = strongSelf.rightButtonNodes[key] else {
} return
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
} }
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
} }
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height) let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height)
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
@ -1213,6 +1346,10 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
} }
let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction) let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
if wasAdded { if wasAdded {
if key == .moreToSearch {
buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
}
buttonNode.frame = buttonFrame buttonNode.frame = buttonFrame
buttonNode.alpha = 0.0 buttonNode.alpha = 0.0
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor) transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
@ -1223,20 +1360,37 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
} }
var removeKeys: [PeerInfoHeaderNavigationButtonKey] = [] var removeKeys: [PeerInfoHeaderNavigationButtonKey] = []
for (key, _) in self.rightButtonNodes { for (key, _) in self.rightButtonNodes {
if !rightButtons.contains(where: { $0.key == key }) { if key == .moreToSearch {
if !rightButtons.contains(where: { $0.key == .more || $0.key == .search }) {
removeKeys.append(key)
}
} else if !rightButtons.contains(where: { $0.key == key }) {
removeKeys.append(key) removeKeys.append(key)
} }
} }
for key in removeKeys { for key in removeKeys {
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) { if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) {
buttonNode.removeFromSupernode() if key == .moreToSearch {
buttonNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in
buttonNode?.removeFromSupernode()
})
buttonNode.layer.animateScale(from: 1.0, to: 0.001, duration: 0.2, removeOnCompletion: false)
} else {
buttonNode.removeFromSupernode()
}
} }
} }
} else { } else {
var nextRegularButtonOrigin = size.width - 16.0 var nextRegularButtonOrigin = size.width - 16.0
var nextExpandedButtonOrigin = size.width - 16.0 var nextExpandedButtonOrigin = size.width - 16.0
for spec in rightButtons.reversed() { for spec in rightButtons.reversed() {
if let buttonNode = self.rightButtonNodes[spec.key] { var key = spec.key
if key == .more || key == .search {
key = .moreToSearch
}
if let buttonNode = self.rightButtonNodes[key] {
let buttonSize = buttonNode.bounds.size let buttonSize = buttonNode.bounds.size
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize) let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize)

View File

@ -2835,7 +2835,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} }
case .qrCode: case .qrCode:
strongSelf.openQrCode() strongSelf.openQrCode()
case .editPhoto, .editVideo: case .editPhoto, .editVideo, .moreToSearch:
break break
} }
} }

View File

@ -424,7 +424,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
case let .animated(resource, isVideo): case let .animated(resource, isVideo):
let animatedStickerNode = AnimatedStickerNode() let animatedStickerNode = AnimatedStickerNode()
self.animatedStickerNode = animatedStickerNode self.animatedStickerNode = animatedStickerNode
animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: context.account, resource: resource._asResource(), isVideo: isVideo), width: 80, height: 80, mode: .cached) animatedStickerNode.setup(source: AnimatedStickerResourceSource(account: context.account, resource: resource._asResource(), isVideo: isVideo), width: 80, height: 80, mode: .direct(cachePathPrefix: nil))
} }
} }
case let .dice(dice, context, text, action): case let .dice(dice, context, text, action):