Stickers Import Improvements

This commit is contained in:
Ilya Laktyushin 2021-06-18 04:21:15 +03:00
parent d6bd5192a7
commit 920829490a
11 changed files with 5418 additions and 5240 deletions

View File

@ -6507,9 +6507,16 @@ Sorry for the inconvenience.";
"ImportStickerPack.RemoveFromImport" = "Remove From Import";
"ImportStickerPack.ChooseName" = "Choose Name";
"ImportStickerPack.ChooseNameDescription" = "Please choose a name for your set.";
"ImportStickerPack.GeneratingLink" = "generating link...";
"ImportStickerPack.CheckingLink" = "checking availability...";
"ImportStickerPack.ChooseLink" = "Choose Link";
"ImportStickerPack.ChooseLinkDescription" = "You can use a-z, 0-9 and underscores.";
"ImportStickerPack.LinkTaken" = "Sorry, this link is alreay taken.";
"ImportStickerPack.LinkAvailable" = "Link is available.";
"ImportStickerPack.ImportingStickers" = "Importing Stickers";
"ImportStickerPack.Of" = "%1$@ of %2$@ Imported";
"ImportStickerPack.InProgress" = "Please keep this window open\nuntil the import is completed.";
"ImportStickerPack.Create" = "Create";
"WallpaperPreview.PreviewBottomTextAnimatable" = "Tap the play button to view the background animation.";

View File

