mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit 'b618777883809b306d7ff86423bf580994758ddf' into beta
This commit is contained in:
commit
462f2a7117
@ -38,13 +38,15 @@ public final class ManagedAnimationState {
|
||||
guard let path = item.source.path else {
|
||||
return nil
|
||||
}
|
||||
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
||||
guard var data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
|
||||
return nil
|
||||
}
|
||||
guard let unpackedData = TGGUnzipData(data, 5 * 1024 * 1024) else {
|
||||
return nil
|
||||
if path.hasSuffix(".json") {
|
||||
|
||||
} 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
|
||||
}
|
||||
resolvedInstance = instance
|
||||
@ -92,7 +94,10 @@ public enum ManagedAnimationSource: Equatable {
|
||||
var path: String? {
|
||||
switch self {
|
||||
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):
|
||||
return account.postbox.mediaBox.completedResourcePath(resource._asResource())
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
||||
if self.animationNode == nil {
|
||||
let animationNode = AnimatedStickerNode()
|
||||
self.animationNode = animationNode
|
||||
self.addSubnode(animationNode)
|
||||
self.insertSubnode(animationNode, aboveSubnode: self.imageNode)
|
||||
animationNode.started = { [weak self] in
|
||||
self?.imageNode.isHidden = true
|
||||
self?.removePlaceholder(animated: false)
|
||||
@ -196,16 +196,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
|
||||
let bounds = self.bounds
|
||||
let boundsSide = min(bounds.size.width - 14.0, bounds.size.height - 14.0)
|
||||
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 = item, let dimensions = item.file.dimensions?.cgSize {
|
||||
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) {
|
||||
|
@ -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
@ -7573,7 +7573,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|> switchToLatest
|
||||
|> deliverOnMainQueue).start(next: { [weak self] added in
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -21,6 +21,9 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
|
||||
case _ as TelegramMediaImage:
|
||||
return (strings.Message_Photo, true)
|
||||
case let file as TelegramMediaFile:
|
||||
if file.isVideoSticker || file.isAnimatedSticker {
|
||||
return (strings.Message_Sticker, true)
|
||||
}
|
||||
var fileName: String = strings.Message_File
|
||||
for attribute in file.attributes {
|
||||
switch attribute {
|
||||
@ -52,9 +55,6 @@ func textStringForForwardedMessage(_ message: Message, strings: PresentationStri
|
||||
break
|
||||
}
|
||||
}
|
||||
if file.isAnimatedSticker {
|
||||
return (strings.Message_Sticker, true)
|
||||
}
|
||||
return (fileName, true)
|
||||
case _ as TelegramMediaContact:
|
||||
return (strings.Message_Contact, true)
|
||||
|
@ -21,6 +21,7 @@ import TelegramUIPreferences
|
||||
import PeerInfoAvatarListNode
|
||||
import AnimationUI
|
||||
import ContextUI
|
||||
import ManagedAnimationNode
|
||||
|
||||
enum PeerInfoHeaderButtonKey: Hashable {
|
||||
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 {
|
||||
let containerNode: ContextControllerSourceNode
|
||||
let contextSourceNode: ContextReferenceContentNode
|
||||
private let regularTextNode: ImmediateTextNode
|
||||
private let whiteTextNode: ImmediateTextNode
|
||||
private let iconNode: ASImageNode
|
||||
private var animationNode: AnimationNode?
|
||||
private var animationNode: MoreIconNode?
|
||||
|
||||
private var key: PeerInfoHeaderNavigationButtonKey?
|
||||
private var theme: PresentationTheme?
|
||||
@ -982,11 +1069,13 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
}
|
||||
|
||||
@objc private func pressed() {
|
||||
self.animationNode?.play()
|
||||
self.action?(self.contextSourceNode, nil)
|
||||
}
|
||||
|
||||
func update(key: PeerInfoHeaderNavigationButtonKey, presentationData: PresentationData, height: CGFloat) -> CGSize {
|
||||
let textSize: CGSize
|
||||
let isFirstTime = self.key == nil
|
||||
if self.key != key || self.theme !== presentationData.theme {
|
||||
self.key = key
|
||||
self.theme = presentationData.theme
|
||||
@ -995,6 +1084,8 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
var icon: UIImage?
|
||||
var isBold = false
|
||||
var isGestureEnabled = false
|
||||
var isAnimation = false
|
||||
var animationState: MoreIconNodeState = .more
|
||||
switch key {
|
||||
case .edit:
|
||||
text = presentationData.strings.Common_Edit
|
||||
@ -1005,18 +1096,24 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
text = presentationData.strings.Common_Select
|
||||
case .search:
|
||||
text = ""
|
||||
icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
|
||||
icon = nil// PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
|
||||
isAnimation = true
|
||||
animationState = .search
|
||||
case .editPhoto:
|
||||
text = presentationData.strings.Settings_EditPhoto
|
||||
case .editVideo:
|
||||
text = presentationData.strings.Settings_EditVideo
|
||||
case .more:
|
||||
text = ""
|
||||
icon = PresentationResourcesRootController.navigationMoreCircledIcon(presentationData.theme)
|
||||
icon = nil// PresentationResourcesRootController.navigationMoreCircledIcon(presentationData.theme)
|
||||
isGestureEnabled = true
|
||||
isAnimation = true
|
||||
animationState = .more
|
||||
case .qrCode:
|
||||
text = ""
|
||||
icon = PresentationResourcesRootController.navigationQrCodeIcon(presentationData.theme)
|
||||
case .moreToSearch:
|
||||
text = ""
|
||||
}
|
||||
self.accessibilityLabel = text
|
||||
self.containerNode.isGestureEnabled = isGestureEnabled
|
||||
@ -1027,6 +1124,26 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
self.whiteTextNode.attributedText = NSAttributedString(string: text, font: font, textColor: .white)
|
||||
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))
|
||||
let _ = self.whiteTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
|
||||
} else {
|
||||
@ -1039,7 +1156,16 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
self.regularTextNode.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)
|
||||
|
||||
let size = CGSize(width: image.size.width + inset * 2.0, height: height)
|
||||
@ -1066,6 +1192,7 @@ enum PeerInfoHeaderNavigationButtonKey {
|
||||
case editVideo
|
||||
case more
|
||||
case qrCode
|
||||
case moreToSearch
|
||||
}
|
||||
|
||||
struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
||||
@ -1187,20 +1314,26 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
for spec in rightButtons.reversed() {
|
||||
let buttonNode: PeerInfoHeaderNavigationButton
|
||||
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
|
||||
} else {
|
||||
wasAdded = true
|
||||
buttonNode = PeerInfoHeaderNavigationButton()
|
||||
self.rightButtonNodes[spec.key] = buttonNode
|
||||
self.rightButtonNodes[key] = buttonNode
|
||||
self.addSubnode(buttonNode)
|
||||
buttonNode.isWhite = self.isWhite
|
||||
buttonNode.action = { [weak self] _, gesture in
|
||||
guard let strongSelf = self, let buttonNode = strongSelf.rightButtonNodes[spec.key] else {
|
||||
return
|
||||
}
|
||||
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
|
||||
}
|
||||
buttonNode.action = { [weak self] _, gesture in
|
||||
guard let strongSelf = self, let buttonNode = strongSelf.rightButtonNodes[key] else {
|
||||
return
|
||||
}
|
||||
strongSelf.performAction?(spec.key, buttonNode.contextSourceNode, gesture)
|
||||
}
|
||||
let buttonSize = buttonNode.update(key: spec.key, presentationData: presentationData, height: size.height)
|
||||
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
|
||||
@ -1213,6 +1346,10 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
}
|
||||
let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
|
||||
if wasAdded {
|
||||
if key == .moreToSearch {
|
||||
buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
buttonNode.frame = buttonFrame
|
||||
buttonNode.alpha = 0.0
|
||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
@ -1223,20 +1360,37 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
}
|
||||
var removeKeys: [PeerInfoHeaderNavigationButtonKey] = []
|
||||
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)
|
||||
}
|
||||
}
|
||||
for key in removeKeys {
|
||||
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 {
|
||||
var nextRegularButtonOrigin = size.width - 16.0
|
||||
var nextExpandedButtonOrigin = size.width - 16.0
|
||||
|
||||
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
|
||||
var nextButtonOrigin = spec.isForExpandedView ? nextExpandedButtonOrigin : nextRegularButtonOrigin
|
||||
let buttonFrame = CGRect(origin: CGPoint(x: nextButtonOrigin - buttonSize.width, y: expandOffset + (spec.isForExpandedView ? maximumExpandOffset : 0.0)), size: buttonSize)
|
||||
|
@ -2835,7 +2835,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
||||
}
|
||||
case .qrCode:
|
||||
strongSelf.openQrCode()
|
||||
case .editPhoto, .editVideo:
|
||||
case .editPhoto, .editVideo, .moreToSearch:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
case let .animated(resource, isVideo):
|
||||
let 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):
|
||||
|
Loading…
x
Reference in New Issue
Block a user