mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge commit '8aca1f28fb3faf48a85feb33216ce673a4ad438a'
This commit is contained in:
commit
0dd4f9d438
@ -7530,8 +7530,6 @@ Sorry for the inconvenience.";
|
||||
|
||||
"StickerPack.Share" = "Share Stickers";
|
||||
"StickerPack.CopyLink" = "Copy Link";
|
||||
"StickerPack.PremiumStickers_1" = "+%@ PREMIUM STICKER";
|
||||
"StickerPack.PremiumStickers_any" = "+%@ PREMIUM STICKERS";
|
||||
|
||||
"Stickers.PremiumStickers" = "Premium Stickers";
|
||||
|
||||
@ -7546,11 +7544,11 @@ Sorry for the inconvenience.";
|
||||
"Chat.MultipleTypingPair" = "%@ and %@";
|
||||
"Chat.MultipleTypingMore" = "%@ and %@ others";
|
||||
|
||||
"DialogList.ExtendedPinLimitError" = "Sorry, you can't pin more than **%1$@** chats to the top. Unpin some of the currently pinned ones or subscribe to **Telegram Premium** to double the limit to **%2$@** chats.";
|
||||
|
||||
"Group.Username.RemoveExistingUsernamesOrExtendInfo" = "You have reserved too many public links. Try revoking a link from an older group or channel, or upgrade to **Telegram Premium** to double the limit to **%@** public links.";
|
||||
"Group.Username.RemoveExistingUsernamesFinalInfo" = "You have reserved too many public links. Try revoking the link from an older group or channel, or create a private one instead.";
|
||||
|
||||
"OldChannels.TooManyCommunitiesText" = "You are a member of **%@** groups and channels. Please leave some before joining a new one or upgrade to **Telegram Premium** to double the limit to **%@** groups and channels.";
|
||||
"OldChannels.TooManyCommunitiesFinalText" = "You are a member of **%@** groups and channels. Please leave some before joining a new one.";
|
||||
"OldChannels.LeaveCommunities_1" = "Leave %@ Community";
|
||||
"OldChannels.LeaveCommunities_any" = "Leave %@ Communities";
|
||||
|
||||
@ -7559,11 +7557,19 @@ Sorry for the inconvenience.";
|
||||
"Premium.IncreaseLimit" = "Increase Limit";
|
||||
|
||||
"Premium.MaxFoldersCountText" = "You have reached the limit of **%1$@** folders. You can double the limit to **%2$@** folders by subscribing to **Telegram Premium**.";
|
||||
"Premium.MaxChatsInFolderCountText" = "Sorry, you can't add more than **%1$@** chats to a folder. You can increase this limit to **%2$@** by upgrading to **Telegram Premium**.";
|
||||
"Premium.MaxChatsInFolderText" = "Sorry, you can't add more than **%1$@** chats to a folder. You can increase this limit to **%2$@** by upgrading to **Telegram Premium**.";
|
||||
"Premium.MaxChatsInFolderFinalText" = "Sorry, you can't add more than **%@** chats to a folder.";
|
||||
"Premium.MaxFileSizeText" = "Double this limit to %@ per file by subscribing to **Telegram Premium**.";
|
||||
"Premium.MaxFileSizeFinalText" = "The document can't be sent, because it is larger than **%@**.";
|
||||
"Premium.MaxPinsText" = "Sorry, you can't pin more than **%1$@** chats to the top. Unpin some of the currently pinned ones or subscribe to **Telegram Premium** to double the limit to **%2$@** chats.";
|
||||
"Premium.MaxPinsFinalText" = "Sorry, you can't pin more than **@** chats to the top. Unpin some of the currently pinned ones.";
|
||||
"Premium.MaxPinsFinalText" = "Sorry, you can't pin more than **@** chats to the top.";
|
||||
"Premium.MaxFavedStickersTitle" = "The Limit of %@ Stickers Reached";
|
||||
"Premium.MaxFavedStickersText" = "An older sticker was replaced with this one. You can [increase the limit]() to %@ stickers.";
|
||||
"Premium.MaxFavedStickersFinalText" = "An older sticker was replaced with this one.";
|
||||
"Premium.MaxSavedGifsTitle" = "The Limit of %@ GIFs Reached";
|
||||
"Premium.MaxSavedGifsText" = "An older GIF was replaced with this one. You can [increase the limit]() to %@ GIFS.";
|
||||
"Premium.MaxSavedGifsFinalText" = "An older GIF was replaced with this one.";
|
||||
"Premium.MaxAccountsText" = "You have reached the limit of **%@** connected accounts. You can free one place by subscribing to **Telegram Premium**.";
|
||||
|
||||
"Premium.Free" = "Free";
|
||||
@ -7636,3 +7642,5 @@ Sorry for the inconvenience.";
|
||||
"SponsoredMessageMenu.Hide" = "Hide";
|
||||
|
||||
"ChatListFolder.MaxChatsInFolder" = "Sorry, you can't add more than %d chats to a folder.";
|
||||
|
||||
"Conversation.SaveGif" = "Save GIF";
|
||||
|
@ -712,6 +712,8 @@ public protocol SharedAccountContext: AnyObject {
|
||||
|
||||
func makeChatQrCodeScreen(context: AccountContext, peer: Peer) -> ViewController
|
||||
|
||||
func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource) -> ViewController
|
||||
|
||||
func navigateToCurrentCall()
|
||||
var hasOngoingCall: ValuePromise<Bool> { get }
|
||||
var immediateHasOngoingCall: Bool { get }
|
||||
@ -723,6 +725,24 @@ public protocol SharedAccountContext: AnyObject {
|
||||
func beginNewAuth(testingEnvironment: Bool)
|
||||
}
|
||||
|
||||
public enum PremiumIntroSource {
|
||||
case settings
|
||||
case stickers
|
||||
case reactions
|
||||
case ads
|
||||
case upload
|
||||
case groupsAndChannels
|
||||
case pinnedChats
|
||||
case publicLinks
|
||||
case savedGifs
|
||||
case savedStickers
|
||||
case folders
|
||||
case chatsPerFolder
|
||||
case accounts
|
||||
case deeplink(String?)
|
||||
case profile(PeerId)
|
||||
}
|
||||
|
||||
#if ENABLE_WALLET
|
||||
private final class TonInstanceData {
|
||||
var config: String?
|
||||
|
@ -332,7 +332,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS
|
||||
if let peer = peer {
|
||||
return self.context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.UserLimits.init(isPremium: peer.isPremium))
|
||||
|> map { limits in
|
||||
return limits.maxCaptionLengthCount
|
||||
return limits.maxCaptionLength
|
||||
}
|
||||
} else {
|
||||
return .complete()
|
||||
|
@ -6,9 +6,9 @@ import ViewControllerComponent
|
||||
|
||||
public final class SheetComponentEnvironment: Equatable {
|
||||
public let isDisplaying: Bool
|
||||
public let dismiss: () -> Void
|
||||
public let dismiss: (Bool) -> Void
|
||||
|
||||
public init(isDisplaying: Bool, dismiss: @escaping () -> Void) {
|
||||
public init(isDisplaying: Bool, dismiss: @escaping (Bool) -> Void) {
|
||||
self.isDisplaying = isDisplaying
|
||||
self.dismiss = dismiss
|
||||
}
|
||||
@ -55,7 +55,7 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
private let contentView: ComponentHostView<ChildEnvironmentType>
|
||||
|
||||
private var previousIsDisplaying: Bool = false
|
||||
private var dismiss: (() -> Void)?
|
||||
private var dismiss: ((Bool) -> Void)?
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.dimView = UIView()
|
||||
@ -78,8 +78,9 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
|
||||
super.init(frame: frame)
|
||||
|
||||
self.addSubview(self.dimView)
|
||||
self.scrollView.delegate = self
|
||||
|
||||
self.addSubview(self.dimView)
|
||||
self.scrollView.addSubview(self.backgroundView)
|
||||
self.scrollView.addSubview(self.contentView)
|
||||
self.addSubview(self.scrollView)
|
||||
@ -93,17 +94,39 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
|
||||
@objc private func dimViewTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.dismiss?()
|
||||
self.dismiss?(true)
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
}
|
||||
|
||||
private var scrollingOut = false
|
||||
public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
|
||||
let contentOffset = (scrollView.contentOffset.y + scrollView.contentInset.top - scrollView.contentSize.height) * -1.0
|
||||
let dismissalOffset = scrollView.contentSize.height - scrollView.contentInset.top + scrollView.contentSize.height
|
||||
let delta = dismissalOffset - contentOffset
|
||||
|
||||
let initialVelocity = !delta.isZero ? velocity.y / delta : 0.0
|
||||
|
||||
targetContentOffset.pointee = scrollView.contentOffset
|
||||
if velocity.y > 300.0 {
|
||||
self.animateOut(initialVelocity: initialVelocity, completion: {
|
||||
self.dismiss?(false)
|
||||
})
|
||||
} else {
|
||||
if contentOffset < scrollView.contentSize.height * 0.333 {
|
||||
scrollView.setContentOffset(CGPoint(x: 0.0, y: scrollView.contentSize.height - scrollView.contentInset.top), animated: true)
|
||||
} else {
|
||||
self.animateOut(initialVelocity: initialVelocity, completion: {
|
||||
self.dismiss?(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
let contentOffset = (scrollView.contentOffset.y + scrollView.contentInset.top - scrollView.contentSize.height) * -1.0
|
||||
if contentOffset >= scrollView.contentSize.height {
|
||||
self.dismiss?(false)
|
||||
}
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
@ -114,14 +137,38 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
return super.hitTest(point, with: event)
|
||||
}
|
||||
|
||||
private func animateOut(completion: @escaping () -> Void) {
|
||||
self.isUserInteractionEnabled = false
|
||||
self.dimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
|
||||
self.scrollView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.bounds.height - self.scrollView.contentInset.top), duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeIn.rawValue, removeOnCompletion: false, additive: true, completion: { _ in
|
||||
completion()
|
||||
private func animateIn() {
|
||||
self.dimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.4, curve: .spring)
|
||||
let targetPosition = self.scrollView.center
|
||||
self.scrollView.center = targetPosition.offsetBy(dx: 0.0, dy: self.scrollView.contentSize.height)
|
||||
transition.animateView(allowUserInteraction: true, {
|
||||
self.scrollView.center = targetPosition
|
||||
})
|
||||
}
|
||||
|
||||
private func animateOut(initialVelocity: CGFloat? = nil, completion: @escaping () -> Void) {
|
||||
self.isUserInteractionEnabled = false
|
||||
self.dimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
|
||||
if let initialVelocity = initialVelocity {
|
||||
let transition = ContainedViewLayoutTransition.animated(duration: 0.35, curve: .customSpring(damping: 124.0, initialVelocity: initialVelocity))
|
||||
|
||||
let contentOffset = (self.scrollView.contentOffset.y + self.scrollView.contentInset.top - self.scrollView.contentSize.height) * -1.0
|
||||
let dismissalOffset = self.scrollView.contentSize.height
|
||||
let delta = dismissalOffset - contentOffset
|
||||
|
||||
transition.updatePosition(layer: self.scrollView.layer, position: CGPoint(x: self.scrollView.center.x, y: self.scrollView.center.y + delta), completion: { _ in
|
||||
completion()
|
||||
})
|
||||
} else {
|
||||
self.scrollView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.scrollView.contentSize.height), duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, additive: true, completion: { _ in
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: SheetComponent<ChildEnvironmentType>, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: Transition) -> CGSize {
|
||||
component.animateOut.connect { [weak self] completion in
|
||||
guard let strongSelf = self else {
|
||||
@ -147,15 +194,14 @@ public final class SheetComponent<ChildEnvironmentType: Equatable>: Component {
|
||||
containerSize: CGSize(width: availableSize.width, height: .greatestFiniteMagnitude)
|
||||
)
|
||||
|
||||
transition.setFrame(view: self.contentView, frame: CGRect(origin: CGPoint(), size: contentSize), completion: nil)
|
||||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(), size: CGSize(width: contentSize.width, height: contentSize.height + 1000.0)), completion: nil)
|
||||
transition.setFrame(view: self.contentView, frame: CGRect(origin: .zero, size: contentSize), completion: nil)
|
||||
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: .zero, size: CGSize(width: contentSize.width, height: contentSize.height + 1000.0)), completion: nil)
|
||||
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: availableSize), completion: nil)
|
||||
self.scrollView.contentSize = contentSize
|
||||
self.scrollView.contentInset = UIEdgeInsets(top: max(0.0, availableSize.height - contentSize.height), left: 0.0, bottom: 0.0, right: 0.0)
|
||||
self.scrollView.contentInset = UIEdgeInsets(top: max(0.0, availableSize.height - contentSize.height) + contentSize.height, left: 0.0, bottom: 0.0, right: 0.0)
|
||||
|
||||
if environment[SheetComponentEnvironment.self].value.isDisplaying, !self.previousIsDisplaying, let _ = transition.userData(ViewControllerComponentContainer.AnimateInTransition.self) {
|
||||
self.dimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.scrollView.layer.animatePosition(from: CGPoint(x: 0.0, y: availableSize.height - self.scrollView.contentInset.top), to: CGPoint(), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, additive: true, completion: nil)
|
||||
self.animateIn()
|
||||
} else if !environment[SheetComponentEnvironment.self].value.isDisplaying, self.previousIsDisplaying, let _ = transition.userData(ViewControllerComponentContainer.AnimateOutTransition.self) {
|
||||
self.animateOut(completion: {})
|
||||
}
|
||||
|
@ -1249,9 +1249,32 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let message = messages[0]
|
||||
let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: .message(message: MessageReference(message._asMessage()), media: file)).start()
|
||||
|
||||
strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
let context = strongSelf.context
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controllerInteraction = strongSelf.controllerInteraction
|
||||
let _ = (toggleGifSaved(account: context.account, fileReference: .message(message: MessageReference(message._asMessage()), media: file), saved: true)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .generic:
|
||||
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsFinalText
|
||||
} else {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
|
||||
}
|
||||
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: true, animateInAsReplacement: true, action: { action in
|
||||
if case .info = action {
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .savedGifs)
|
||||
controllerInteraction?.pushController(controller)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}))
|
||||
} else if file.mimeType.hasPrefix("image/") {
|
||||
@ -1421,9 +1444,31 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
if file.isAnimated {
|
||||
preferredAction = .custom(action: ShareControllerAction(title: presentationData.strings.Preview_SaveGif, action: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: .webPage(webPage: WebpageReference(webPage), media: file)).start()
|
||||
|
||||
strongSelf.controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
let context = strongSelf.context
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controllerInteraction = strongSelf.controllerInteraction
|
||||
let _ = (toggleGifSaved(account: context.account, fileReference: .webPage(webPage: WebpageReference(webPage), media: file), saved: true)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .generic:
|
||||
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: true, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsFinalText
|
||||
} else {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
|
||||
}
|
||||
controllerInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: true, animateInAsReplacement: true, action: { action in
|
||||
if case .info = action {
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .savedGifs)
|
||||
controllerInteraction?.pushController(controller)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}))
|
||||
} else if file.mimeType.hasPrefix("image/") || file.mimeType.hasPrefix("video/") {
|
||||
|
@ -1002,7 +1002,10 @@ public class GalleryController: ViewController, StandalonePresentableController
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, dismissController: { [weak self] in
|
||||
}, pushController: { [weak self] c in
|
||||
self?.baseNavigationController?.pushViewController(c)
|
||||
self?.dismiss(forceAway: true)
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { [weak self] controller, ready in
|
||||
if let strongSelf = self {
|
||||
|
@ -7,12 +7,14 @@ import Postbox
|
||||
|
||||
public final class GalleryControllerInteraction {
|
||||
public let presentController: (ViewController, ViewControllerPresentationArguments?) -> Void
|
||||
public let pushController: (ViewController) -> Void
|
||||
public let dismissController: () -> Void
|
||||
public let replaceRootController: (ViewController, Promise<Bool>?) -> Void
|
||||
public let editMedia: (MessageId) -> Void
|
||||
|
||||
public init(presentController: @escaping (ViewController, ViewControllerPresentationArguments?) -> Void, dismissController: @escaping () -> Void, replaceRootController: @escaping (ViewController, Promise<Bool>?) -> Void, editMedia: @escaping (MessageId) -> Void) {
|
||||
public init(presentController: @escaping (ViewController, ViewControllerPresentationArguments?) -> Void, pushController: @escaping (ViewController) -> Void, dismissController: @escaping () -> Void, replaceRootController: @escaping (ViewController, Promise<Bool>?) -> Void, editMedia: @escaping (MessageId) -> Void) {
|
||||
self.presentController = presentController
|
||||
self.pushController = pushController
|
||||
self.dismissController = dismissController
|
||||
self.replaceRootController = replaceRootController
|
||||
self.editMedia = editMedia
|
||||
|
@ -204,6 +204,7 @@ public final class SecretMediaPreviewController: ViewController {
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, pushController: { _ in
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { _, _ in
|
||||
|
@ -362,6 +362,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, pushController: { _ in
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { [weak self] controller, ready in
|
||||
|
@ -176,6 +176,7 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, pushController: { _ in
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { [weak self] controller, ready in
|
||||
|
@ -207,12 +207,18 @@ private final class AddPaymentMethodSheetComponent: CombinedComponent {
|
||||
environment
|
||||
SheetComponentEnvironment(
|
||||
isDisplaying: environment.value.isVisible,
|
||||
dismiss: {
|
||||
animateOut.invoke(Action { _ in
|
||||
dismiss: { animated in
|
||||
if animated {
|
||||
animateOut.invoke(Action { _ in
|
||||
if let controller = controller() {
|
||||
controller.dismiss(completion: nil)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if let controller = controller() {
|
||||
controller.dismiss(completion: nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
|
@ -565,6 +565,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, pushController: { _ in
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { [weak self] controller, ready in
|
||||
|
@ -60,6 +60,7 @@ private final class PhoneView: UIView {
|
||||
self.contentContainerView.clipsToBounds = true
|
||||
self.contentContainerView.backgroundColor = .darkGray
|
||||
self.contentContainerView.layer.cornerRadius = 10.0
|
||||
self.contentContainerView.layer.allowsGroupOpacity = true
|
||||
|
||||
self.overlayView = UIView()
|
||||
self.overlayView.backgroundColor = .black
|
||||
@ -230,22 +231,26 @@ final class PhoneDemoComponent: Component {
|
||||
var mappedPosition = environment[DemoPageEnvironment.self].position
|
||||
mappedPosition *= abs(mappedPosition)
|
||||
|
||||
let scale: CGFloat = availableSize.width / 390.0
|
||||
|
||||
let phoneX = mappedPosition * 50.0 * scale
|
||||
let phoneY: CGFloat
|
||||
switch component.position {
|
||||
case .top:
|
||||
phoneY = phoneSize.height / 2.0 + 24.0 + abs(mappedPosition) * 24.0
|
||||
phoneY = availableSize.height + (-phoneSize.height / 2.0 + 24.0 + 149.0 + abs(mappedPosition) * 24.0) * scale
|
||||
case .bottom:
|
||||
phoneY = availableSize.height - phoneSize.height / 2.0 - 24.0 - abs(mappedPosition) * 24.0
|
||||
phoneY = (-149.0 + phoneSize.height / 2.0 - 24.0 - abs(mappedPosition) * 24.0) * scale
|
||||
}
|
||||
|
||||
|
||||
let isVisible = environment[DemoPageEnvironment.self].isDisplaying
|
||||
let isCentral = environment[DemoPageEnvironment.self].isCentral
|
||||
self.isCentral = isCentral
|
||||
|
||||
self.phoneView.center = CGPoint(x: availableSize.width / 2.0 + mappedPosition * 50.0, y: phoneY)
|
||||
self.phoneView.center = CGPoint(x: availableSize.width / 2.0 + phoneX, y: phoneY)
|
||||
self.phoneView.screenRotation = mappedPosition * -0.7
|
||||
|
||||
var perspective = CATransform3DIdentity
|
||||
var perspective = CATransform3DMakeScale(scale, scale, 1.0)
|
||||
perspective.m34 = mappedPosition / 50.0
|
||||
self.phoneView.layer.transform = CATransform3DRotate(perspective, 0.1, 0, 1, 0)
|
||||
|
||||
|
@ -855,7 +855,7 @@ private final class DemoSheetContent: CombinedComponent {
|
||||
transition: context.transition
|
||||
)
|
||||
|
||||
var contentHeight: CGFloat = context.availableSize.width + 154.0
|
||||
var contentHeight: CGFloat = context.availableSize.width + 146.0
|
||||
if case .other = component.source {
|
||||
contentHeight -= 40.0
|
||||
}
|
||||
@ -865,7 +865,9 @@ private final class DemoSheetContent: CombinedComponent {
|
||||
.position(CGPoint(x: buttonFrame.midX, y: buttonFrame.midY))
|
||||
)
|
||||
|
||||
let contentSize = CGSize(width: context.availableSize.width, height: buttonFrame.maxY + 5.0 + environment.safeInsets.bottom)
|
||||
let bottomPanelPadding: CGFloat = 12.0
|
||||
let bottomInset: CGFloat = environment.safeInsets.bottom > 0.0 ? environment.safeInsets.bottom + 5.0 : bottomPanelPadding
|
||||
let contentSize = CGSize(width: context.availableSize.width, height: buttonFrame.maxY + bottomInset)
|
||||
|
||||
return contentSize
|
||||
}
|
||||
@ -933,12 +935,18 @@ private final class DemoSheetComponent: CombinedComponent {
|
||||
environment
|
||||
SheetComponentEnvironment(
|
||||
isDisplaying: environment.value.isVisible,
|
||||
dismiss: {
|
||||
animateOut.invoke(Action { _ in
|
||||
dismiss: { animated in
|
||||
if animated {
|
||||
animateOut.invoke(Action { _ in
|
||||
if let controller = controller() {
|
||||
controller.dismiss(completion: nil)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if let controller = controller() {
|
||||
controller.dismiss(completion: nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
|
@ -698,7 +698,7 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
let premiumLimit = state.premiumLimits.maxFolderChatsCount
|
||||
iconName = "Premium/Chat"
|
||||
badgeText = "\(component.count)"
|
||||
string = strings.Premium_MaxChatsInFolderCountText("\(limit)", "\(premiumLimit)").string
|
||||
string = strings.Premium_MaxChatsInFolderText("\(limit)", "\(premiumLimit)").string
|
||||
defaultValue = component.count > limit ? "\(limit)" : ""
|
||||
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
||||
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
||||
@ -909,12 +909,18 @@ private final class LimitSheetComponent: CombinedComponent {
|
||||
environment
|
||||
SheetComponentEnvironment(
|
||||
isDisplaying: environment.value.isVisible,
|
||||
dismiss: {
|
||||
animateOut.invoke(Action { _ in
|
||||
dismiss: { animated in
|
||||
if animated {
|
||||
animateOut.invoke(Action { _ in
|
||||
if let controller = controller() {
|
||||
controller.dismiss(completion: nil)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if let controller = controller() {
|
||||
controller.dismiss(completion: nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
|
@ -223,7 +223,7 @@ private class StickersCarouselNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
init(context: AccountContext, stickers: [TelegramMediaFile]) {
|
||||
self.context = context
|
||||
self.stickers = Array(stickers.shuffled().prefix(14))
|
||||
self.stickers = stickers
|
||||
|
||||
self.scrollNode = ASScrollNode()
|
||||
self.tapNode = ASDisplayNode()
|
||||
|
@ -357,6 +357,7 @@ public class WallpaperGalleryController: ViewController {
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, pushController: { _ in
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { controller, ready in
|
||||
|
@ -1,69 +0,0 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramPresentationData
|
||||
import AppBundle
|
||||
|
||||
final class StickerPackPreviewPremiumHeaderItem: GridItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let count: Int32
|
||||
|
||||
let section: GridSection? = nil
|
||||
let fillsRowWithHeight: (CGFloat, Bool)? = (15.0, true)
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, count: Int32) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.count = count
|
||||
}
|
||||
|
||||
func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode {
|
||||
let node = StickerPackPreviewPremiumHeaderItemNode()
|
||||
node.setup(theme: self.theme, strings: self.strings, count: self.count)
|
||||
return node
|
||||
}
|
||||
|
||||
func update(node: GridItemNode) {
|
||||
guard let node = node as? StickerPackPreviewPremiumHeaderItemNode else {
|
||||
assertionFailure()
|
||||
return
|
||||
}
|
||||
node.setup(theme: self.theme, strings: self.strings, count: self.count)
|
||||
}
|
||||
}
|
||||
|
||||
final class StickerPackPreviewPremiumHeaderItemNode: GridItemNode {
|
||||
private var currentState: (PresentationTheme, PresentationStrings, Int32)?
|
||||
|
||||
let labelNode: ImmediateTextNode
|
||||
|
||||
override init() {
|
||||
self.labelNode = ImmediateTextNode()
|
||||
self.labelNode.displaysAsynchronously = false
|
||||
self.labelNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.labelNode)
|
||||
}
|
||||
|
||||
|
||||
func setup(theme: PresentationTheme, strings: PresentationStrings, count: Int32) {
|
||||
if self.currentState?.0 !== theme || self.currentState?.1 !== strings || self.currentState?.2 != count {
|
||||
self.labelNode.attributedText = NSAttributedString(string: strings.StickerPack_PremiumStickers(count), font: Font.medium(12.0), textColor: theme.actionSheet.controlAccentColor)
|
||||
self.currentState = (theme, strings, count)
|
||||
}
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
super.layout()
|
||||
|
||||
let bounds = self.bounds
|
||||
|
||||
let textSize = self.labelNode.updateLayout(bounds.size)
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((bounds.width - textSize.width) / 2.0), y: floor((bounds.height - textSize.height) / 2.0)), size: textSize)
|
||||
self.labelNode.frame = textFrame
|
||||
}
|
||||
}
|
@ -18,14 +18,11 @@ import PremiumUI
|
||||
|
||||
private enum StickerPackPreviewGridEntry: Comparable, Identifiable {
|
||||
case sticker(index: Int, stableId: Int, stickerItem: StickerPackItem?, isEmpty: Bool, isPremium: Bool, isLocked: Bool)
|
||||
case premiumHeader(index: Int, stableId: Int, count: Int32)
|
||||
|
||||
var stableId: Int {
|
||||
switch self {
|
||||
case let .sticker(_, stableId, _, _, _, _):
|
||||
return stableId
|
||||
case let .premiumHeader(_, stableId, _):
|
||||
return stableId
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,8 +30,6 @@ private enum StickerPackPreviewGridEntry: Comparable, Identifiable {
|
||||
switch self {
|
||||
case let .sticker(index, _, _, _, _, _):
|
||||
return index
|
||||
case let .premiumHeader(index, _, _):
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +41,6 @@ private enum StickerPackPreviewGridEntry: Comparable, Identifiable {
|
||||
switch self {
|
||||
case let .sticker(_, _, stickerItem, isEmpty, isPremium, isLocked):
|
||||
return StickerPackPreviewGridItem(account: account, stickerItem: stickerItem, interaction: interaction, theme: theme, isPremium: isPremium, isLocked: isLocked, isEmpty: isEmpty)
|
||||
case let .premiumHeader(_, _, count):
|
||||
return StickerPackPreviewPremiumHeaderItem(theme: theme, strings: strings, count: count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,11 @@ public func getIsGifSaved(transaction: Transaction, mediaId: MediaId) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func addSavedGif(postbox: Postbox, fileReference: FileMediaReference) -> Signal<Void, NoError> {
|
||||
public func addSavedGif(postbox: Postbox, fileReference: FileMediaReference, limit: Int = 200) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Void in
|
||||
if let resource = fileReference.media.resource as? CloudDocumentMediaResource {
|
||||
if let entry = CodableEntry(RecentMediaItem(fileReference.media)) {
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, item: OrderedItemListEntry(id: RecentMediaItemId(fileReference.media.fileId).rawValue, contents: entry), removeTailIfCountExceeds: 200)
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudRecentGifs, item: OrderedItemListEntry(id: RecentMediaItemId(fileReference.media.fileId).rawValue, contents: entry), removeTailIfCountExceeds: limit)
|
||||
}
|
||||
addSynchronizeSavedGifsOperation(transaction: transaction, operation: .add(id: resource.fileId, accessHash: resource.accessHash, fileReference: fileReference))
|
||||
}
|
||||
@ -52,3 +52,48 @@ public func removeSavedGif(postbox: Postbox, mediaId: MediaId) -> Signal<Void, N
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum SavedGifResult {
|
||||
case generic
|
||||
case limitExceeded(Int32, Int32)
|
||||
}
|
||||
|
||||
public func toggleGifSaved(account: Account, fileReference: FileMediaReference, saved: Bool) -> Signal<SavedGifResult, NoError> {
|
||||
if saved {
|
||||
return account.postbox.transaction { transaction -> Signal<SavedGifResult, NoError> in
|
||||
let isPremium = transaction.getPeer(account.peerId)?.isPremium ?? false
|
||||
let items = transaction.getOrderedListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)
|
||||
|
||||
let appConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? .defaultValue
|
||||
let limitsConfiguration = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let premiumLimitsConfiguration = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
let result: SavedGifResult
|
||||
if isPremium && items.count >= premiumLimitsConfiguration.maxSavedGifCount {
|
||||
result = .limitExceeded(premiumLimitsConfiguration.maxSavedGifCount, premiumLimitsConfiguration.maxSavedGifCount)
|
||||
} else if !isPremium && items.count >= limitsConfiguration.maxSavedGifCount {
|
||||
result = .limitExceeded(limitsConfiguration.maxSavedGifCount, premiumLimitsConfiguration.maxSavedGifCount)
|
||||
} else {
|
||||
result = .generic
|
||||
}
|
||||
|
||||
return addSavedGif(postbox: account.postbox, fileReference: fileReference, limit: Int(isPremium ? premiumLimitsConfiguration.maxSavedGifCount : limitsConfiguration.maxSavedGifCount))
|
||||
|> map { _ -> SavedGifResult in
|
||||
return .generic
|
||||
}
|
||||
|> filter { _ in
|
||||
return false
|
||||
}
|
||||
|> then(
|
||||
.single(result)
|
||||
)
|
||||
}
|
||||
|> switchToLatest
|
||||
} else {
|
||||
return removeSavedSticker(postbox: account.postbox, mediaId: fileReference.media.fileId)
|
||||
|> map { _ -> SavedGifResult in
|
||||
return .generic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ public func getIsStickerSaved(transaction: Transaction, fileId: MediaId) -> Bool
|
||||
}
|
||||
}
|
||||
|
||||
public func addSavedSticker(postbox: Postbox, network: Network, file: TelegramMediaFile) -> Signal<Void, AddSavedStickerError> {
|
||||
public func addSavedSticker(postbox: Postbox, network: Network, file: TelegramMediaFile, limit: Int = 5) -> Signal<Void, AddSavedStickerError> {
|
||||
return postbox.transaction { transaction -> Signal<Void, AddSavedStickerError> in
|
||||
for attribute in file.attributes {
|
||||
if case let .Sticker(_, maybePackReference, _) = attribute, let packReference = maybePackReference {
|
||||
@ -107,10 +107,10 @@ public func addSavedSticker(postbox: Postbox, network: Network, file: TelegramMe
|
||||
} |> mapError { _ -> AddSavedStickerError in } |> switchToLatest
|
||||
}
|
||||
|
||||
public func addSavedSticker(transaction: Transaction, file: TelegramMediaFile, stringRepresentations: [String]) {
|
||||
public func addSavedSticker(transaction: Transaction, file: TelegramMediaFile, stringRepresentations: [String], limit: Int = 5) {
|
||||
if let resource = file.resource as? CloudDocumentMediaResource {
|
||||
if let entry = CodableEntry(SavedStickerItem(file: file, stringRepresentations: stringRepresentations)) {
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudSavedStickers, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: entry), removeTailIfCountExceeds: 5)
|
||||
transaction.addOrMoveToFirstPositionOrderedItemListItem(collectionId: Namespaces.OrderedItemList.CloudSavedStickers, item: OrderedItemListEntry(id: RecentMediaItemId(file.fileId).rawValue, contents: entry), removeTailIfCountExceeds: limit)
|
||||
}
|
||||
addSynchronizeSavedStickersOperation(transaction: transaction, operation: .add(id: resource.fileId, accessHash: resource.accessHash, fileReference: .standalone(media: file)))
|
||||
}
|
||||
|
@ -9,8 +9,9 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
public let maxFavedStickerCount: Int32
|
||||
public let maxFoldersCount: Int32
|
||||
public let maxFolderChatsCount: Int32
|
||||
public let maxCaptionLengthCount: Int32
|
||||
public let maxCaptionLength: Int32
|
||||
public let maxUploadFileParts: Int32
|
||||
public let maxAboutLength: Int32
|
||||
public let maxAnimatedEmojisInText: Int32
|
||||
|
||||
public static var defaultValue: UserLimitsConfiguration {
|
||||
@ -22,8 +23,9 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
maxFavedStickerCount: 5,
|
||||
maxFoldersCount: 10,
|
||||
maxFolderChatsCount: 100,
|
||||
maxCaptionLengthCount: 1024,
|
||||
maxCaptionLength: 1024,
|
||||
maxUploadFileParts: 4000,
|
||||
maxAboutLength: 70,
|
||||
maxAnimatedEmojisInText: 10
|
||||
)
|
||||
}
|
||||
@ -36,8 +38,9 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
maxFavedStickerCount: Int32,
|
||||
maxFoldersCount: Int32,
|
||||
maxFolderChatsCount: Int32,
|
||||
maxCaptionLengthCount: Int32,
|
||||
maxCaptionLength: Int32,
|
||||
maxUploadFileParts: Int32,
|
||||
maxAboutLength: Int32,
|
||||
maxAnimatedEmojisInText: Int32
|
||||
) {
|
||||
self.maxPinnedChatCount = maxPinnedChatCount
|
||||
@ -47,8 +50,9 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
self.maxFavedStickerCount = maxFavedStickerCount
|
||||
self.maxFoldersCount = maxFoldersCount
|
||||
self.maxFolderChatsCount = maxFolderChatsCount
|
||||
self.maxCaptionLengthCount = maxCaptionLengthCount
|
||||
self.maxCaptionLength = maxCaptionLength
|
||||
self.maxUploadFileParts = maxUploadFileParts
|
||||
self.maxAboutLength = maxAboutLength
|
||||
self.maxAnimatedEmojisInText = maxAnimatedEmojisInText
|
||||
}
|
||||
}
|
||||
@ -81,8 +85,9 @@ extension UserLimitsConfiguration {
|
||||
self.maxFavedStickerCount = getValue("stickers_faved_limit", orElse: defaultValue.maxFavedStickerCount)
|
||||
self.maxFoldersCount = getValue("dialog_filters_limit", orElse: defaultValue.maxFoldersCount)
|
||||
self.maxFolderChatsCount = getValue("dialog_filters_chats_limit", orElse: defaultValue.maxFolderChatsCount)
|
||||
self.maxCaptionLengthCount = getValue("caption_length_limit", orElse: defaultValue.maxCaptionLengthCount)
|
||||
self.maxCaptionLength = getValue("caption_length_limit", orElse: defaultValue.maxCaptionLength)
|
||||
self.maxUploadFileParts = getValue("upload_max_fileparts", orElse: defaultValue.maxUploadFileParts)
|
||||
self.maxAboutLength = getValue("about_length_limit", orElse: defaultValue.maxAboutLength)
|
||||
self.maxAnimatedEmojisInText = getGeneralValue("message_animated_emoji_max", orElse: defaultValue.maxAnimatedEmojisInText)
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,9 @@ public enum EngineConfiguration {
|
||||
public let maxFavedStickerCount: Int32
|
||||
public let maxFoldersCount: Int32
|
||||
public let maxFolderChatsCount: Int32
|
||||
public let maxCaptionLengthCount: Int32
|
||||
public let maxCaptionLength: Int32
|
||||
public let maxUploadFileParts: Int32
|
||||
public let maxAboutLength: Int32
|
||||
public let maxAnimatedEmojisInText: Int32
|
||||
|
||||
public static var defaultValue: UserLimits {
|
||||
@ -74,8 +75,9 @@ public enum EngineConfiguration {
|
||||
maxFavedStickerCount: Int32,
|
||||
maxFoldersCount: Int32,
|
||||
maxFolderChatsCount: Int32,
|
||||
maxCaptionLengthCount: Int32,
|
||||
maxCaptionLength: Int32,
|
||||
maxUploadFileParts: Int32,
|
||||
maxAboutLength: Int32,
|
||||
maxAnimatedEmojisInText: Int32
|
||||
) {
|
||||
self.maxPinnedChatCount = maxPinnedChatCount
|
||||
@ -85,8 +87,9 @@ public enum EngineConfiguration {
|
||||
self.maxFavedStickerCount = maxFavedStickerCount
|
||||
self.maxFoldersCount = maxFoldersCount
|
||||
self.maxFolderChatsCount = maxFolderChatsCount
|
||||
self.maxCaptionLengthCount = maxCaptionLengthCount
|
||||
self.maxCaptionLength = maxCaptionLength
|
||||
self.maxUploadFileParts = maxUploadFileParts
|
||||
self.maxAboutLength = maxAboutLength
|
||||
self.maxAnimatedEmojisInText = maxAnimatedEmojisInText
|
||||
}
|
||||
}
|
||||
@ -142,8 +145,9 @@ public extension EngineConfiguration.UserLimits {
|
||||
maxFavedStickerCount: userLimitsConfiguration.maxFavedStickerCount,
|
||||
maxFoldersCount: userLimitsConfiguration.maxFoldersCount,
|
||||
maxFolderChatsCount: userLimitsConfiguration.maxFolderChatsCount,
|
||||
maxCaptionLengthCount: userLimitsConfiguration.maxCaptionLengthCount,
|
||||
maxCaptionLength: userLimitsConfiguration.maxCaptionLength,
|
||||
maxUploadFileParts: userLimitsConfiguration.maxUploadFileParts,
|
||||
maxAboutLength: userLimitsConfiguration.maxAboutLength,
|
||||
maxAnimatedEmojisInText: userLimitsConfiguration.maxAnimatedEmojisInText
|
||||
)
|
||||
}
|
||||
|
@ -16,9 +16,18 @@ func _internal_toggleStickerSaved(postbox: Postbox, network: Network, accountPee
|
||||
|
||||
let appConfiguration = transaction.getPreferencesEntry(key: PreferencesKeys.appConfiguration)?.get(AppConfiguration.self) ?? .defaultValue
|
||||
let limitsConfiguration = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let premiumLimitsConfiguration = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let premiumLimitsConfiguration = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
return addSavedSticker(postbox: postbox, network: network, file: file)
|
||||
let result: SavedStickerResult
|
||||
if isPremium && items.count >= premiumLimitsConfiguration.maxFavedStickerCount {
|
||||
result = .limitExceeded(premiumLimitsConfiguration.maxFavedStickerCount, premiumLimitsConfiguration.maxFavedStickerCount)
|
||||
} else if !isPremium && items.count >= limitsConfiguration.maxFavedStickerCount {
|
||||
result = .limitExceeded(limitsConfiguration.maxFavedStickerCount, premiumLimitsConfiguration.maxFavedStickerCount)
|
||||
} else {
|
||||
result = .generic
|
||||
}
|
||||
|
||||
return addSavedSticker(postbox: postbox, network: network, file: file, limit: Int(isPremium ? premiumLimitsConfiguration.maxFavedStickerCount : limitsConfiguration.maxFavedStickerCount))
|
||||
|> map { _ -> SavedStickerResult in
|
||||
return .generic
|
||||
}
|
||||
@ -26,7 +35,7 @@ func _internal_toggleStickerSaved(postbox: Postbox, network: Network, accountPee
|
||||
return false
|
||||
}
|
||||
|> then(
|
||||
items.count == limitsConfiguration.maxFavedStickerCount && !isPremium ? .single(.limitExceeded(limitsConfiguration.maxFavedStickerCount, premiumLimitsConfiguration.maxFavedStickerCount)) : .single(.generic)
|
||||
.single(result)
|
||||
)
|
||||
}
|
||||
|> castError(AddSavedStickerError.self)
|
||||
|
@ -7982,7 +7982,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
case .generic:
|
||||
strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: nil, text: added ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: true, action: { _ in return false }), with: nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: true, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.presentationData.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: stickerFile, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: true, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
|
@ -1213,10 +1213,33 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
if let file = media as? TelegramMediaFile, !chatPresentationInterfaceState.copyProtectionEnabled && !message.isCopyProtected() {
|
||||
if file.isVideo {
|
||||
if file.isAnimated && !file.isVideoSticker {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_LinkDialogSave, icon: { theme in
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_SaveGif, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Save"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { _, f in
|
||||
let _ = addSavedGif(postbox: context.account.postbox, fileReference: .message(message: MessageReference(message), media: file)).start()
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let _ = (toggleGifSaved(account: context.account, fileReference: .message(message: MessageReference(message), media: file), saved: true)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .generic:
|
||||
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsFinalText
|
||||
} else {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
|
||||
}
|
||||
controllerInteraction.presentControllerInCurrent(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
|
||||
controllerInteraction.navigationController()?.pushViewController(controller)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), nil)
|
||||
}
|
||||
})
|
||||
|
||||
f(.default)
|
||||
})))
|
||||
}
|
||||
|
@ -1487,9 +1487,32 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: file.file).start()
|
||||
|
||||
strongSelf.controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
let context = strongSelf.context
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controllerInteraction = strongSelf.controllerInteraction
|
||||
let _ = (toggleGifSaved(account: context.account, fileReference: file.file, saved: true)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .generic:
|
||||
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsFinalText
|
||||
} else {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
|
||||
}
|
||||
controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
|
||||
controllerInteraction.navigationController()?.pushViewController(controller)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), nil)
|
||||
}
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
@ -1581,7 +1604,13 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
case .generic:
|
||||
strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
@ -1727,7 +1756,13 @@ final class ChatMediaInputNode: ChatInputNode {
|
||||
case .generic:
|
||||
strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.controllerInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
|
@ -502,7 +502,13 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
|
||||
case .generic:
|
||||
strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), with: nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.presentationData.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
@ -583,7 +589,13 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode {
|
||||
case .generic:
|
||||
strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.presentationData.strings.Conversation_StickerAddedToFavorites : strongSelf.presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), with: nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.presentationData.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.controller?.presentInGlobalOverlay(UndoOverlayController(presentationData: strongSelf.presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
|
@ -193,10 +193,32 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = addSavedGif(postbox: strongSelf.context.account.postbox, fileReference: .standalone(media: file)).start()
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
strongSelf.interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: strongSelf.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
let context = strongSelf.context
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let interfaceInteraction = strongSelf.interfaceInteraction
|
||||
let _ = (toggleGifSaved(account: context.account, fileReference: .standalone(media: file), saved: true)
|
||||
|> deliverOnMainQueue).start(next: { result in
|
||||
switch result {
|
||||
case .generic:
|
||||
interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: nil, text: presentationData.strings.Gallery_GifSaved), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsFinalText
|
||||
} else {
|
||||
text = presentationData.strings.Premium_MaxSavedGifsText("\(premiumLimit)").string
|
||||
}
|
||||
interfaceInteraction?.presentController(UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_gif", scale: 0.075, colors: [:], title: presentationData.strings.Premium_MaxSavedGifsTitle("\(limit)").string, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: context, source: .savedGifs)
|
||||
interfaceInteraction?.getNavigationController()?.pushViewController(controller)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}), nil)
|
||||
}
|
||||
})
|
||||
})))
|
||||
}
|
||||
menuItems.append(.action(ContextMenuActionItem(text: strongSelf.strings.ShareMenu_Send, icon: { theme in
|
||||
|
@ -193,7 +193,13 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode {
|
||||
case .generic:
|
||||
strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
|
@ -145,7 +145,13 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie
|
||||
case .generic:
|
||||
strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.getControllerInteraction?()?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
|
@ -25,6 +25,7 @@ import LocationUI
|
||||
import AppLock
|
||||
import WallpaperBackgroundNode
|
||||
import InAppPurchaseManager
|
||||
import PremiumUI
|
||||
|
||||
private final class AccountUserInterfaceInUseContext {
|
||||
let subscribers = Bag<(Bool) -> Void>()
|
||||
@ -1461,6 +1462,43 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
public func makePrivacyAndSecurityController(context: AccountContext) -> ViewController {
|
||||
return SettingsUI.makePrivacyAndSecurityController(context: context)
|
||||
}
|
||||
|
||||
public func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource) -> ViewController {
|
||||
let mappedSource: PremiumSource
|
||||
switch source {
|
||||
case .settings:
|
||||
mappedSource = .settings
|
||||
case .stickers:
|
||||
mappedSource = .stickers
|
||||
case .reactions:
|
||||
mappedSource = .reactions
|
||||
case .ads:
|
||||
mappedSource = .ads
|
||||
case .upload:
|
||||
mappedSource = .upload
|
||||
case .groupsAndChannels:
|
||||
mappedSource = .groupsAndChannels
|
||||
case .pinnedChats:
|
||||
mappedSource = .pinnedChats
|
||||
case .publicLinks:
|
||||
mappedSource = .publicLinks
|
||||
case .savedGifs:
|
||||
mappedSource = .savedGifs
|
||||
case .savedStickers:
|
||||
mappedSource = .savedStickers
|
||||
case .folders:
|
||||
mappedSource = .folders
|
||||
case .chatsPerFolder:
|
||||
mappedSource = .chatsPerFolder
|
||||
case .accounts:
|
||||
mappedSource = .accounts
|
||||
case let .deeplink(reference):
|
||||
mappedSource = .deeplink(reference)
|
||||
case let .profile(peerId):
|
||||
mappedSource = .profile(peerId)
|
||||
}
|
||||
return PremiumIntroScreen(context: context, source: mappedSource)
|
||||
}
|
||||
}
|
||||
|
||||
private func peerInfoControllerImpl(context: AccountContext, updatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, requestsContext: PeerInvitationImportersContext? = nil) -> ViewController? {
|
||||
|
@ -149,7 +149,13 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode {
|
||||
case .generic:
|
||||
strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: nil, text: !isStarred ? strongSelf.strings.Conversation_StickerAddedToFavorites : strongSelf.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false }), nil)
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
let text: String
|
||||
if limit == premiumLimit {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersFinalText
|
||||
} else {
|
||||
text = strongSelf.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string
|
||||
}
|
||||
strongSelf.interfaceInteraction?.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: strongSelf.context, file: item.file, title: strongSelf.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { [weak self] action in
|
||||
if let strongSelf = self {
|
||||
if case .info = action {
|
||||
let controller = PremiumIntroScreen(context: strongSelf.context, source: .savedStickers)
|
||||
|
@ -829,9 +829,14 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
||||
}), textAlignment: .natural)
|
||||
self.textNode.attributedText = attributedText
|
||||
|
||||
|
||||
if text.contains("](") {
|
||||
isUserInteractionEnabled = true
|
||||
}
|
||||
self.originalRemainingSeconds = isUserInteractionEnabled ? 5 : 3
|
||||
|
||||
self.textNode.maximumNumberOfLines = 5
|
||||
displayUndo = false
|
||||
self.originalRemainingSeconds = 3
|
||||
case let .image(image, text):
|
||||
self.avatarNode = nil
|
||||
self.iconNode = ASImageNode()
|
||||
|
@ -219,6 +219,7 @@ class WebSearchGalleryController: ViewController {
|
||||
if let strongSelf = self {
|
||||
strongSelf.present(controller, in: .window(.root), with: arguments, blockInteraction: true)
|
||||
}
|
||||
}, pushController: { _ in
|
||||
}, dismissController: { [weak self] in
|
||||
self?.dismiss(forceAway: true)
|
||||
}, replaceRootController: { [weak self] controller, ready in
|
||||
|
Loading…
x
Reference in New Issue
Block a user