@ -86,11 +86,14 @@ open class AlertController: ViewController, StandalonePresentableController {
private let contentNode: AlertContentNode
private let allowInputInset: Bool
private weak var existingAlertController: AlertController?
public var dismissed: (() -> Void)?
public init(theme: AlertControllerTheme, contentNode: AlertContentNode, allowInputInset: Bool = true) {
public init(theme: AlertControllerTheme, contentNode: AlertContentNode, existingAlertController: AlertController? = nil, allowInputInset: Bool = true) {
self.theme = theme
self.contentNode = contentNode
self.existingAlertController = existingAlertController
self.allowInputInset = allowInputInset
super.init(navigationBarPresentationData: nil)
@ -108,6 +111,8 @@ open class AlertController: ViewController, StandalonePresentableController {
self.displayNode = AlertControllerNode(contentNode: self.contentNode, theme: self.theme, allowInputInset: self.allowInputInset)
self.displayNodeDidLoad()
self.controllerNode.existingAlertControllerNode = self.existingAlertController?.controllerNode
self.controllerNode.dismiss = { [weak self] in
if let strongSelf = self, strongSelf.contentNode.dismissOnOutsideTap {
strongSelf.controllerNode.animateOut {
@ -120,6 +125,9 @@ open class AlertController: ViewController, StandalonePresentableController {
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.existingAlertController?.dismiss(completion: nil)
self.existingAlertController = nil
self.controllerNode.animateIn()
}

View File

@ -3,6 +3,8 @@ import UIKit
import AsyncDisplayKit
final class AlertControllerNode: ASDisplayNode {
var existingAlertControllerNode: AlertControllerNode?
private let centerDimView: UIImageView
private let topDimView: UIView
private let bottomDimView: UIView
@ -90,6 +92,22 @@ final class AlertControllerNode: ASDisplayNode {
}
func animateIn() {
if let previousNode = self.existingAlertControllerNode {
let transition = ContainedViewLayoutTransition.animated(duration: 0.3, curve: .spring)
previousNode.position = previousNode.position.offsetBy(dx: -previousNode.frame.width, dy: 0.0)
self.addSubnode(previousNode)
let position = self.position
self.position = position.offsetBy(dx: self.frame.width, dy: 0.0)
transition.animateView {
self.position = position
} completion: { _ in
previousNode.removeFromSupernode()
}
self.existingAlertControllerNode = nil
} else {
self.centerDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
self.topDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
self.bottomDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
@ -103,6 +121,7 @@ final class AlertControllerNode: ASDisplayNode {
})
self.containerNode.layer.animateSpring(from: 0.8 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, removeOnCompletion: true, additive: false, completion: nil)
}
}
func animateOut(completion: @escaping () -> Void) {
self.containerNode.layer.removeAllAnimations()

View File

@ -1,5 +1,6 @@
import Foundation
import UIKit
import Postbox
public class ImportStickerPack {
public class Sticker: Equatable {
@ -15,6 +16,7 @@ public class ImportStickerPack {
let content: Content
let emojis: [String]
let uuid: UUID
var resource: MediaResource?
init(content: Content, emojis: [String], uuid: UUID = UUID()) {
self.content = content

View File

@ -73,6 +73,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
private let radialStatusBackground: ASImageNode
private let radialStatusText: ImmediateTextNode
private let progressText: ImmediateTextNode
private let infoText: ImmediateTextNode
private var interaction: StickerPackPreviewInteraction!
@ -90,6 +91,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
private var hapticFeedback: HapticFeedback?
private let disposable = MetaDisposable()
private let shortNameSuggestionDisposable = MetaDisposable()
private var progress: (CGFloat, Int32, Int32)?
@ -134,23 +136,37 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.installActionSeparatorNode.displaysAsynchronously = false
self.radialStatus = RadialStatusNode(backgroundNodeColor: .clear)
self.radialStatus.alpha = 0.0
self.radialCheck = RadialStatusNode(backgroundNodeColor: .clear)
self.radialCheck.alpha = 0.0
self.radialStatusBackground = ASImageNode()
self.radialStatusBackground.isUserInteractionEnabled = false
self.radialStatusBackground.displaysAsynchronously = false
self.radialStatusBackground.image = generateCircleImage(diameter: 180.0, lineWidth: 6.0, color: self.presentationData.theme.list.itemAccentColor.withMultipliedAlpha(0.2))
self.radialStatusBackground.alpha = 0.0
self.radialStatusText = ImmediateTextNode()
self.radialStatusText.isUserInteractionEnabled = false
self.radialStatusText.displaysAsynchronously = false
self.radialStatusText.maximumNumberOfLines = 1
self.radialStatusText.isAccessibilityElement = false
self.radialStatusText.alpha = 0.0
self.progressText = ImmediateTextNode()
self.progressText.isUserInteractionEnabled = false
self.progressText.displaysAsynchronously = false
self.progressText.maximumNumberOfLines = 1
self.progressText.isAccessibilityElement = false
self.progressText.alpha = 0.0
self.infoText = ImmediateTextNode()
self.infoText.isUserInteractionEnabled = false
self.infoText.displaysAsynchronously = false
self.infoText.maximumNumberOfLines = 4
self.infoText.isAccessibilityElement = false
self.infoText.textAlignment = .center
self.infoText.alpha = 0.0
super.init()
@ -184,6 +200,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.wrappingScrollNode.addSubnode(self.radialCheck)
self.wrappingScrollNode.addSubnode(self.radialStatusText)
self.wrappingScrollNode.addSubnode(self.progressText)
self.wrappingScrollNode.addSubnode(self.infoText)
self.contentGridNode.presentationLayoutUpdated = { [weak self] presentationLayout, transition in
self?.gridPresentationLayoutUpdated(presentationLayout, transition: transition)
@ -192,6 +209,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
deinit {
self.disposable.dispose()
self.shortNameSuggestionDisposable.dispose()
}
override func didLoad() {
@ -254,18 +272,6 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.presentationData = presentationData
let theme = presentationData.theme
let solidBackground = generateImage(CGSize(width: 1.0, height: 1.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.actionSheet.opaqueItemBackgroundColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height)))
})?.stretchableImage(withLeftCapWidth: 16, topCapHeight: 1)
let highlightedSolidBackground = generateImage(CGSize(width: 1.0, height: 1.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.actionSheet.opaqueItemHighlightedBackgroundColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height)))
})?.stretchableImage(withLeftCapWidth: 16, topCapHeight: 1)
let halfRoundedBackground = generateImage(CGSize(width: 32.0, height: 32.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.actionSheet.opaqueItemBackgroundColor.cgColor)
@ -337,7 +343,6 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
var transaction: StickerPackPreviewGridTransaction?
var itemCount = 0
var animateIn = false
var forceTitleUpdate = false
@ -359,12 +364,12 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
}
self.contentTitleNode.attributedText = stringWithAppliedEntities(title, entities: [], baseColor: self.presentationData.theme.actionSheet.primaryTextColor, linkColor: self.presentationData.theme.actionSheet.controlAccentColor, baseFont: titleFont, linkFont: titleFont, boldFont: titleFont, italicFont: titleFont, boldItalicFont: titleFont, fixedFont: titleFont, blockQuoteFont: titleFont)
animateIn = true
itemCount = self.currentItems.count
if !forceTitleUpdate {
transaction = StickerPackPreviewGridTransaction(previousList: previousItems, list: self.currentItems, account: self.context.account, interaction: self.interaction, theme: self.presentationData.theme)
}
}
let itemCount = self.currentItems.count
let titleSize = self.contentTitleNode.updateLayout(CGSize(width: contentContainerFrame.size.width - 24.0, height: CGFloat.greatestFiniteMagnitude))
let titleFrame = CGRect(origin: CGPoint(x: contentContainerFrame.minX + floor((contentContainerFrame.size.width - titleSize.width) / 2.0), y: self.contentBackgroundNode.frame.minY + 15.0), size: titleSize)
@ -406,8 +411,17 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
transition.updateAlpha(node: self.contentGridNode, alpha: self.progress == nil ? 1.0 : 0.0)
if let (progress, count, total) = self.progress {
let effectiveProgress = progress
var effectiveProgress: CGFloat = 0.0
var count: Int32 = 0
var total: Int32 = 0
var hasProgress = false
if let (progress, progressCount, progressTotal) = self.progress {
effectiveProgress = progress
count = progressCount
total = progressTotal
hasProgress = true
}
let availableHeight: CGFloat = 330.0
var radialStatusSize = CGSize(width: 186.0, height: 186.0)
@ -440,13 +454,17 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
}
let contentOrigin = self.contentBackgroundNode.frame.minY + 72.0
if hasProgress {
transition.updateAlpha(node: self.radialStatusText, alpha: 1.0)
transition.updateAlpha(node: self.progressText, alpha: 1.0)
transition.updateAlpha(node: self.radialStatus, alpha: 1.0)
transition.updateAlpha(node: self.infoText, alpha: 1.0)
transition.updateAlpha(node: self.radialCheck, alpha: 1.0)
transition.updateAlpha(node: self.radialStatusBackground, alpha: 1.0)
transition.updateAlpha(node: self.installActionButtonNode, alpha: 0.0)
transition.updateAlpha(node: self.contentSeparatorNode, alpha: 0.0)
transition.updateAlpha(node: self.installActionSeparatorNode, alpha: 0.0)
}
self.radialStatusText.attributedText = NSAttributedString(string: "\(Int(effectiveProgress * 100.0))%", font: Font.with(size: floor(36.0 * maxK), design: .round, weight: .semibold), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
let radialStatusTextSize = self.radialStatusText.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
@ -454,15 +472,19 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.progressText.attributedText = NSAttributedString(string: self.presentationData.strings.ImportStickerPack_Of(String(count), String(total)).0, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.itemPrimaryTextColor)
let progressTextSize = self.progressText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude))
self.radialStatus.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - radialStatusSize.width) / 2.0), y: contentOrigin), size: radialStatusSize)
self.infoText.attributedText = NSAttributedString(string: self.presentationData.strings.ImportStickerPack_InProgress, font: Font.regular(17.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor)
let infoTextSize = self.infoText.updateLayout(CGSize(width: layout.size.width - 16.0 * 2.0, height: .greatestFiniteMagnitude))
transition.updateFrame(node: self.radialStatus, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - radialStatusSize.width) / 2.0), y: contentOrigin), size: radialStatusSize))
let checkSize: CGFloat = 130.0
self.radialCheck.frame = CGRect(origin: CGPoint(x: self.radialStatus.frame.minX + floor((self.radialStatus.frame.width - checkSize) / 2.0), y: self.radialStatus.frame.minY + floor((self.radialStatus.frame.height - checkSize) / 2.0)), size: CGSize(width: checkSize, height: checkSize))
self.radialStatusBackground.frame = self.radialStatus.frame
transition.updateFrame(node: self.radialCheck, frame: CGRect(origin: CGPoint(x: self.radialStatus.frame.minX + floor((self.radialStatus.frame.width - checkSize) / 2.0), y: self.radialStatus.frame.minY + floor((self.radialStatus.frame.height - checkSize) / 2.0)), size: CGSize(width: checkSize, height: checkSize)))
transition.updateFrame(node: self.radialStatusBackground, frame: self.radialStatus.frame)
self.radialStatusText.frame = CGRect(origin: CGPoint(x: self.radialStatus.frame.minX + floor((self.radialStatus.frame.width - radialStatusTextSize.width) / 2.0), y: self.radialStatus.frame.minY + floor((self.radialStatus.frame.height - radialStatusTextSize.height) / 2.0)), size: radialStatusTextSize)
transition.updateFrame(node: self.radialStatusText, frame: CGRect(origin: CGPoint(x: self.radialStatus.frame.minX + floor((self.radialStatus.frame.width - radialStatusTextSize.width) / 2.0), y: self.radialStatus.frame.minY + floor((self.radialStatus.frame.height - radialStatusTextSize.height) / 2.0)), size: radialStatusTextSize))
self.progressText.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - progressTextSize.width) / 2.0), y: (self.radialStatus.frame.maxY + maxProgressTextSpacing)), size: progressTextSize)
}
transition.updateFrame(node: self.progressText, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - progressTextSize.width) / 2.0), y: (self.radialStatus.frame.maxY + maxProgressTextSpacing)), size: progressTextSize))
transition.updateFrame(node: self.infoText, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - infoTextSize.width) / 2.0), y: (self.progressText.frame.maxY + maxProgressTextSpacing) + 10.0), size: infoTextSize))
}
private func gridPresentationLayoutUpdated(_ presentationLayout: GridNodeCurrentPresentationLayout, transition: ContainedViewLayoutTransition) {
@ -498,7 +520,6 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
backgroundFrame.origin.y -= buttonHeight + 32.0 - backgroundFrame.size.height
backgroundFrame.size.height = buttonHeight + 32.0
}
var compactFrame = false
let backgroundDeltaY = backgroundFrame.minY - self.contentBackgroundNode.frame.minY
transition.updateFrame(node: self.contentBackgroundNode, frame: backgroundFrame)
transition.animatePositionAdditive(node: self.contentGridNode, offset: CGPoint(x: 0.0, y: -backgroundDeltaY))
@ -509,7 +530,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
transition.updateFrame(node: self.contentSeparatorNode, frame: CGRect(origin: CGPoint(x: contentFrame.minX, y: backgroundFrame.minY + titleAreaHeight), size: CGSize(width: contentFrame.size.width, height: UIScreenPixel)))
if !compactFrame && CGFloat(0.0).isLessThanOrEqualTo(presentationLayout.contentOffset.y) {
if CGFloat(0.0).isLessThanOrEqualTo(presentationLayout.contentOffset.y) {
self.contentSeparatorNode.alpha = 1.0
} else {
self.contentSeparatorNode.alpha = 0.0
@ -524,6 +545,7 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
}
@objc func cancelButtonPressed() {
self.disposable.set(nil)
self.cancel?()
}
@ -538,10 +560,10 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
if case let .image(data) = item.stickerItem.content, let image = UIImage(data: data) {
dimensions = PixelDimensions(image.size)
}
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: item.stickerItem.data)
if let resource = item.stickerItem.resource {
stickers.append(ImportSticker(resource: resource, emojis: item.stickerItem.emojis, dimensions: dimensions))
}
}
var thumbnailSticker: ImportSticker?
if let thumbnail = stickerPack.thumbnail {
var dimensions = PixelDimensions(width: 512, height: 512)
@ -553,6 +575,8 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
thumbnailSticker = ImportSticker(resource: resource, emojis: [], dimensions: dimensions)
}
let firstStickerItem = thumbnailSticker ?? stickers.first
self.progress = (0.0, 0, Int32(stickers.count))
self.radialStatus.transitionToState(.progress(color: self.presentationData.theme.list.itemAccentColor, lineWidth: 6.0, value: max(0.01, 0.0), cancelEnabled: false, animateRotation: false), animated: false, synchronous: true, completion: {})
if let (layout, navigationBarHeight) = self.containerLayout {
@ -597,8 +621,12 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
strongSelf.cancelButtonNode.isUserInteractionEnabled = false
Queue.mainQueue().after(1.0) {
strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: items.first, context: strongSelf.context), elevatedLayout: false, action: { _ in return true}), nil)
strongSelf.dismiss?()
var firstItem: StickerPackItem?
if let firstStickerItem = firstStickerItem, let resource = firstStickerItem.resource as? TelegramMediaResource {
firstItem = StickerPackItem(index: ItemCollectionItemIndex(index: 0, id: 0), file: TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: stickerPack.isAnimated ? "application/x-tgsticker": "image/png", size: nil, attributes: [.FileName(fileName: stickerPack.isAnimated ? "sticker.tgs" : "sticker.png"), .ImageSize(size: firstStickerItem.dimensions)]), indexKeys: [])
}
strongSelf.presentInGlobalOverlay?(UndoOverlayController(presentationData: strongSelf.presentationData, content: .stickersModified(title: strongSelf.presentationData.strings.StickerPackActionInfo_AddedTitle, text: strongSelf.presentationData.strings.StickerPackActionInfo_AddedText(info.title).0, undo: false, info: info, topItem: firstItem ?? items.first, context: strongSelf.context), elevatedLayout: false, action: { _ in return true}), nil)
strongSelf.cancel?()
}
} else if case let .progress(progress, count, total) = status {
strongSelf.progress = (CGFloat(progress), count, total)
@ -616,14 +644,31 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
}
@objc func installActionButtonPressed() {
let controller = importStickerPackTitleController(sharedContext: self.context.sharedContext, account: self.context.account, title: self.presentationData.strings.ImportStickerPack_ChooseName, text: self.presentationData.strings.ImportStickerPack_ChooseNameDescription, placeholder: "", doneButtonTitle: nil, value: nil, maxLength: 128, apply: { [weak self] title in
if let strongSelf = self, let stickerPack = strongSelf.stickerPack, var title = title {
title = title.trimmingTrailingSpaces()
var proceedImpl: ((String, String?) -> Void)?
let titleController = importStickerPackTitleController(context: self.context, title: self.presentationData.strings.ImportStickerPack_ChooseName, text: self.presentationData.strings.ImportStickerPack_ChooseNameDescription, placeholder: "", value: nil, maxLength: 128, apply: { [weak self] title in
if let strongSelf = self, let title = title {
strongSelf.shortNameSuggestionDisposable.set((strongSelf.context.engine.stickers.getStickerSetShortNameSuggestion(title: title)
|> deliverOnMainQueue).start(next: { suggestedShortName in
proceedImpl?(title, suggestedShortName)
}))
}
}, cancel: { [weak self] in
if let strongSelf = self {
strongSelf.shortNameSuggestionDisposable.set(nil)
}
})
self.present?(controller, nil)
proceedImpl = { [weak titleController, weak self] title, suggestedShortName in
guard let strongSelf = self else {
return
}
let controller = importStickerPackShortNameController(context: strongSelf.context, title: strongSelf.presentationData.strings.ImportStickerPack_ChooseLink, text: strongSelf.presentationData.strings.ImportStickerPack_ChooseLinkDescription, placeholder: "", value: suggestedShortName, maxLength: 60, existingAlertController: titleController, apply: { [weak self] shortName in
if let shortName = shortName {
self?.createStickerSet(title: title, shortName: shortName)
}
})
strongSelf.present?(controller, nil)
}
self.present?(titleController, nil)
}
func animateIn() {
@ -665,49 +710,19 @@ final class ImportStickerPackControllerNode: ViewControllerTracingNode, UIScroll
self.stickerPack = stickerPack
var updatedItems: [StickerPackPreviewGridEntry] = []
for item in stickerPack.stickers {
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: item.data)
item.resource = resource
updatedItems.append(StickerPackPreviewGridEntry(index: updatedItems.count, stickerItem: item))
}
self.pendingItems = updatedItems
// self.interaction.playAnimatedStickers = stickerSettings.loopAnimatedStickers
self.interaction.playAnimatedStickers = true
if let _ = self.containerLayout {
self.dequeueUpdateStickerPack()
}
self.installActionButtonNode.setTitle(self.presentationData.strings.ImportStickerPack_CreateStickerSet, with: Font.regular(20.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
// switch stickerPack {
// case .none, .fetching:
// self.installActionSeparatorNode.alpha = 0.0
// self.shareActionSeparatorNode.alpha = 0.0
// self.shareActionButtonNode.alpha = 0.0
// self.installActionButtonNode.alpha = 0.0
// self.installActionButtonNode.setTitle("", with: Font.medium(20.0), with: self.presentationData.theme.actionSheet.standardActionTextColor, for: .normal)
// case let .result(info, _, installed):
// if self.stickerPackInitiallyInstalled == nil {
// self.stickerPackInitiallyInstalled = installed
// }
// self.installActionSeparatorNode.alpha = 1.0
// self.shareActionSeparatorNode.alpha = 1.0
// self.shareActionButtonNode.alpha = 1.0
// self.installActionButtonNode.alpha = 1.0
// if installed {
// let text: String
// if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks {
// text = self.presentationData.strings.StickerPack_RemoveStickerCount(info.count)
// } else {
// text = self.presentationData.strings.StickerPack_RemoveMaskCount(info.count)
// }
// self.installActionButtonNode.setTitle(text, with: Font.regular(20.0), with: self.presentationData.theme.actionSheet.destructiveActionTextColor, for: .normal)
// } else {
// let text: String
// if info.id.namespace == Namespaces.ItemCollection.CloudStickerPacks {
// text = self.presentationData.strings.StickerPack_AddStickerCount(info.count)
// } else {
// text = self.presentationData.strings.StickerPack_AddMaskCount(info.count)
// }
// self.installActionButtonNode.setTitle(text, with: Font.regular(20.0), with: self.presentationData.theme.actionSheet.controlAccentColor, for: .normal)
// }
// }
}
func dequeueUpdateStickerPack() {

View File

@ -9,6 +9,7 @@ import SyncCore
import TelegramPresentationData
import AccountContext
import UrlEscaping
import ActivityIndicator
private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegate {
private var theme: PresentationTheme
@ -23,14 +24,14 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
var textChanged: ((String) -> Void)?
private let backgroundInsets = UIEdgeInsets(top: 8.0, left: 16.0, bottom: 15.0, right: 16.0)
private let inputInsets = UIEdgeInsets(top: 5.0, left: 12.0, bottom: 5.0, right: 12.0)
private let inputInsets = UIEdgeInsets(top: 8.0, left: 8.0, bottom: 8.0, right: 8.0)
var text: String {
get {
return self.textInputNode.attributedText?.string ?? ""
}
set {
self.textInputNode.attributedText = NSAttributedString(string: newValue, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputTextColor)
self.textInputNode.attributedText = NSAttributedString(string: newValue, font: Font.regular(14.0), textColor: self.theme.actionSheet.inputTextColor)
self.placeholderNode.isHidden = !newValue.isEmpty
if self.textInputNode.isFirstResponder() {
self.clearButton.isHidden = newValue.isEmpty
@ -42,19 +43,25 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
var placeholder: String = "" {
didSet {
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholder, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.placeholderNode.attributedText = NSAttributedString(string: self.placeholder, font: Font.regular(14.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
}
}
var prefix: String = "" {
didSet {
self.prefixNode.attributedText = NSAttributedString(string: self.prefix, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputTextColor)
self.prefixNode.attributedText = NSAttributedString(string: self.prefix, font: Font.regular(14.0), textColor: self.theme.actionSheet.inputTextColor)
}
}
var disabled: Bool = false {
didSet {
self.clearButton.isHidden = true
}
}
private let maxLength: Int
init(theme: PresentationTheme, placeholder: String, maxLength: Int, returnKeyType: UIReturnKeyType = .done) {
init(theme: PresentationTheme, placeholder: String, maxLength: Int, keyboardType: UIKeyboardType = .default, returnKeyType: UIReturnKeyType = .done) {
self.theme = theme
self.maxLength = maxLength
@ -65,12 +72,12 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
self.backgroundNode.image = generateStretchableFilledCircleImage(diameter: 12.0, color: theme.actionSheet.inputHollowBackgroundColor, strokeColor: theme.actionSheet.inputBorderColor, strokeWidth: 1.0)
self.textInputNode = EditableTextNode()
self.textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: theme.actionSheet.inputTextColor]
self.textInputNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(14.0), NSAttributedString.Key.foregroundColor.rawValue: theme.actionSheet.inputTextColor]
self.textInputNode.clipsToBounds = true
self.textInputNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
self.textInputNode.textContainerInset = UIEdgeInsets(top: self.inputInsets.top, left: 0.0, bottom: self.inputInsets.bottom, right: 0.0)
self.textInputNode.keyboardAppearance = theme.rootController.keyboardColor.keyboardAppearance
self.textInputNode.keyboardType = .default
self.textInputNode.keyboardType = keyboardType
self.textInputNode.autocapitalizationType = .sentences
self.textInputNode.returnKeyType = returnKeyType
self.textInputNode.autocorrectionType = .default
@ -79,12 +86,12 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
self.placeholderNode = ASTextNode()
self.placeholderNode.isUserInteractionEnabled = false
self.placeholderNode.displaysAsynchronously = false
self.placeholderNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.placeholderNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(14.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.prefixNode = ASTextNode()
self.prefixNode.isUserInteractionEnabled = false
self.prefixNode.displaysAsynchronously = false
self.prefixNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.prefixNode.attributedText = NSAttributedString(string: placeholder, font: Font.regular(14.0), textColor: self.theme.actionSheet.inputPlaceholderColor)
self.clearButton = HighlightableButtonNode()
self.clearButton.imageNode.displaysAsynchronously = false
@ -129,7 +136,10 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
let placeholderSize = self.placeholderNode.measure(backgroundFrame.size)
transition.updateFrame(node: self.placeholderNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY + floor((backgroundFrame.size.height - placeholderSize.height) / 2.0)), size: placeholderSize))
transition.updateFrame(node: self.textInputNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY), size: CGSize(width: backgroundFrame.size.width - inputInsets.left - inputInsets.right - 20.0, height: backgroundFrame.size.height)))
let prefixSize = self.prefixNode.measure(backgroundFrame.size)
transition.updateFrame(node: self.prefixNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left, y: backgroundFrame.minY + floor((backgroundFrame.size.height - prefixSize.height) / 2.0)), size: prefixSize))
transition.updateFrame(node: self.textInputNode, frame: CGRect(origin: CGPoint(x: backgroundFrame.minX + inputInsets.left + prefixSize.width, y: backgroundFrame.minY), size: CGSize(width: backgroundFrame.size.width - inputInsets.left - inputInsets.right - 20.0, height: backgroundFrame.size.height)))
if let image = self.clearButton.image(for: []) {
transition.updateFrame(node: self.clearButton, frame: CGRect(origin: CGPoint(x: backgroundFrame.maxX - 8.0 - image.size.width, y: backgroundFrame.minY + floor((backgroundFrame.size.height - image.size.height) / 2.0)), size: image.size))
@ -162,6 +172,9 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
}
func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if self.disabled {
return false
}
let updatedText = (editableTextNode.textView.text as NSString).replacingCharacters(in: range, with: text)
if updatedText.count > maxLength {
self.textInputNode.layer.addShakeAnimation()
@ -204,16 +217,63 @@ private final class ImportStickerPackTitleInputFieldNode: ASDisplayNode, ASEdita
}
private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
enum InfoText {
case info
case checking
case available
case taken
case generating
}
private var theme: PresentationTheme
private var alertTheme: AlertControllerTheme
private let strings: PresentationStrings
private let title: String
private let text: String
var infoText: InfoText? {
didSet {
let text: String
let color: UIColor
var activity = false
if let infoText = self.infoText {
switch infoText {
case .info:
text = self.strings.ImportStickerPack_ChooseLinkDescription
color = self.alertTheme.primaryColor
case .checking:
text = self.strings.ImportStickerPack_CheckingLink
color = self.alertTheme.secondaryColor
activity = true
case .available:
text = self.strings.ImportStickerPack_LinkAvailable
color = self.theme.list.freeTextSuccessColor
case .taken:
text = self.strings.ImportStickerPack_LinkTaken
color = self.theme.list.freeTextErrorColor
case .generating:
text = self.strings.ImportStickerPack_GeneratingLink
color = self.alertTheme.secondaryColor
activity = true
}
self.activityIndicator.isHidden = !activity
} else {
text = self.text
color = self.alertTheme.primaryColor
}
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(13.0), textColor: color)
if let size = self.validLayout {
_ = self.updateLayout(size: size, transition: .immediate)
}
}
}
private let titleNode: ASTextNode
private let textNode: ASTextNode
private let activityIndicator: ActivityIndicator
let inputFieldNode: ImportStickerPackTitleInputFieldNode
private let actionNodesSeparator: ASDisplayNode
private let actionNodes: [TextAlertContentActionNode]
fileprivate let actionNodes: [TextAlertContentActionNode]
private let actionVerticalSeparators: [ASDisplayNode]
private let disposable = MetaDisposable()
@ -232,8 +292,10 @@ private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
return self.isUserInteractionEnabled
}
init(theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, actions: [TextAlertAction], title: String, text: String, placeholder: String, value: String?, maxLength: Int) {
init(theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, actions: [TextAlertAction], title: String, text: String, placeholder: String, value: String?, maxLength: Int, asciiOnly: Bool = false) {
self.strings = strings
self.alertTheme = theme
self.theme = ptheme
self.title = title
self.text = text
@ -242,7 +304,13 @@ private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
self.textNode = ASTextNode()
self.textNode.maximumNumberOfLines = 8
self.inputFieldNode = ImportStickerPackTitleInputFieldNode(theme: ptheme, placeholder: placeholder, maxLength: maxLength)
self.activityIndicator = ActivityIndicator(type: .custom(ptheme.rootController.navigationBar.secondaryTextColor, 20.0, 1.5, false), speed: .slow)
self.activityIndicator.isHidden = true
self.inputFieldNode = ImportStickerPackTitleInputFieldNode(theme: ptheme, placeholder: placeholder, maxLength: maxLength, keyboardType: asciiOnly ? .asciiCapable : .default, returnKeyType: asciiOnly ? .done : .next)
if asciiOnly {
self.inputFieldNode.prefix = "t.me/addstickers/"
}
self.inputFieldNode.text = value ?? ""
self.actionNodesSeparator = ASDisplayNode()
@ -266,6 +334,7 @@ private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
self.addSubnode(self.activityIndicator)
self.addSubnode(self.inputFieldNode)
@ -299,6 +368,8 @@ private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
}
override func updateTheme(_ theme: AlertControllerTheme) {
self.alertTheme = theme
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.bold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
@ -331,8 +402,13 @@ private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: origin.y), size: titleSize))
origin.y += titleSize.height + 4.0
let activitySize = CGSize(width: 20.0, height: 20.0)
let textSize = self.textNode.measure(measureSize)
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: origin.y), size: textSize))
let activityInset: CGFloat = self.activityIndicator.isHidden ? 0.0 : activitySize.width + 5.0
let totalWidth = textSize.width + activityInset
transition.updateFrame(node: self.activityIndicator, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - totalWidth) / 2.0), y: origin.y - 1.0), size: activitySize))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - totalWidth) / 2.0) + activityInset, y: origin.y), size: textSize))
origin.y += textSize.height + 6.0 + spacing
let actionButtonHeight: CGFloat = 44.0
@ -435,14 +511,15 @@ private final class ImportStickerPackTitleAlertContentNode: AlertContentNode {
}
}
func importStickerPackTitleController(sharedContext: SharedAccountContext, account: Account, title: String, text: String, placeholder: String, doneButtonTitle: String? = nil, value: String?, maxLength: Int, apply: @escaping (String?) -> Void) -> AlertController {
let presentationData = sharedContext.currentPresentationData.with { $0 }
func importStickerPackTitleController(context: AccountContext, title: String, text: String, placeholder: String, value: String?, maxLength: Int, apply: @escaping (String?) -> Void, cancel: @escaping () -> Void) -> AlertController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var dismissImpl: ((Bool) -> Void)?
var applyImpl: (() -> Void)?
let actions: [TextAlertAction] = [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
dismissImpl?(true)
}), TextAlertAction(type: .defaultAction, title: doneButtonTitle ?? presentationData.strings.Common_Done, action: {
cancel()
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Next, action: {
applyImpl?()
})]
@ -454,18 +531,27 @@ func importStickerPackTitleController(sharedContext: SharedAccountContext, accou
guard let contentNode = contentNode else {
return
}
dismissImpl?(true)
let previousValue = value ?? ""
let newValue = contentNode.value.trimmingCharacters(in: .whitespacesAndNewlines)
apply(previousValue != newValue || value == nil ? newValue : nil)
guard !newValue.isEmpty else {
return
}
contentNode.infoText = .generating
contentNode.inputFieldNode.disabled = true
contentNode.actionNodes.last?.actionEnabled = false
apply(newValue)
}
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
let presentationDataDisposable = sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
controller?.theme = AlertControllerTheme(presentationData: presentationData)
contentNode?.inputFieldNode.updateTheme(presentationData.theme)
})
contentNode.actionNodes.last?.actionEnabled = false
contentNode.inputFieldNode.textChanged = { [weak contentNode] title in
contentNode?.actionNodes.last?.actionEnabled = !title.trimmingTrailingSpaces().isEmpty
}
controller.dismissed = {
presentationDataDisposable.dispose()
}
@ -481,18 +567,18 @@ func importStickerPackTitleController(sharedContext: SharedAccountContext, accou
}
func importStickerPackShortNameController(sharedContext: SharedAccountContext, account: Account, title: String, text: String, placeholder: String, doneButtonTitle: String? = nil, value: String?, maxLength: Int, apply: @escaping (String?) -> Void) -> AlertController {
let presentationData = sharedContext.currentPresentationData.with { $0 }
func importStickerPackShortNameController(context: AccountContext, title: String, text: String, placeholder: String, value: String?, maxLength: Int, existingAlertController: AlertController?, apply: @escaping (String?) -> Void) -> AlertController {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var dismissImpl: ((Bool) -> Void)?
var applyImpl: (() -> Void)?
let actions: [TextAlertAction] = [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
dismissImpl?(true)
}), TextAlertAction(type: .defaultAction, title: doneButtonTitle ?? presentationData.strings.Common_Done, action: {
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.ImportStickerPack_Create, action: {
applyImpl?()
})]
let contentNode = ImportStickerPackTitleAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: presentationData.strings, actions: actions, title: title, text: text, placeholder: placeholder, value: value, maxLength: maxLength)
let contentNode = ImportStickerPackTitleAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: presentationData.strings, actions: actions, title: title, text: text, placeholder: placeholder, value: value, maxLength: maxLength, asciiOnly: true)
contentNode.complete = {
applyImpl?()
}
@ -500,18 +586,54 @@ func importStickerPackShortNameController(sharedContext: SharedAccountContext, a
guard let contentNode = contentNode else {
return
}
dismissImpl?(true)
let previousValue = value ?? ""
let newValue = contentNode.value.trimmingCharacters(in: .whitespacesAndNewlines)
apply(previousValue != newValue || value == nil ? newValue : nil)
guard !newValue.isEmpty else {
return
}
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
let presentationDataDisposable = sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
dismissImpl?(true)
apply(newValue)
}
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode, existingAlertController: existingAlertController)
let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
controller?.theme = AlertControllerTheme(presentationData: presentationData)
contentNode?.inputFieldNode.updateTheme(presentationData.theme)
})
let checkDisposable = MetaDisposable()
var value = value ?? ""
contentNode.actionNodes.last?.actionEnabled = !value.isEmpty
contentNode.inputFieldNode.textChanged = { [weak contentNode] value in
if value.isEmpty {
checkDisposable.set(nil)
contentNode?.infoText = .info
contentNode?.actionNodes.last?.actionEnabled = false
} else {
checkDisposable.set((context.engine.stickers.validateStickerSetShortNameInteractive(shortName: value)
|> deliverOnMainQueue).start(next: { [weak contentNode] result in
switch result {
case .checking:
contentNode?.infoText = .checking
contentNode?.actionNodes.last?.actionEnabled = false
case let .availability(availability):
switch availability {
case .available:
contentNode?.infoText = .available
contentNode?.actionNodes.last?.actionEnabled = true
case .taken:
contentNode?.infoText = .taken
contentNode?.actionNodes.last?.actionEnabled = false
case .invalid:
contentNode?.infoText = .info
contentNode?.actionNodes.last?.actionEnabled = false
}
case .invalidFormat:
contentNode?.infoText = .info
contentNode?.actionNodes.last?.actionEnabled = false
}
}))
}
}
controller.dismissed = {
presentationDataDisposable.dispose()
}

