Various improvements

This commit is contained in:
Ilya Laktyushin 2022-05-28 19:28:58 +04:00
parent 9e38b1736d
commit 7b0e7a47af
32 changed files with 355 additions and 124 deletions

View File

@ -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";

View File

@ -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?

View File

@ -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()

View File

@ -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/") {
@ -1425,9 +1448,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/") {

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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
}
}

View File

@ -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)
}
}
}

View File

@ -30,11 +30,11 @@ public func isGifSaved(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
}
}
}

View File

@ -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)))
}

View 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)
}
}

View File

@ -55,8 +55,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 {
@ -71,8 +72,9 @@ public enum EngineConfiguration {
maxFavedStickerCount: Int32,
maxFoldersCount: Int32,
maxFolderChatsCount: Int32,
maxCaptionLengthCount: Int32,
maxCaptionLength: Int32,
maxUploadFileParts: Int32,
maxAboutLength: Int32,
maxAnimatedEmojisInText: Int32
) {
self.maxPinnedChatCount = maxPinnedChatCount
@ -82,8 +84,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
}
}
@ -118,8 +121,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
)
}

View File

@ -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)

View File

@ -7983,7 +7983,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)

View File

@ -1215,10 +1215,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)
})))
}

View File

@ -1490,9 +1490,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)
}
})
})))
}
@ -1586,7 +1609,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)
@ -1730,7 +1759,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)

View File

@ -504,7 +504,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)
@ -587,7 +593,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)

View File

@ -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

View File

@ -195,7 +195,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)

View File

@ -147,7 +147,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)

View File

@ -25,6 +25,7 @@ import LocationUI
import AppLock
import WallpaperBackgroundNode
import InAppPurchaseManager
import PremiumUI
private final class AccountUserInterfaceInUseContext {
let subscribers = Bag<(Bool) -> Void>()
@ -1459,6 +1460,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? {

View File

@ -151,7 +151,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)

View File

@ -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()

View File

@ -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