View File

@ -119,14 +119,16 @@ final class StickerPackPreviewGridItemNode: GridItemNode {
self.imageNode.image = image
dimensions = image.size
}
case let .animation(data):
case .animation:
self.imageNode.isHidden = true
let animationNode = AnimatedStickerNode()
self.animationNode = animationNode
self.addSubnode(animationNode)
let fittedDimensions = dimensions.aspectFitted(CGSize(width: 160.0, height: 160.0))
// animationNode.setup(source: AnimatedStickerResourceSource(account: account, resource: stickerItem.file.resource), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .cached)
if let resource = stickerItem.resource {
animationNode.setup(source: AnimatedStickerResourceSource(account: account, resource: resource), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .direct(cachePathPrefix: nil))
}
animationNode.visibility = self.isVisibleInGrid && self.interaction?.playAnimatedStickers ?? true
}
} else {

View File

@ -68,26 +68,24 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController
self.textNode = ASTextNode()
self.imageNode = ASImageNode()
self.imageNode.displaysAsynchronously = false
switch item.content {
case let .image(data):
self.imageNode.image = UIImage(data: data)
case .animation:
let animationNode = AnimatedStickerNode()
self.animationNode = animationNode
let dimensions = PixelDimensions(width: 512, height: 512)
let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 400.0, height: 400.0))
if let resource = item.resource {
self.animationNode?.setup(source: AnimatedStickerResourceSource(account: account, resource: resource), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .direct(cachePathPrefix: nil))
}
self.animationNode?.visibility = true
}
if case let .image(data) = item.content, let image = UIImage(data: data) {
self.imageNode.image = image
}
self.textNode.attributedText = NSAttributedString(string: item.emojis.joined(separator: " "), font: Font.regular(32.0), textColor: .black)
// if item.file.isAnimatedSticker {
// let animationNode = AnimatedStickerNode()
// self.animationNode = animationNode
//
// let dimensions = item.file.dimensions ?? PixelDimensions(width: 512, height: 512)
// let fittedDimensions = dimensions.cgSize.aspectFitted(CGSize(width: 400.0, height: 400.0))
//
// self.animationNode?.setup(source: AnimatedStickerResourceSource(account: account, resource: item.file.resource), width: Int(fittedDimensions.width), height: Int(fittedDimensions.height), mode: .direct(cachePathPrefix: nil))
// self.animationNode?.visibility = true
// self.animationNode?.addSubnode(self.textNode)
// } else {
// self.imageNode.addSubnode(self.textNode)
// self.animationNode = nil
// }
super.init()
self.isUserInteractionEnabled = false
@ -110,26 +108,11 @@ private final class StickerPreviewPeekContentNode: ASDisplayNode, PeekController
self.textNode.frame = CGRect(origin: CGPoint(x: floor((imageFrame.size.width - textSize.width) / 2.0), y: -textSize.height - textSpacing), size: textSize)
self.imageNode.frame = imageFrame
return boundingSize
// if let dimensitons = self.item.file.dimensions {
// let textSpacing: CGFloat = 10.0
// let textSize = self.textNode.measure(CGSize(width: 100.0, height: 100.0))
//
// let imageSize = dimensitons.cgSize.aspectFitted(boundingSize)
// self.imageNode.asyncLayout()(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets()))()
// let imageFrame = CGRect(origin: CGPoint(x: floor((size.width - imageSize.width) / 2.0), y: textSize.height + textSpacing), size: imageSize)
// self.imageNode.frame = imageFrame
// if let animationNode = self.animationNode {
// animationNode.frame = imageFrame
// animationNode.updateLayout(size: imageSize)
// }
//
// self.textNode.frame = CGRect(origin: CGPoint(x: floor((imageFrame.size.width - textSize.width) / 2.0), y: -textSize.height - textSpacing), size: textSize)
//
// return CGSize(width: size.width, height: imageFrame.height + textSize.height + textSpacing)
// } else {
// return CGSize(width: size.width, height: 10.0)
// }
if let animationNode = self.animationNode {
animationNode.frame = imageFrame
animationNode.updateLayout(size: imageFrame.size)
}
return boundingSize
}
}

View File

@ -79,9 +79,9 @@ public enum CreateStickerSetError {
}
public struct ImportSticker {
let resource: MediaResource
public let resource: MediaResource
let emojis: [String]
let dimensions: PixelDimensions
public let dimensions: PixelDimensions
public init(resource: MediaResource, emojis: [String], dimensions: PixelDimensions) {
self.resource = resource
@ -200,6 +200,9 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri
completeCount += 1
case let .progress(progress):
totalProgress += progress
if progress == 1.0 {
completeCount += 1
}
}
}
let normalizedProgress = min(1.0, max(0.0, totalProgress / Float(stickers.count)))
@ -237,6 +240,9 @@ func _internal_stickerSetShortNameAvailability(account: Account, shortName: Stri
}
}
|> `catch` { error -> Signal<AddressNameAvailability, NoError> in
if error.errorDescription == "SHORT_NAME_OCCUPIED" {
return .single(.taken)
}
return .single(.invalid)
}
}