mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
# Conflicts: # submodules/TelegramCore/Sources/TelegramEngine/Peers/AdPeers.swift
This commit is contained in:
commit
fd20831e92
@ -14034,3 +14034,26 @@ Sorry for the inconvenience.";
|
|||||||
"Privacy.Gifts.PremiumToast.Action" = "Open";
|
"Privacy.Gifts.PremiumToast.Action" = "Open";
|
||||||
|
|
||||||
"Gift.Send.ErrorDisallowed" = "**%@** doesn't accept this kind of gifts.";
|
"Gift.Send.ErrorDisallowed" = "**%@** doesn't accept this kind of gifts.";
|
||||||
|
|
||||||
|
"ChatbotSetup.Rights.ManageMessages" = "Manage Messages";
|
||||||
|
"ChatbotSetup.Rights.ReadMessages" = "Read Messages";
|
||||||
|
"ChatbotSetup.Rights.ReplyToMessages" = "Reply to Messages";
|
||||||
|
"ChatbotSetup.Rights.MarkAsRead" = "Mark Messages as Read";
|
||||||
|
"ChatbotSetup.Rights.DeleteSentMessages" = "Delete Sent Messages";
|
||||||
|
"ChatbotSetup.Rights.DeleteReceivedMessages" = "Delete Received Messages";
|
||||||
|
|
||||||
|
"ChatbotSetup.Rights.ManageProfile" = "Manage Profile";
|
||||||
|
"ChatbotSetup.Rights.EditName" = "Edit Name";
|
||||||
|
"ChatbotSetup.Rights.EditBio" = "Edit Bio";
|
||||||
|
"ChatbotSetup.Rights.EditProfilePhoto" = "Edit Profile Photo";
|
||||||
|
"ChatbotSetup.Rights.EditUsername" = "Edit Username";
|
||||||
|
|
||||||
|
"ChatbotSetup.Rights.ManageGiftsAndStars" = "Manage Gifts and Stars";
|
||||||
|
"ChatbotSetup.Rights.ViewGifts" = "View Gifts";
|
||||||
|
"ChatbotSetup.Rights.SellGifts" = "Sell Gifts";
|
||||||
|
"ChatbotSetup.Rights.ChangeGiftSettings" = "Change Gift Settings";
|
||||||
|
"ChatbotSetup.Rights.TransferAndUpgradeGifts" = "Transfer and Upgrade Gifts";
|
||||||
|
"ChatbotSetup.Rights.TransferStars" = "Transfer Stars";
|
||||||
|
"ChatbotSetup.Rights.ManageStories" = "Manage Stories";
|
||||||
|
|
||||||
|
"Gift.Send.Upgrade.ForcedInfo" = "%1$@ accepts only unique gifts. [Learn More >]()";
|
||||||
|
@ -114,6 +114,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/LottieComponent",
|
"//submodules/TelegramUI/Components/LottieComponent",
|
||||||
"//submodules/TelegramUI/Components/AvatarUploadToastScreen",
|
"//submodules/TelegramUI/Components/AvatarUploadToastScreen",
|
||||||
"//submodules/TelegramUI/Components/Ads/AdsInfoScreen",
|
"//submodules/TelegramUI/Components/Ads/AdsInfoScreen",
|
||||||
|
"//submodules/TelegramUI/Components/Ads/AdsReportScreen",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -54,6 +54,7 @@ import OldChannelsController
|
|||||||
import TextFormat
|
import TextFormat
|
||||||
import AvatarUploadToastScreen
|
import AvatarUploadToastScreen
|
||||||
import AdsInfoScreen
|
import AdsInfoScreen
|
||||||
|
import AdsReportScreen
|
||||||
|
|
||||||
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
|
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
|
||||||
let controller: ViewController
|
let controller: ViewController
|
||||||
@ -6131,15 +6132,16 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.push(controller)
|
self.push(controller)
|
||||||
}
|
}
|
||||||
|
|
||||||
func openAdInfo(_ node: ASDisplayNode) {
|
func openAdInfo(node: ASDisplayNode, adPeer: AdPeer) {
|
||||||
let controller = self
|
let controller = self
|
||||||
let referenceView = node.view
|
let referenceView = node.view
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
|
//TODO:localize
|
||||||
var actions: [ContextMenuItem] = []
|
var actions: [ContextMenuItem] = []
|
||||||
//if adAttribute.sponsorInfo != nil || adAttribute.additionalInfo != nil {
|
if adPeer.sponsorInfo != nil || adPeer.additionalInfo != nil {
|
||||||
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfo, textColor: .primary, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfo, textColor: .primary, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Channels"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Channels"), color: theme.actionSheet.primaryTextColor)
|
||||||
}, iconSource: nil, action: { [weak self] c, _ in
|
}, iconSource: nil, action: { [weak self] c, _ in
|
||||||
@ -6154,32 +6156,40 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|
|
||||||
subItems.append(.separator)
|
subItems.append(.separator)
|
||||||
|
|
||||||
// if let sponsorInfo = adAttribute.sponsorInfo {
|
if let sponsorInfo = adPeer.sponsorInfo {
|
||||||
// subItems.append(.action(ContextMenuActionItem(text: sponsorInfo, textColor: .primary, textLayout: .multiline, textFont: .custom(font: Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 0.8)), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
subItems.append(.action(ContextMenuActionItem(text: sponsorInfo, textColor: .primary, textLayout: .multiline, textFont: .custom(font: Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 0.8)), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
||||||
// return nil
|
return nil
|
||||||
// }, iconSource: nil, action: { [weak self] c, _ in
|
}, iconSource: nil, action: { [weak self] c, _ in
|
||||||
// c?.dismiss(completion: {
|
c?.dismiss(completion: {
|
||||||
// UIPasteboard.general.string = sponsorInfo
|
UIPasteboard.general.string = sponsorInfo
|
||||||
//
|
|
||||||
// self?.displayUndo(.copy(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfoCopied))
|
if let self {
|
||||||
// })
|
self.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfoCopied), elevatedLayout: false, action: { _ in
|
||||||
// })))
|
return true
|
||||||
// }
|
}), in: .current)
|
||||||
// if let additionalInfo = adAttribute.additionalInfo {
|
}
|
||||||
// subItems.append(.action(ContextMenuActionItem(text: additionalInfo, textColor: .primary, textLayout: .multiline, textFont: .custom(font: Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 0.8)), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
})
|
||||||
// return nil
|
})))
|
||||||
// }, iconSource: nil, action: { [weak self] c, _ in
|
}
|
||||||
// c?.dismiss(completion: {
|
if let additionalInfo = adPeer.additionalInfo {
|
||||||
// UIPasteboard.general.string = additionalInfo
|
subItems.append(.action(ContextMenuActionItem(text: additionalInfo, textColor: .primary, textLayout: .multiline, textFont: .custom(font: Font.regular(floor(presentationData.listsFontSize.baseDisplaySize * 0.8)), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
||||||
//
|
return nil
|
||||||
// self?.displayUndo(.copy(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfoCopied))
|
}, iconSource: nil, action: { [weak self] c, _ in
|
||||||
// })
|
c?.dismiss(completion: {
|
||||||
// })))
|
UIPasteboard.general.string = additionalInfo
|
||||||
// }
|
|
||||||
|
if let self {
|
||||||
|
self.present(UndoOverlayController(presentationData: presentationData, content: .copy(text: presentationData.strings.Chat_ContextMenu_AdSponsorInfoCopied), elevatedLayout: false, action: { _ in
|
||||||
|
return true
|
||||||
|
}), in: .current)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
c?.pushItems(items: .single(ContextController.Items(content: .list(subItems))))
|
c?.pushItems(items: .single(ContextController.Items(content: .list(subItems))))
|
||||||
})))
|
})))
|
||||||
//}
|
}
|
||||||
|
|
||||||
actions.append(.action(ContextMenuActionItem(text: "About These Ads", textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
actions.append(.action(ContextMenuActionItem(text: "About These Ads", textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
|
||||||
@ -6190,70 +6200,59 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if "".isEmpty {
|
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_ReportAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
||||||
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_ReportAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor)
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Restrict"), color: theme.actionSheet.primaryTextColor)
|
}, iconSource: nil, action: { [weak self] _, f in
|
||||||
}, iconSource: nil, action: { [weak self] _, f in
|
f(.default)
|
||||||
f(.default)
|
|
||||||
|
guard let navigationController = self?.navigationController as? NavigationController else {
|
||||||
guard let navigationController = self?.navigationController as? NavigationController else {
|
return
|
||||||
return
|
}
|
||||||
|
|
||||||
|
let _ = (context.engine.messages.reportAdMessage(opaqueId: adPeer.opaqueId, option: nil)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak navigationController] result in
|
||||||
|
if case let .options(title, options) = result {
|
||||||
|
Queue.mainQueue().after(0.2) {
|
||||||
|
navigationController?.pushViewController(
|
||||||
|
AdsReportScreen(
|
||||||
|
context: context,
|
||||||
|
opaqueId: adPeer.opaqueId,
|
||||||
|
title: title,
|
||||||
|
options: options,
|
||||||
|
completed: {
|
||||||
|
//removeAd?(adAttribute.opaqueId)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let _ = navigationController
|
})
|
||||||
//.dismiss(animated: true)
|
})))
|
||||||
|
|
||||||
// let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|
actions.append(.separator)
|
||||||
// |> deliverOnMainQueue).start(next: { [weak navigationController] result in
|
|
||||||
// if case let .options(title, options) = result {
|
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_RemoveAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
||||||
// Queue.mainQueue().after(0.2) {
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
|
||||||
// navigationController?.pushViewController(
|
}, iconSource: nil, action: { [weak self] c, _ in
|
||||||
// AdsReportScreen(
|
guard let navigationController = self?.navigationController as? NavigationController else {
|
||||||
// context: context,
|
return
|
||||||
// peerId: message.id.peerId,
|
}
|
||||||
// opaqueId: adAttribute.opaqueId,
|
c?.dismiss(completion: {
|
||||||
// title: title,
|
if context.isPremium && !"".isEmpty {
|
||||||
// options: options,
|
//removeAd?(adAttribute.opaqueId)
|
||||||
// completed: {
|
} else {
|
||||||
// removeAd?(adAttribute.opaqueId)
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
// }
|
let demoController = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: false, action: {
|
||||||
// )
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil)
|
||||||
// )
|
replaceImpl?(controller)
|
||||||
// }
|
}, dismissed: nil)
|
||||||
// }
|
replaceImpl = { [weak demoController] c in
|
||||||
// })
|
demoController?.replace(with: c)
|
||||||
})))
|
}
|
||||||
|
navigationController.pushViewController(demoController)
|
||||||
actions.append(.separator)
|
}
|
||||||
|
})
|
||||||
actions.append(.action(ContextMenuActionItem(text: presentationData.strings.Chat_ContextMenu_RemoveAd, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
})))
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
}, iconSource: nil, action: { [weak self] c, _ in
|
|
||||||
c?.dismiss(completion: {
|
|
||||||
let _ = self
|
|
||||||
// if context.isPremium {
|
|
||||||
// removeAd?(adAttribute.opaqueId)
|
|
||||||
// } else {
|
|
||||||
// self?.presentNoAdsDemo()
|
|
||||||
// }
|
|
||||||
})
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
// } else {
|
|
||||||
// if !actions.isEmpty {
|
|
||||||
// actions.append(.separator)
|
|
||||||
// }
|
|
||||||
// actions.append(.action(ContextMenuActionItem(text: presentationData.strings.SponsoredMessageMenu_Hide, textColor: .primary, textLayout: .twoLinesMax, textFont: .custom(font: Font.regular(presentationData.listsFontSize.baseDisplaySize - 1.0), height: nil, verticalOffset: nil), badge: nil, icon: { theme in
|
|
||||||
// return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Clear"), color: theme.actionSheet.primaryTextColor)
|
|
||||||
// }, iconSource: nil, action: { [weak self] c, _ in
|
|
||||||
// c?.dismiss(completion: {
|
|
||||||
// if context.isPremium {
|
|
||||||
// removeAd?(adAttribute.opaqueId)
|
|
||||||
// } else {
|
|
||||||
// self?.presentNoAdsDemo()
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// })))
|
|
||||||
// }
|
|
||||||
|
|
||||||
let contextController = ContextController(presentationData: presentationData, source: .reference(AdsInfoContextReferenceContentSource(controller: controller, sourceView: referenceView, insets: .zero, contentInsets: .zero)), items: .single(ContextController.Items(content: .list(actions))), gesture: nil)
|
let contextController = ContextController(presentationData: presentationData, source: .reference(AdsInfoContextReferenceContentSource(controller: controller, sourceView: referenceView, insets: .zero, contentInsets: .zero)), items: .single(ContextController.Items(content: .list(actions))), gesture: nil)
|
||||||
controller.presentInGlobalOverlay(contextController)
|
controller.presentInGlobalOverlay(contextController)
|
||||||
|
@ -1684,8 +1684,8 @@ final class ChatListControllerNode: ASDisplayNode, ASGestureRecognizerDelegate {
|
|||||||
contentNode.dismissSearch = { [weak self] in
|
contentNode.dismissSearch = { [weak self] in
|
||||||
self?.dismissSearch?()
|
self?.dismissSearch?()
|
||||||
}
|
}
|
||||||
contentNode.openAdInfo = { [weak self] node in
|
contentNode.openAdInfo = { [weak self] node, adPeer in
|
||||||
self?.controller?.openAdInfo(node)
|
self?.controller?.openAdInfo(node: node, adPeer: adPeer)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: contentNode, cancel: { [weak self] in
|
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, contentNode: contentNode, cancel: { [weak self] in
|
||||||
|
@ -62,9 +62,9 @@ final class ChatListSearchInteraction {
|
|||||||
let openStories: ((PeerId, ASDisplayNode) -> Void)?
|
let openStories: ((PeerId, ASDisplayNode) -> Void)?
|
||||||
let switchToFilter: (ChatListSearchPaneKey) -> Void
|
let switchToFilter: (ChatListSearchPaneKey) -> Void
|
||||||
let dismissSearch: () -> Void
|
let dismissSearch: () -> Void
|
||||||
let openAdInfo: (ASDisplayNode) -> Void
|
let openAdInfo: (ASDisplayNode, AdPeer) -> Void
|
||||||
|
|
||||||
init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?, openStories: ((PeerId, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void, openAdInfo: @escaping (ASDisplayNode) -> Void) {
|
init(openPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, openUrl: @escaping (String) -> Void, clearRecentSearch: @escaping () -> Void, addContact: @escaping (String) -> Void, toggleMessageSelection: @escaping (EngineMessage.Id, Bool) -> Void, messageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int64, isFirstInList: Bool)?) -> Void), mediaMessageContextAction: @escaping ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?) -> Void), peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismissInput: @escaping () -> Void, getSelectedMessageIds: @escaping () -> Set<EngineMessage.Id>?, openStories: ((PeerId, ASDisplayNode) -> Void)?, switchToFilter: @escaping (ChatListSearchPaneKey) -> Void, dismissSearch: @escaping () -> Void, openAdInfo: @escaping (ASDisplayNode, AdPeer) -> Void) {
|
||||||
self.openPeer = openPeer
|
self.openPeer = openPeer
|
||||||
self.openDisabledPeer = openDisabledPeer
|
self.openDisabledPeer = openDisabledPeer
|
||||||
self.openMessage = openMessage
|
self.openMessage = openMessage
|
||||||
@ -105,7 +105,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
private let navigationController: NavigationController?
|
private let navigationController: NavigationController?
|
||||||
|
|
||||||
var dismissSearch: (() -> Void)?
|
var dismissSearch: (() -> Void)?
|
||||||
var openAdInfo: ((ASDisplayNode) -> Void)?
|
var openAdInfo: ((ASDisplayNode, AdPeer) -> Void)?
|
||||||
|
|
||||||
private let dimNode: ASDisplayNode
|
private let dimNode: ASDisplayNode
|
||||||
let filterContainerNode: ChatListSearchFiltersContainerNode
|
let filterContainerNode: ChatListSearchFiltersContainerNode
|
||||||
@ -307,8 +307,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||||||
}
|
}
|
||||||
}, dismissSearch: { [weak self] in
|
}, dismissSearch: { [weak self] in
|
||||||
self?.dismissSearch?()
|
self?.dismissSearch?()
|
||||||
}, openAdInfo: { [weak self] node in
|
}, openAdInfo: { [weak self] node, adPeer in
|
||||||
self?.openAdInfo?(node)
|
self?.openAdInfo?(node, adPeer)
|
||||||
})
|
})
|
||||||
self.paneContainerNode.interaction = interaction
|
self.paneContainerNode.interaction = interaction
|
||||||
|
|
||||||
|
@ -439,8 +439,9 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
|
|
||||||
case topic(EnginePeer, ChatListItemContent.ThreadInfo, Int, PresentationTheme, PresentationStrings, ChatListSearchSectionExpandType)
|
case topic(EnginePeer, ChatListItemContent.ThreadInfo, Int, PresentationTheme, PresentationStrings, ChatListSearchSectionExpandType)
|
||||||
case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PeerStoryStats?, Bool)
|
case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PeerStoryStats?, Bool)
|
||||||
|
case adPeer(AdPeer, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, String?)
|
||||||
case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool, Bool)
|
case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool, Bool)
|
||||||
case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool, String?, Bool)
|
case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType, PeerStoryStats?, Bool, String?)
|
||||||
case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, EngineMessageHistoryThread.Info?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int64, isFirstInList: Bool)?, MessageSection, Bool, PeerStoryStats?, Bool, TelegramSearchPeersScope)
|
case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, EngineMessageHistoryThread.Info?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int64, isFirstInList: Bool)?, MessageSection, Bool, PeerStoryStats?, Bool, TelegramSearchPeersScope)
|
||||||
case messagePlaceholder(Int32, ChatListPresentationData, TelegramSearchPeersScope)
|
case messagePlaceholder(Int32, ChatListPresentationData, TelegramSearchPeersScope)
|
||||||
case emptyMessagesFooter(ChatListPresentationData, TelegramSearchPeersScope, String?)
|
case emptyMessagesFooter(ChatListPresentationData, TelegramSearchPeersScope, String?)
|
||||||
@ -454,7 +455,9 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
return .localPeerId(peer.id)
|
return .localPeerId(peer.id)
|
||||||
case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _, _):
|
case let .localPeer(peer, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
return .localPeerId(peer.id)
|
return .localPeerId(peer.id)
|
||||||
case let .globalPeer(peer, _, _, _, _, _, _, _, _, _, _, _):
|
case let .adPeer(peer, _, _, _, _, _, _, _):
|
||||||
|
return .globalPeerId(peer.peer.id)
|
||||||
|
case let .globalPeer(peer, _, _, _, _, _, _, _, _, _, _):
|
||||||
return .globalPeerId(peer.peer.id)
|
return .globalPeerId(peer.peer.id)
|
||||||
case let .message(message, _, _, _, _, _, _, _, _, _, section, _, _, _, _):
|
case let .message(message, _, _, _, _, _, _, _, _, _, section, _, _, _, _):
|
||||||
return .messageId(message.id, section)
|
return .messageId(message.id, section)
|
||||||
@ -487,8 +490,14 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .globalPeer(lhsPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats, lhsRequiresPremiumForMessaging, lhsQuery, lhsIsAd):
|
case let .adPeer(lhsPeer, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsQuery):
|
||||||
if case let .globalPeer(rhsPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats, rhsRequiresPremiumForMessaging, rhsQuery, rhsIsAd) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging, lhsQuery == rhsQuery, lhsIsAd == rhsIsAd {
|
if case let .adPeer(rhsPeer, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsQuery) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsExpandType == rhsExpandType && lhsQuery == rhsQuery {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case let .globalPeer(lhsPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType, lhsStoryStats, lhsRequiresPremiumForMessaging, lhsQuery):
|
||||||
|
if case let .globalPeer(rhsPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType, rhsStoryStats, rhsRequiresPremiumForMessaging, rhsQuery) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType && lhsStoryStats == rhsStoryStats && lhsRequiresPremiumForMessaging == rhsRequiresPremiumForMessaging, lhsQuery == rhsQuery {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -620,14 +629,23 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
return false
|
return false
|
||||||
case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _, _, _, _):
|
case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _, _, _, _):
|
||||||
return lhsIndex <= rhsIndex
|
return lhsIndex <= rhsIndex
|
||||||
case .globalPeer, .message, .messagePlaceholder, .emptyMessagesFooter, .addContact:
|
case .adPeer, .globalPeer, .message, .messagePlaceholder, .emptyMessagesFooter, .addContact:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case let .globalPeer(_, _, lhsIndex, _, _, _, _, _, _, _, _, _):
|
case let .adPeer(_, lhsIndex, _, _, _, _, _, _):
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case .topic, .recentlySearchedPeer, .localPeer:
|
case .topic, .recentlySearchedPeer, .localPeer:
|
||||||
return false
|
return false
|
||||||
case let .globalPeer(_, _, rhsIndex, _, _, _, _, _, _, _, _, _):
|
case let .adPeer(_, rhsIndex, _, _, _, _, _, _):
|
||||||
|
return lhsIndex <= rhsIndex
|
||||||
|
case .globalPeer, .message, .messagePlaceholder, .emptyMessagesFooter, .addContact:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case let .globalPeer(_, _, lhsIndex, _, _, _, _, _, _, _, _):
|
||||||
|
switch rhs {
|
||||||
|
case .topic, .recentlySearchedPeer, .localPeer, .adPeer:
|
||||||
|
return false
|
||||||
|
case let .globalPeer(_, _, rhsIndex, _, _, _, _, _, _, _, _):
|
||||||
return lhsIndex <= rhsIndex
|
return lhsIndex <= rhsIndex
|
||||||
case .message, .messagePlaceholder, .emptyMessagesFooter, .addContact:
|
case .message, .messagePlaceholder, .emptyMessagesFooter, .addContact:
|
||||||
return true
|
return true
|
||||||
@ -808,6 +826,51 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
openStories(peer.id, sourceNode.avatarNode)
|
openStories(peer.id, sourceNode.avatarNode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
case let .adPeer(peer, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, _):
|
||||||
|
let enabled = true
|
||||||
|
var suffixString = ""
|
||||||
|
if let subscribers = peer.subscribers, subscribers != 0 {
|
||||||
|
if case .user = peer.peer {
|
||||||
|
suffixString = ", \(strings.Conversation_StatusBotSubscribers(subscribers))"
|
||||||
|
} else if case let .channel(channel) = peer.peer, case .broadcast = channel.info {
|
||||||
|
suffixString = ", \(strings.Conversation_StatusSubscribers(subscribers))"
|
||||||
|
} else {
|
||||||
|
suffixString = ", \(strings.Conversation_StatusMembers(subscribers))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let header: ChatListSearchItemHeader?
|
||||||
|
let actionTitle: String?
|
||||||
|
switch expandType {
|
||||||
|
case .none:
|
||||||
|
actionTitle = nil
|
||||||
|
case .expand:
|
||||||
|
actionTitle = strings.ChatList_Search_ShowMore
|
||||||
|
case .collapse:
|
||||||
|
actionTitle = strings.ChatList_Search_ShowLess
|
||||||
|
}
|
||||||
|
header = ChatListSearchItemHeader(type: .globalPeers, theme: theme, strings: strings, actionTitle: actionTitle, action: actionTitle == nil ? nil : { _ in
|
||||||
|
toggleExpandGlobalResults()
|
||||||
|
})
|
||||||
|
|
||||||
|
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: false), peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: nil, requiresPremiumForMessaging: false, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: nil, isAd: true, action: { _ in
|
||||||
|
interaction.peerSelected(peer.peer, nil, nil, nil, false)
|
||||||
|
}, disabledAction: { _ in
|
||||||
|
interaction.disabledPeerSelected(peer.peer, nil, .generic)
|
||||||
|
}, contextAction: peerContextAction.flatMap { peerContextAction in
|
||||||
|
return { node, gesture, location in
|
||||||
|
peerContextAction(peer.peer, .search(nil), node, gesture, location)
|
||||||
|
}
|
||||||
|
}, animationCache: interaction.animationCache, animationRenderer: interaction.animationRenderer, storyStats: nil, openStories: { itemPeer, sourceNode in
|
||||||
|
guard case let .peer(_, chatPeer) = itemPeer, let peer = chatPeer else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let sourceNode = sourceNode as? ContactsPeerItemNode {
|
||||||
|
openStories(peer.id, sourceNode.avatarNode)
|
||||||
|
}
|
||||||
|
}, adButtonAction: { node in
|
||||||
|
interaction.openAdInfo(node, peer)
|
||||||
|
})
|
||||||
case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging, isSelf):
|
case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging, isSelf):
|
||||||
let primaryPeer: EnginePeer
|
let primaryPeer: EnginePeer
|
||||||
var chatPeer: EnginePeer?
|
var chatPeer: EnginePeer?
|
||||||
@ -942,7 +1005,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
openStories(peer.id, sourceNode.avatarNode)
|
openStories(peer.id, sourceNode.avatarNode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
case let .globalPeer(peer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging, query, isAd):
|
case let .globalPeer(peer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType, storyStats, requiresPremiumForMessaging, query):
|
||||||
var enabled = true
|
var enabled = true
|
||||||
if filter.contains(.onlyWriteable) {
|
if filter.contains(.onlyWriteable) {
|
||||||
enabled = canSendMessagesToPeer(peer.peer)
|
enabled = canSendMessagesToPeer(peer.peer)
|
||||||
@ -1002,7 +1065,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
isSavedMessages = true
|
isSavedMessages = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: EnginePeer(peer.peer), chatPeer: EnginePeer(peer.peer)), status: .addressName(suffixString), badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: query, isAd: isAd, action: { _ in
|
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch(isSavedMessages: isSavedMessages), peer: .peer(peer: EnginePeer(peer.peer), chatPeer: EnginePeer(peer.peer)), status: .addressName(suffixString), badge: badge, requiresPremiumForMessaging: requiresPremiumForMessaging, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, searchQuery: query, isAd: false, action: { _ in
|
||||||
interaction.peerSelected(EnginePeer(peer.peer), nil, nil, nil, false)
|
interaction.peerSelected(EnginePeer(peer.peer), nil, nil, nil, false)
|
||||||
}, disabledAction: { _ in
|
}, disabledAction: { _ in
|
||||||
interaction.disabledPeerSelected(EnginePeer(peer.peer), nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
interaction.disabledPeerSelected(EnginePeer(peer.peer), nil, requiresPremiumForMessaging ? .premiumRequired : .generic)
|
||||||
@ -1019,8 +1082,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
if let sourceNode = sourceNode as? ContactsPeerItemNode {
|
if let sourceNode = sourceNode as? ContactsPeerItemNode {
|
||||||
openStories(peer.id, sourceNode.avatarNode)
|
openStories(peer.id, sourceNode.avatarNode)
|
||||||
}
|
}
|
||||||
}, adButtonAction: { node in
|
}, adButtonAction: { _ in
|
||||||
interaction.openAdInfo(node)
|
|
||||||
})
|
})
|
||||||
case let .message(message, peer, readState, threadInfo, presentationData, _, selected, displayCustomHeader, orderingKey, _, section, allPaused, storyStats, requiresPremiumForMessaging, searchScope):
|
case let .message(message, peer, readState, threadInfo, presentationData, _, selected, displayCustomHeader, orderingKey, _, section, allPaused, storyStats, requiresPremiumForMessaging, searchScope):
|
||||||
let header: ChatListSearchItemHeader
|
let header: ChatListSearchItemHeader
|
||||||
@ -1791,7 +1853,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
self.mediaNode.isHidden = true
|
self.mediaNode.isHidden = true
|
||||||
self.recentListNode.isHidden = peersFilter.contains(.excludeRecent)
|
self.recentListNode.isHidden = peersFilter.contains(.excludeRecent)
|
||||||
|
|
||||||
let currentRemotePeers = Atomic<([FoundPeer], [FoundPeer])?>(value: nil)
|
let currentRemotePeers = Atomic<([FoundPeer], [FoundPeer], [AdPeer])?>(value: nil)
|
||||||
let presentationDataPromise = self.presentationDataPromise
|
let presentationDataPromise = self.presentationDataPromise
|
||||||
let searchStatePromise = self.searchStatePromise
|
let searchStatePromise = self.searchStatePromise
|
||||||
let selectionPromise = self.selectedMessagesPromise
|
let selectionPromise = self.selectedMessagesPromise
|
||||||
@ -2351,35 +2413,40 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
let _ = previousRecentlySearchedPeersState.swap(nil)
|
let _ = previousRecentlySearchedPeersState.swap(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
let foundRemotePeers: Signal<([FoundPeer], [FoundPeer], Bool), NoError>
|
let foundRemotePeers: Signal<([FoundPeer], [FoundPeer], [AdPeer], Bool), NoError>
|
||||||
let currentRemotePeersValue: ([FoundPeer], [FoundPeer]) = currentRemotePeers.with { $0 } ?? ([], [])
|
let currentRemotePeersValue: ([FoundPeer], [FoundPeer], [AdPeer]) = currentRemotePeers.with { $0 } ?? ([], [], [])
|
||||||
if case .savedMessagesChats = location {
|
if case .savedMessagesChats = location {
|
||||||
foundRemotePeers = .single(([], [], false))
|
foundRemotePeers = .single(([], [], [], false))
|
||||||
} else if let query = query, case .chats = key {
|
} else if let query = query, case .chats = key {
|
||||||
if query.hasPrefix("#") {
|
if query.hasPrefix("#") {
|
||||||
foundRemotePeers = .single(([], [], false))
|
foundRemotePeers = .single(([], [], [], false))
|
||||||
} else {
|
} else {
|
||||||
foundRemotePeers = (
|
foundRemotePeers = (
|
||||||
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, true))
|
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, currentRemotePeersValue.2, true))
|
||||||
|> then(
|
|> then(
|
||||||
globalPeerSearchContext.searchRemotePeers(engine: context.engine, query: query)
|
globalPeerSearchContext.searchRemotePeers(engine: context.engine, query: query)
|
||||||
|> map { ($0.0, $0.1, false) }
|
|> mapToSignal { result in
|
||||||
|
return context.engine.peers.searchAdPeers(query: query)
|
||||||
|
|> map { adPeers in
|
||||||
|
return (result.0, result.1, adPeers, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if let query = query, case .channels = key {
|
} else if let query = query, case .channels = key {
|
||||||
foundRemotePeers = (
|
foundRemotePeers = (
|
||||||
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, true))
|
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, currentRemotePeersValue.2, true))
|
||||||
|> then(
|
|> then(
|
||||||
globalPeerSearchContext.searchRemotePeers(engine: context.engine, query: query, scope: .channels)
|
globalPeerSearchContext.searchRemotePeers(engine: context.engine, query: query, scope: .channels)
|
||||||
|> map { ($0.0, $0.1, false) }
|
|> map { ($0.0, $0.1, [], false) }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else if let query, case .apps = key {
|
} else if let query, case .apps = key {
|
||||||
let _ = query
|
let _ = query
|
||||||
foundRemotePeers = .single(([], [], false))
|
foundRemotePeers = .single(([], [], [], false))
|
||||||
} else {
|
} else {
|
||||||
foundRemotePeers = .single(([], [], false))
|
foundRemotePeers = .single(([], [], [], false))
|
||||||
}
|
}
|
||||||
let searchLocations: [SearchMessagesLocation]
|
let searchLocations: [SearchMessagesLocation]
|
||||||
if let options = options {
|
if let options = options {
|
||||||
@ -2661,7 +2728,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
foundThreads
|
foundThreads
|
||||||
)
|
)
|
||||||
|> map { accountPeer, foundLocalPeers, foundRemotePeers, foundRemoteMessages, foundPublicMessages, presentationData, searchState, selectionState, resolvedMessage, recentPeers, allAndFoundThreads -> ([ChatListSearchEntry], Bool)? in
|
|> map { accountPeer, foundLocalPeers, foundRemotePeers, foundRemoteMessages, foundPublicMessages, presentationData, searchState, selectionState, resolvedMessage, recentPeers, allAndFoundThreads -> ([ChatListSearchEntry], Bool)? in
|
||||||
let isSearching = foundRemotePeers.2 || foundRemoteMessages.1 || foundPublicMessages.1
|
let isSearching = foundRemotePeers.3 || foundRemoteMessages.1 || foundPublicMessages.1
|
||||||
var entries: [ChatListSearchEntry] = []
|
var entries: [ChatListSearchEntry] = []
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|
||||||
@ -2677,7 +2744,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
recentPeers = []
|
recentPeers = []
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = currentRemotePeers.swap((foundRemotePeers.0, foundRemotePeers.1))
|
let _ = currentRemotePeers.swap((foundRemotePeers.0, foundRemotePeers.1, foundRemotePeers.2))
|
||||||
|
|
||||||
let filteredPeer: (EnginePeer, EnginePeer) -> Bool = { peer, accountPeer in
|
let filteredPeer: (EnginePeer, EnginePeer) -> Bool = { peer, accountPeer in
|
||||||
if let requestPeerType {
|
if let requestPeerType {
|
||||||
@ -2882,7 +2949,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if peersFilter.contains(.includeSelf) {
|
if peersFilter.contains(.includeSelf) {
|
||||||
for renderedPeer in foundLocalPeers.peers {
|
for renderedPeer in foundLocalPeers.peers {
|
||||||
if renderedPeer.peerId == context.account.peerId, let peer = renderedPeer.peers[renderedPeer.peerId], filteredPeer(peer, EnginePeer(accountPeer)) {
|
if renderedPeer.peerId == context.account.peerId, let peer = renderedPeer.peers[renderedPeer.peerId], filteredPeer(peer, EnginePeer(accountPeer)) {
|
||||||
@ -2962,7 +3029,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for peer in foundRemotePeers.0 {
|
for peer in foundRemotePeers.0 {
|
||||||
if case .expand = localExpandType, numberOfLocalPeers >= 3 {
|
if case .expand = localExpandType, numberOfLocalPeers >= 3 {
|
||||||
break
|
break
|
||||||
@ -2978,6 +3045,14 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
|
|
||||||
var numberOfGlobalPeers = 0
|
var numberOfGlobalPeers = 0
|
||||||
index = 0
|
index = 0
|
||||||
|
for peer in foundRemotePeers.2 {
|
||||||
|
if !existingPeerIds.contains(peer.peer.id) {
|
||||||
|
existingPeerIds.insert(peer.peer.id)
|
||||||
|
entries.append(.adPeer(peer, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalExpandType, finalQuery))
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let _ = tagMask {
|
if let _ = tagMask {
|
||||||
} else {
|
} else {
|
||||||
for peer in foundRemotePeers.1 {
|
for peer in foundRemotePeers.1 {
|
||||||
@ -2986,14 +3061,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !existingPeerIds.contains(peer.peer.id), filteredPeer(EnginePeer(peer.peer), EnginePeer(accountPeer)) {
|
if !existingPeerIds.contains(peer.peer.id), filteredPeer(EnginePeer(peer.peer), EnginePeer(accountPeer)) {
|
||||||
//TODO:unmock
|
|
||||||
var isAd = !"".isEmpty
|
|
||||||
#if DEBUG
|
|
||||||
isAd = numberOfGlobalPeers == 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
existingPeerIds.insert(peer.peer.id)
|
existingPeerIds.insert(peer.peer.id)
|
||||||
entries.append(.globalPeer(peer, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalExpandType, nil, false, finalQuery, isAd))
|
entries.append(.globalPeer(peer, nil, index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, globalExpandType, nil, false, finalQuery))
|
||||||
index += 1
|
index += 1
|
||||||
numberOfGlobalPeers += 1
|
numberOfGlobalPeers += 1
|
||||||
}
|
}
|
||||||
@ -3013,7 +3082,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var firstHeaderId: Int64?
|
var firstHeaderId: Int64?
|
||||||
if !foundRemotePeers.2 {
|
if !foundRemotePeers.3 {
|
||||||
index = 0
|
index = 0
|
||||||
var existingPostIds = Set<MessageId>()
|
var existingPostIds = Set<MessageId>()
|
||||||
for foundPublicMessageSet in foundPublicMessages.0 {
|
for foundPublicMessageSet in foundPublicMessages.0 {
|
||||||
@ -3279,8 +3348,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { node in
|
}, openAdInfo: { node, adPeer in
|
||||||
interaction.openAdInfo(node)
|
interaction.openAdInfo(node, adPeer)
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
chatListInteraction.isSearchMode = true
|
chatListInteraction.isSearchMode = true
|
||||||
@ -3410,7 +3479,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
if case let .user(user) = peer, user.flags.contains(.requirePremium) {
|
if case let .user(user) = peer, user.flags.contains(.requirePremium) {
|
||||||
requiresPremiumForMessagingPeerIds.append(peer.id)
|
requiresPremiumForMessagingPeerIds.append(peer.id)
|
||||||
}
|
}
|
||||||
case let .globalPeer(foundPeer, _, _, _, _, _, _, _, _, _, _, _):
|
case let .globalPeer(foundPeer, _, _, _, _, _, _, _, _, _, _):
|
||||||
storyStatsIds.append(foundPeer.peer.id)
|
storyStatsIds.append(foundPeer.peer.id)
|
||||||
if let user = foundPeer.peer as? TelegramUser, user.flags.contains(.requirePremium) {
|
if let user = foundPeer.peer as? TelegramUser, user.flags.contains(.requirePremium) {
|
||||||
requiresPremiumForMessagingPeerIds.append(foundPeer.peer.id)
|
requiresPremiumForMessagingPeerIds.append(foundPeer.peer.id)
|
||||||
@ -3451,8 +3520,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
mappedItems[i] = .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false)
|
mappedItems[i] = .recentlySearchedPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false)
|
||||||
case let .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _, isSelf):
|
case let .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _, isSelf):
|
||||||
mappedItems[i] = .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false, isSelf)
|
mappedItems[i] = .localPeer(peer, associatedPeer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.id] ?? nil, requiresPremiumForMessaging[peer.id] ?? false, isSelf)
|
||||||
case let .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _, searchQuery, isAd):
|
case let .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, _, _, searchQuery):
|
||||||
mappedItems[i] = .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.peer.id] ?? nil, requiresPremiumForMessaging[peer.peer.id] ?? false, searchQuery, isAd)
|
mappedItems[i] = .globalPeer(peer, unreadBadge, index, theme, strings, sortOrder, displayOrder, expandType, stats[peer.peer.id] ?? nil, requiresPremiumForMessaging[peer.peer.id] ?? false, searchQuery)
|
||||||
case let .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, _, _, searchScope):
|
case let .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, _, _, searchScope):
|
||||||
mappedItems[i] = .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, stats[peer.peerId] ?? nil, requiresPremiumForMessaging[peer.peerId] ?? false, searchScope)
|
mappedItems[i] = .message(message, peer, combinedPeerReadState, threadInfo, presentationData, totalCount, selected, displayCustomHeader, key, resourceId, section, allPaused, stats[peer.peerId] ?? nil, requiresPremiumForMessaging[peer.peerId] ?? false, searchScope)
|
||||||
default:
|
default:
|
||||||
@ -5263,7 +5332,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
var isInlineMode = false
|
var isInlineMode = false
|
||||||
|
@ -161,7 +161,7 @@ public final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
interaction.isInlineMode = isInlineMode
|
interaction.isInlineMode = isInlineMode
|
||||||
|
@ -114,7 +114,7 @@ public final class ChatListNodeInteraction {
|
|||||||
let editPeer: (ChatListItem) -> Void
|
let editPeer: (ChatListItem) -> Void
|
||||||
let openWebApp: (TelegramUser) -> Void
|
let openWebApp: (TelegramUser) -> Void
|
||||||
let openPhotoSetup: () -> Void
|
let openPhotoSetup: () -> Void
|
||||||
let openAdInfo: (ASDisplayNode) -> Void
|
let openAdInfo: (ASDisplayNode, AdPeer) -> Void
|
||||||
let openAccountFreezeInfo: () -> Void
|
let openAccountFreezeInfo: () -> Void
|
||||||
|
|
||||||
public var searchTextHighightState: String?
|
public var searchTextHighightState: String?
|
||||||
@ -174,7 +174,7 @@ public final class ChatListNodeInteraction {
|
|||||||
editPeer: @escaping (ChatListItem) -> Void,
|
editPeer: @escaping (ChatListItem) -> Void,
|
||||||
openWebApp: @escaping (TelegramUser) -> Void,
|
openWebApp: @escaping (TelegramUser) -> Void,
|
||||||
openPhotoSetup: @escaping () -> Void,
|
openPhotoSetup: @escaping () -> Void,
|
||||||
openAdInfo: @escaping (ASDisplayNode) -> Void,
|
openAdInfo: @escaping (ASDisplayNode, AdPeer) -> Void,
|
||||||
openAccountFreezeInfo: @escaping () -> Void
|
openAccountFreezeInfo: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.activateSearch = activateSearch
|
self.activateSearch = activateSearch
|
||||||
@ -1245,7 +1245,7 @@ public final class ChatListNode: ListView {
|
|||||||
public var openStarsTopup: ((Int64?) -> Void)?
|
public var openStarsTopup: ((Int64?) -> Void)?
|
||||||
public var openWebApp: ((TelegramUser) -> Void)?
|
public var openWebApp: ((TelegramUser) -> Void)?
|
||||||
public var openPhotoSetup: (() -> Void)?
|
public var openPhotoSetup: (() -> Void)?
|
||||||
public var openAdInfo: ((ASDisplayNode) -> Void)?
|
public var openAdInfo: ((ASDisplayNode, AdPeer) -> Void)?
|
||||||
public var openAccountFreezeInfo: (() -> Void)?
|
public var openAccountFreezeInfo: (() -> Void)?
|
||||||
|
|
||||||
private var theme: PresentationTheme
|
private var theme: PresentationTheme
|
||||||
@ -1905,8 +1905,8 @@ public final class ChatListNode: ListView {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.openPhotoSetup?()
|
self.openPhotoSetup?()
|
||||||
}, openAdInfo: { [weak self] node in
|
}, openAdInfo: { [weak self] node, adPeer in
|
||||||
self?.openAdInfo?(node)
|
self?.openAdInfo?(node, adPeer)
|
||||||
}, openAccountFreezeInfo: { [weak self] in
|
}, openAccountFreezeInfo: { [weak self] in
|
||||||
self?.openAccountFreezeInfo?()
|
self?.openAccountFreezeInfo?()
|
||||||
})
|
})
|
||||||
|
@ -569,14 +569,13 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}, iconSource: nil, action: { [weak self] _, f in
|
}, iconSource: nil, action: { [weak self] _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|
let _ = (context.engine.messages.reportAdMessage(opaqueId: adAttribute.opaqueId, option: nil)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||||
if case let .options(title, options) = result {
|
if case let .options(title, options) = result {
|
||||||
if let navigationController = self?.baseNavigationController() as? NavigationController {
|
if let navigationController = self?.baseNavigationController() as? NavigationController {
|
||||||
navigationController.pushViewController(
|
navigationController.pushViewController(
|
||||||
AdsReportScreen(
|
AdsReportScreen(
|
||||||
context: context,
|
context: context,
|
||||||
peerId: message.id.peerId,
|
|
||||||
opaqueId: adAttribute.opaqueId,
|
opaqueId: adAttribute.opaqueId,
|
||||||
title: title,
|
title: title,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -3131,14 +3131,13 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
|||||||
}, iconSource: nil, action: { [weak self] _, f in
|
}, iconSource: nil, action: { [weak self] _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|
let _ = (context.engine.messages.reportAdMessage(opaqueId: adAttribute.opaqueId, option: nil)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||||
if case let .options(title, options) = result {
|
if case let .options(title, options) = result {
|
||||||
if let navigationController = self?.baseNavigationController() as? NavigationController {
|
if let navigationController = self?.baseNavigationController() as? NavigationController {
|
||||||
navigationController.pushViewController(
|
navigationController.pushViewController(
|
||||||
AdsReportScreen(
|
AdsReportScreen(
|
||||||
context: context,
|
context: context,
|
||||||
peerId: message.id.peerId,
|
|
||||||
opaqueId: adAttribute.opaqueId,
|
opaqueId: adAttribute.opaqueId,
|
||||||
title: title,
|
title: title,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -174,8 +174,9 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
|||||||
case disallowedGiftsUnlimited(PresentationTheme, String, Bool, Bool)
|
case disallowedGiftsUnlimited(PresentationTheme, String, Bool, Bool)
|
||||||
case disallowedGiftsLimited(PresentationTheme, String, Bool, Bool)
|
case disallowedGiftsLimited(PresentationTheme, String, Bool, Bool)
|
||||||
case disallowedGiftsUnique(PresentationTheme, String, Bool, Bool)
|
case disallowedGiftsUnique(PresentationTheme, String, Bool, Bool)
|
||||||
|
case disallowedGiftsPremium(PresentationTheme, String, Bool, Bool)
|
||||||
case disallowedGiftsInfo(PresentationTheme, String)
|
case disallowedGiftsInfo(PresentationTheme, String)
|
||||||
case showGiftButton(PresentationTheme, String, Bool, Bool)
|
case showGiftButton(PresentationTheme, String, Bool, Bool, Bool)
|
||||||
case showGiftButtonInfo(PresentationTheme, String)
|
case showGiftButtonInfo(PresentationTheme, String)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
@ -202,7 +203,7 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
|||||||
return SelectivePrivacySettingsSection.hideReadTime.rawValue
|
return SelectivePrivacySettingsSection.hideReadTime.rawValue
|
||||||
case .subscribeToPremium, .subscribeToPremiumInfo:
|
case .subscribeToPremium, .subscribeToPremiumInfo:
|
||||||
return SelectivePrivacySettingsSection.premium.rawValue
|
return SelectivePrivacySettingsSection.premium.rawValue
|
||||||
case .disallowedGiftsHeader, .disallowedGiftsUnlimited, .disallowedGiftsLimited, .disallowedGiftsUnique, .disallowedGiftsInfo:
|
case .disallowedGiftsHeader, .disallowedGiftsUnlimited, .disallowedGiftsLimited, .disallowedGiftsUnique, .disallowedGiftsPremium, .disallowedGiftsInfo:
|
||||||
return SelectivePrivacySettingsSection.disallowedGifts.rawValue
|
return SelectivePrivacySettingsSection.disallowedGifts.rawValue
|
||||||
case .showGiftButton, .showGiftButtonInfo:
|
case .showGiftButton, .showGiftButtonInfo:
|
||||||
return SelectivePrivacySettingsSection.giftButton.rawValue
|
return SelectivePrivacySettingsSection.giftButton.rawValue
|
||||||
@ -285,12 +286,14 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
|||||||
return 35
|
return 35
|
||||||
case .disallowedGiftsUnique:
|
case .disallowedGiftsUnique:
|
||||||
return 36
|
return 36
|
||||||
case .disallowedGiftsInfo:
|
case .disallowedGiftsPremium:
|
||||||
return 37
|
return 37
|
||||||
case .showGiftButton:
|
case .disallowedGiftsInfo:
|
||||||
return 38
|
return 38
|
||||||
case .showGiftButtonInfo:
|
case .showGiftButton:
|
||||||
return 39
|
return 39
|
||||||
|
case .showGiftButtonInfo:
|
||||||
|
return 40
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,14 +521,20 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case let .disallowedGiftsPremium(lhsTheme, lhsText, lhsEnabled, lhsValue):
|
||||||
|
if case let .disallowedGiftsPremium(rhsTheme, rhsText, rhsEnabled, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled, lhsValue == rhsValue {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
case let .disallowedGiftsInfo(lhsTheme, lhsText):
|
case let .disallowedGiftsInfo(lhsTheme, lhsText):
|
||||||
if case let .disallowedGiftsInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
if case let .disallowedGiftsInfo(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .showGiftButton(lhsTheme, lhsText, lhsEnabled, lhsValue):
|
case let .showGiftButton(lhsTheme, lhsText, lhsEnabled, lhsValue, lhsAvailable):
|
||||||
if case let .showGiftButton(rhsTheme, rhsText, rhsEnabled, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled, lhsValue == rhsValue {
|
if case let .showGiftButton(rhsTheme, rhsText, rhsEnabled, rhsValue, rhsAvailable) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsEnabled == rhsEnabled, lhsValue == rhsValue, lhsAvailable == rhsAvailable {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -696,18 +705,28 @@ private enum SelectivePrivacySettingsEntry: ItemListNodeEntry {
|
|||||||
}, activatedWhileDisabled: {
|
}, activatedWhileDisabled: {
|
||||||
arguments.displayLockedGiftsInfo()
|
arguments.displayLockedGiftsInfo()
|
||||||
})
|
})
|
||||||
case let .disallowedGiftsInfo(_, text):
|
case let .disallowedGiftsPremium(_, text, isLocked, value):
|
||||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
|
||||||
case let .showGiftButton(_, text, isLocked, value):
|
|
||||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: !isLocked, enabled: true, displayLocked: isLocked, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: !isLocked, enabled: true, displayLocked: isLocked, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
||||||
if !isLocked {
|
if !isLocked {
|
||||||
arguments.updateShowGiftButton?(updatedValue)
|
arguments.updateDisallowedGifts?(.premium, !updatedValue)
|
||||||
} else {
|
} else {
|
||||||
arguments.displayLockedGiftsInfo()
|
arguments.displayLockedGiftsInfo()
|
||||||
}
|
}
|
||||||
}, activatedWhileDisabled: {
|
}, activatedWhileDisabled: {
|
||||||
arguments.displayLockedGiftsInfo()
|
arguments.displayLockedGiftsInfo()
|
||||||
})
|
})
|
||||||
|
case let .disallowedGiftsInfo(_, text):
|
||||||
|
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||||
|
case let .showGiftButton(_, text, isLocked, value, available):
|
||||||
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: !isLocked, enabled: available, displayLocked: isLocked, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
||||||
|
if !isLocked {
|
||||||
|
arguments.updateShowGiftButton?(updatedValue)
|
||||||
|
} else if available {
|
||||||
|
arguments.displayLockedGiftsInfo()
|
||||||
|
}
|
||||||
|
}, activatedWhileDisabled: {
|
||||||
|
arguments.displayLockedGiftsInfo()
|
||||||
|
})
|
||||||
case let .showGiftButtonInfo(_, text):
|
case let .showGiftButtonInfo(_, text):
|
||||||
let attributedString = NSMutableAttributedString(string: text, font: Font.regular(presentationData.fontSize.itemListBaseHeaderFontSize), textColor: presentationData.theme.list.freeTextColor)
|
let attributedString = NSMutableAttributedString(string: text, font: Font.regular(presentationData.fontSize.itemListBaseHeaderFontSize), textColor: presentationData.theme.list.freeTextColor)
|
||||||
if let range = attributedString.string.range(of: "#") {
|
if let range = attributedString.string.range(of: "#") {
|
||||||
@ -1125,8 +1144,9 @@ private func selectivePrivacySettingsControllerEntries(presentationData: Present
|
|||||||
entries.append(.disallowedGiftsUnlimited(presentationData.theme, "Unlimited", !isPremium, !(state.disallowedGifts?.contains(.unlimited) ?? false)))
|
entries.append(.disallowedGiftsUnlimited(presentationData.theme, "Unlimited", !isPremium, !(state.disallowedGifts?.contains(.unlimited) ?? false)))
|
||||||
entries.append(.disallowedGiftsLimited(presentationData.theme, "Limited-Edition", !isPremium, !(state.disallowedGifts?.contains(.limited) ?? false)))
|
entries.append(.disallowedGiftsLimited(presentationData.theme, "Limited-Edition", !isPremium, !(state.disallowedGifts?.contains(.limited) ?? false)))
|
||||||
entries.append(.disallowedGiftsUnique(presentationData.theme, "Unique", !isPremium, !(state.disallowedGifts?.contains(.unique) ?? false)))
|
entries.append(.disallowedGiftsUnique(presentationData.theme, "Unique", !isPremium, !(state.disallowedGifts?.contains(.unique) ?? false)))
|
||||||
|
entries.append(.disallowedGiftsPremium(presentationData.theme, "Premium Subscriptions", !isPremium, !(state.disallowedGifts?.contains(.premium) ?? false)))
|
||||||
entries.append(.disallowedGiftsInfo(presentationData.theme, "Choose the types of gifts that you allow others to send you."))
|
entries.append(.disallowedGiftsInfo(presentationData.theme, "Choose the types of gifts that you allow others to send you."))
|
||||||
entries.append(.showGiftButton(presentationData.theme, "Show Gift Icon in Chats", !isPremium, state.showGiftButton == true))
|
entries.append(.showGiftButton(presentationData.theme, "Show Gift Icon in Chats", !isPremium, state.showGiftButton == true && state.disallowedGifts != TelegramDisallowedGifts.All, state.disallowedGifts != TelegramDisallowedGifts.All))
|
||||||
entries.append(.showGiftButtonInfo(presentationData.theme, "Display the # Gift icon in the message input field for both participants in all chats."))
|
entries.append(.showGiftButtonInfo(presentationData.theme, "Display the # Gift icon in the message input field for both participants in all chats."))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1603,6 +1623,12 @@ public func selectivePrivacySettingsController(
|
|||||||
} else {
|
} else {
|
||||||
updatedDisallowedGifts.remove(.unique)
|
updatedDisallowedGifts.remove(.unique)
|
||||||
}
|
}
|
||||||
|
case .premium:
|
||||||
|
if value {
|
||||||
|
updatedDisallowedGifts.insert(.premium)
|
||||||
|
} else {
|
||||||
|
updatedDisallowedGifts.remove(.premium)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -1713,7 +1739,11 @@ public func selectivePrivacySettingsController(
|
|||||||
disallowedGifts = value
|
disallowedGifts = value
|
||||||
}
|
}
|
||||||
if let value = state.showGiftButton {
|
if let value = state.showGiftButton {
|
||||||
showGiftButton = value
|
if disallowedGifts != TelegramDisallowedGifts.All {
|
||||||
|
showGiftButton = value
|
||||||
|
} else {
|
||||||
|
showGiftButton = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -381,7 +381,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -241,7 +241,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[2004110666] = { return Api.DialogFilterSuggested.parse_dialogFilterSuggested($0) }
|
dict[2004110666] = { return Api.DialogFilterSuggested.parse_dialogFilterSuggested($0) }
|
||||||
dict[-445792507] = { return Api.DialogPeer.parse_dialogPeer($0) }
|
dict[-445792507] = { return Api.DialogPeer.parse_dialogPeer($0) }
|
||||||
dict[1363483106] = { return Api.DialogPeer.parse_dialogPeerFolder($0) }
|
dict[1363483106] = { return Api.DialogPeer.parse_dialogPeerFolder($0) }
|
||||||
dict[1653721450] = { return Api.DisallowedStarGiftsSettings.parse_disallowedStarGiftsSettings($0) }
|
dict[1911715524] = { return Api.DisallowedGiftsSettings.parse_disallowedGiftsSettings($0) }
|
||||||
dict[-1881881384] = { return Api.Document.parse_document($0) }
|
dict[-1881881384] = { return Api.Document.parse_document($0) }
|
||||||
dict[922273905] = { return Api.Document.parse_documentEmpty($0) }
|
dict[922273905] = { return Api.Document.parse_documentEmpty($0) }
|
||||||
dict[297109817] = { return Api.DocumentAttribute.parse_documentAttributeAnimated($0) }
|
dict[297109817] = { return Api.DocumentAttribute.parse_documentAttributeAnimated($0) }
|
||||||
@ -300,7 +300,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1297942941] = { return Api.GeoPoint.parse_geoPoint($0) }
|
dict[-1297942941] = { return Api.GeoPoint.parse_geoPoint($0) }
|
||||||
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
dict[286776671] = { return Api.GeoPoint.parse_geoPointEmpty($0) }
|
||||||
dict[-565420653] = { return Api.GeoPointAddress.parse_geoPointAddress($0) }
|
dict[-565420653] = { return Api.GeoPointAddress.parse_geoPointAddress($0) }
|
||||||
dict[-715184062] = { return Api.GlobalPrivacySettings.parse_globalPrivacySettings($0) }
|
dict[-29248689] = { return Api.GlobalPrivacySettings.parse_globalPrivacySettings($0) }
|
||||||
dict[-839330845] = { return Api.GroupCall.parse_groupCall($0) }
|
dict[-839330845] = { return Api.GroupCall.parse_groupCall($0) }
|
||||||
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
|
dict[2004925620] = { return Api.GroupCall.parse_groupCallDiscarded($0) }
|
||||||
dict[-341428482] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
dict[-341428482] = { return Api.GroupCallParticipant.parse_groupCallParticipant($0) }
|
||||||
@ -1149,7 +1149,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
|
dict[-1831650802] = { return Api.UrlAuthResult.parse_urlAuthResultRequest($0) }
|
||||||
dict[34280482] = { return Api.User.parse_user($0) }
|
dict[34280482] = { return Api.User.parse_user($0) }
|
||||||
dict[-742634630] = { return Api.User.parse_userEmpty($0) }
|
dict[-742634630] = { return Api.User.parse_userEmpty($0) }
|
||||||
dict[791719153] = { return Api.UserFull.parse_userFull($0) }
|
dict[-1712881595] = { return Api.UserFull.parse_userFull($0) }
|
||||||
dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
dict[-2100168954] = { return Api.UserProfilePhoto.parse_userProfilePhoto($0) }
|
||||||
dict[1326562017] = { return Api.UserProfilePhoto.parse_userProfilePhotoEmpty($0) }
|
dict[1326562017] = { return Api.UserProfilePhoto.parse_userProfilePhotoEmpty($0) }
|
||||||
dict[164646985] = { return Api.UserStatus.parse_userStatusEmpty($0) }
|
dict[164646985] = { return Api.UserStatus.parse_userStatusEmpty($0) }
|
||||||
@ -1685,7 +1685,7 @@ public extension Api {
|
|||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.DialogPeer:
|
case let _1 as Api.DialogPeer:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.DisallowedStarGiftsSettings:
|
case let _1 as Api.DisallowedGiftsSettings:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
case let _1 as Api.Document:
|
case let _1 as Api.Document:
|
||||||
_1.serialize(buffer, boxed)
|
_1.serialize(buffer, boxed)
|
||||||
|
@ -614,13 +614,13 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum UserFull: TypeConstructorDescription {
|
enum UserFull: TypeConstructorDescription {
|
||||||
case userFull(flags: Int32, flags2: Int32, id: Int64, about: String?, settings: Api.PeerSettings, personalPhoto: Api.Photo?, profilePhoto: Api.Photo?, fallbackPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?, privateForwardName: String?, botGroupAdminRights: Api.ChatAdminRights?, botBroadcastAdminRights: Api.ChatAdminRights?, wallpaper: Api.WallPaper?, stories: Api.PeerStories?, businessWorkHours: Api.BusinessWorkHours?, businessLocation: Api.BusinessLocation?, businessGreetingMessage: Api.BusinessGreetingMessage?, businessAwayMessage: Api.BusinessAwayMessage?, businessIntro: Api.BusinessIntro?, birthday: Api.Birthday?, personalChannelId: Int64?, personalChannelMessage: Int32?, stargiftsCount: Int32?, starrefProgram: Api.StarRefProgram?, botVerification: Api.BotVerification?, sendPaidMessagesStars: Int64?, disallowedStargifts: Api.DisallowedStarGiftsSettings?)
|
case userFull(flags: Int32, flags2: Int32, id: Int64, about: String?, settings: Api.PeerSettings, personalPhoto: Api.Photo?, profilePhoto: Api.Photo?, fallbackPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?, ttlPeriod: Int32?, themeEmoticon: String?, privateForwardName: String?, botGroupAdminRights: Api.ChatAdminRights?, botBroadcastAdminRights: Api.ChatAdminRights?, wallpaper: Api.WallPaper?, stories: Api.PeerStories?, businessWorkHours: Api.BusinessWorkHours?, businessLocation: Api.BusinessLocation?, businessGreetingMessage: Api.BusinessGreetingMessage?, businessAwayMessage: Api.BusinessAwayMessage?, businessIntro: Api.BusinessIntro?, birthday: Api.Birthday?, personalChannelId: Int64?, personalChannelMessage: Int32?, stargiftsCount: Int32?, starrefProgram: Api.StarRefProgram?, botVerification: Api.BotVerification?, sendPaidMessagesStars: Int64?, disallowedGifts: Api.DisallowedGiftsSettings?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .userFull(let flags, let flags2, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let wallpaper, let stories, let businessWorkHours, let businessLocation, let businessGreetingMessage, let businessAwayMessage, let businessIntro, let birthday, let personalChannelId, let personalChannelMessage, let stargiftsCount, let starrefProgram, let botVerification, let sendPaidMessagesStars, let disallowedStargifts):
|
case .userFull(let flags, let flags2, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let wallpaper, let stories, let businessWorkHours, let businessLocation, let businessGreetingMessage, let businessAwayMessage, let businessIntro, let birthday, let personalChannelId, let personalChannelMessage, let stargiftsCount, let starrefProgram, let botVerification, let sendPaidMessagesStars, let disallowedGifts):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(791719153)
|
buffer.appendInt32(-1712881595)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
serializeInt32(flags2, buffer: buffer, boxed: false)
|
serializeInt32(flags2, buffer: buffer, boxed: false)
|
||||||
@ -654,15 +654,15 @@ public extension Api {
|
|||||||
if Int(flags2) & Int(1 << 11) != 0 {starrefProgram!.serialize(buffer, true)}
|
if Int(flags2) & Int(1 << 11) != 0 {starrefProgram!.serialize(buffer, true)}
|
||||||
if Int(flags2) & Int(1 << 12) != 0 {botVerification!.serialize(buffer, true)}
|
if Int(flags2) & Int(1 << 12) != 0 {botVerification!.serialize(buffer, true)}
|
||||||
if Int(flags2) & Int(1 << 14) != 0 {serializeInt64(sendPaidMessagesStars!, buffer: buffer, boxed: false)}
|
if Int(flags2) & Int(1 << 14) != 0 {serializeInt64(sendPaidMessagesStars!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags2) & Int(1 << 15) != 0 {disallowedStargifts!.serialize(buffer, true)}
|
if Int(flags2) & Int(1 << 15) != 0 {disallowedGifts!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .userFull(let flags, let flags2, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let wallpaper, let stories, let businessWorkHours, let businessLocation, let businessGreetingMessage, let businessAwayMessage, let businessIntro, let birthday, let personalChannelId, let personalChannelMessage, let stargiftsCount, let starrefProgram, let botVerification, let sendPaidMessagesStars, let disallowedStargifts):
|
case .userFull(let flags, let flags2, let id, let about, let settings, let personalPhoto, let profilePhoto, let fallbackPhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId, let ttlPeriod, let themeEmoticon, let privateForwardName, let botGroupAdminRights, let botBroadcastAdminRights, let wallpaper, let stories, let businessWorkHours, let businessLocation, let businessGreetingMessage, let businessAwayMessage, let businessIntro, let birthday, let personalChannelId, let personalChannelMessage, let stargiftsCount, let starrefProgram, let botVerification, let sendPaidMessagesStars, let disallowedGifts):
|
||||||
return ("userFull", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("about", about as Any), ("settings", settings as Any), ("personalPhoto", personalPhoto as Any), ("profilePhoto", profilePhoto as Any), ("fallbackPhoto", fallbackPhoto as Any), ("notifySettings", notifySettings as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("commonChatsCount", commonChatsCount as Any), ("folderId", folderId as Any), ("ttlPeriod", ttlPeriod as Any), ("themeEmoticon", themeEmoticon as Any), ("privateForwardName", privateForwardName as Any), ("botGroupAdminRights", botGroupAdminRights as Any), ("botBroadcastAdminRights", botBroadcastAdminRights as Any), ("wallpaper", wallpaper as Any), ("stories", stories as Any), ("businessWorkHours", businessWorkHours as Any), ("businessLocation", businessLocation as Any), ("businessGreetingMessage", businessGreetingMessage as Any), ("businessAwayMessage", businessAwayMessage as Any), ("businessIntro", businessIntro as Any), ("birthday", birthday as Any), ("personalChannelId", personalChannelId as Any), ("personalChannelMessage", personalChannelMessage as Any), ("stargiftsCount", stargiftsCount as Any), ("starrefProgram", starrefProgram as Any), ("botVerification", botVerification as Any), ("sendPaidMessagesStars", sendPaidMessagesStars as Any), ("disallowedStargifts", disallowedStargifts as Any)])
|
return ("userFull", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("about", about as Any), ("settings", settings as Any), ("personalPhoto", personalPhoto as Any), ("profilePhoto", profilePhoto as Any), ("fallbackPhoto", fallbackPhoto as Any), ("notifySettings", notifySettings as Any), ("botInfo", botInfo as Any), ("pinnedMsgId", pinnedMsgId as Any), ("commonChatsCount", commonChatsCount as Any), ("folderId", folderId as Any), ("ttlPeriod", ttlPeriod as Any), ("themeEmoticon", themeEmoticon as Any), ("privateForwardName", privateForwardName as Any), ("botGroupAdminRights", botGroupAdminRights as Any), ("botBroadcastAdminRights", botBroadcastAdminRights as Any), ("wallpaper", wallpaper as Any), ("stories", stories as Any), ("businessWorkHours", businessWorkHours as Any), ("businessLocation", businessLocation as Any), ("businessGreetingMessage", businessGreetingMessage as Any), ("businessAwayMessage", businessAwayMessage as Any), ("businessIntro", businessIntro as Any), ("birthday", birthday as Any), ("personalChannelId", personalChannelId as Any), ("personalChannelMessage", personalChannelMessage as Any), ("stargiftsCount", stargiftsCount as Any), ("starrefProgram", starrefProgram as Any), ("botVerification", botVerification as Any), ("sendPaidMessagesStars", sendPaidMessagesStars as Any), ("disallowedGifts", disallowedGifts as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,9 +767,9 @@ public extension Api {
|
|||||||
} }
|
} }
|
||||||
var _32: Int64?
|
var _32: Int64?
|
||||||
if Int(_2!) & Int(1 << 14) != 0 {_32 = reader.readInt64() }
|
if Int(_2!) & Int(1 << 14) != 0 {_32 = reader.readInt64() }
|
||||||
var _33: Api.DisallowedStarGiftsSettings?
|
var _33: Api.DisallowedGiftsSettings?
|
||||||
if Int(_2!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
|
if Int(_2!) & Int(1 << 15) != 0 {if let signature = reader.readInt32() {
|
||||||
_33 = Api.parse(reader, signature: signature) as? Api.DisallowedStarGiftsSettings
|
_33 = Api.parse(reader, signature: signature) as? Api.DisallowedGiftsSettings
|
||||||
} }
|
} }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
@ -805,7 +805,7 @@ public extension Api {
|
|||||||
let _c32 = (Int(_2!) & Int(1 << 14) == 0) || _32 != nil
|
let _c32 = (Int(_2!) & Int(1 << 14) == 0) || _32 != nil
|
||||||
let _c33 = (Int(_2!) & Int(1 << 15) == 0) || _33 != nil
|
let _c33 = (Int(_2!) & Int(1 << 15) == 0) || _33 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 {
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 {
|
||||||
return Api.UserFull.userFull(flags: _1!, flags2: _2!, id: _3!, about: _4, settings: _5!, personalPhoto: _6, profilePhoto: _7, fallbackPhoto: _8, notifySettings: _9!, botInfo: _10, pinnedMsgId: _11, commonChatsCount: _12!, folderId: _13, ttlPeriod: _14, themeEmoticon: _15, privateForwardName: _16, botGroupAdminRights: _17, botBroadcastAdminRights: _18, wallpaper: _19, stories: _20, businessWorkHours: _21, businessLocation: _22, businessGreetingMessage: _23, businessAwayMessage: _24, businessIntro: _25, birthday: _26, personalChannelId: _27, personalChannelMessage: _28, stargiftsCount: _29, starrefProgram: _30, botVerification: _31, sendPaidMessagesStars: _32, disallowedStargifts: _33)
|
return Api.UserFull.userFull(flags: _1!, flags2: _2!, id: _3!, about: _4, settings: _5!, personalPhoto: _6, profilePhoto: _7, fallbackPhoto: _8, notifySettings: _9!, botInfo: _10, pinnedMsgId: _11, commonChatsCount: _12!, folderId: _13, ttlPeriod: _14, themeEmoticon: _15, privateForwardName: _16, botGroupAdminRights: _17, botBroadcastAdminRights: _18, wallpaper: _19, stories: _20, businessWorkHours: _21, businessLocation: _22, businessGreetingMessage: _23, businessAwayMessage: _24, businessIntro: _25, birthday: _26, personalChannelId: _27, personalChannelMessage: _28, stargiftsCount: _29, starrefProgram: _30, botVerification: _31, sendPaidMessagesStars: _32, disallowedGifts: _33)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -1425,14 +1425,14 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum DisallowedStarGiftsSettings: TypeConstructorDescription {
|
enum DisallowedGiftsSettings: TypeConstructorDescription {
|
||||||
case disallowedStarGiftsSettings(flags: Int32)
|
case disallowedGiftsSettings(flags: Int32)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .disallowedStarGiftsSettings(let flags):
|
case .disallowedGiftsSettings(let flags):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1653721450)
|
buffer.appendInt32(1911715524)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
break
|
break
|
||||||
@ -1441,17 +1441,17 @@ public extension Api {
|
|||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .disallowedStarGiftsSettings(let flags):
|
case .disallowedGiftsSettings(let flags):
|
||||||
return ("disallowedStarGiftsSettings", [("flags", flags as Any)])
|
return ("disallowedGiftsSettings", [("flags", flags as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func parse_disallowedStarGiftsSettings(_ reader: BufferReader) -> DisallowedStarGiftsSettings? {
|
public static func parse_disallowedGiftsSettings(_ reader: BufferReader) -> DisallowedGiftsSettings? {
|
||||||
var _1: Int32?
|
var _1: Int32?
|
||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
if _c1 {
|
if _c1 {
|
||||||
return Api.DisallowedStarGiftsSettings.disallowedStarGiftsSettings(flags: _1!)
|
return Api.DisallowedGiftsSettings.disallowedGiftsSettings(flags: _1!)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -946,25 +946,25 @@ public extension Api {
|
|||||||
}
|
}
|
||||||
public extension Api {
|
public extension Api {
|
||||||
enum GlobalPrivacySettings: TypeConstructorDescription {
|
enum GlobalPrivacySettings: TypeConstructorDescription {
|
||||||
case globalPrivacySettings(flags: Int32, noncontactPeersPaidStars: Int64?, disallowedStargifts: Api.DisallowedStarGiftsSettings?)
|
case globalPrivacySettings(flags: Int32, noncontactPeersPaidStars: Int64?, disallowedGifts: Api.DisallowedGiftsSettings?)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
case .globalPrivacySettings(let flags, let noncontactPeersPaidStars, let disallowedStargifts):
|
case .globalPrivacySettings(let flags, let noncontactPeersPaidStars, let disallowedGifts):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(-715184062)
|
buffer.appendInt32(-29248689)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 5) != 0 {serializeInt64(noncontactPeersPaidStars!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 5) != 0 {serializeInt64(noncontactPeersPaidStars!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 6) != 0 {disallowedStargifts!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 6) != 0 {disallowedGifts!.serialize(buffer, true)}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||||
switch self {
|
switch self {
|
||||||
case .globalPrivacySettings(let flags, let noncontactPeersPaidStars, let disallowedStargifts):
|
case .globalPrivacySettings(let flags, let noncontactPeersPaidStars, let disallowedGifts):
|
||||||
return ("globalPrivacySettings", [("flags", flags as Any), ("noncontactPeersPaidStars", noncontactPeersPaidStars as Any), ("disallowedStargifts", disallowedStargifts as Any)])
|
return ("globalPrivacySettings", [("flags", flags as Any), ("noncontactPeersPaidStars", noncontactPeersPaidStars as Any), ("disallowedGifts", disallowedGifts as Any)])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -973,15 +973,15 @@ public extension Api {
|
|||||||
_1 = reader.readInt32()
|
_1 = reader.readInt32()
|
||||||
var _2: Int64?
|
var _2: Int64?
|
||||||
if Int(_1!) & Int(1 << 5) != 0 {_2 = reader.readInt64() }
|
if Int(_1!) & Int(1 << 5) != 0 {_2 = reader.readInt64() }
|
||||||
var _3: Api.DisallowedStarGiftsSettings?
|
var _3: Api.DisallowedGiftsSettings?
|
||||||
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
|
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
|
||||||
_3 = Api.parse(reader, signature: signature) as? Api.DisallowedStarGiftsSettings
|
_3 = Api.parse(reader, signature: signature) as? Api.DisallowedGiftsSettings
|
||||||
} }
|
} }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = (Int(_1!) & Int(1 << 5) == 0) || _2 != nil
|
let _c2 = (Int(_1!) & Int(1 << 5) == 0) || _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 6) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 6) == 0) || _3 != nil
|
||||||
if _c1 && _c2 && _c3 {
|
if _c1 && _c2 && _c3 {
|
||||||
return Api.GlobalPrivacySettings.globalPrivacySettings(flags: _1!, noncontactPeersPaidStars: _2, disallowedStargifts: _3)
|
return Api.GlobalPrivacySettings.globalPrivacySettings(flags: _1!, noncontactPeersPaidStars: _2, disallowedGifts: _3)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -306,6 +306,14 @@ public struct TelegramDisallowedGifts: OptionSet, Codable {
|
|||||||
public static let unlimited = TelegramDisallowedGifts(rawValue: 1 << 0)
|
public static let unlimited = TelegramDisallowedGifts(rawValue: 1 << 0)
|
||||||
public static let limited = TelegramDisallowedGifts(rawValue: 1 << 1)
|
public static let limited = TelegramDisallowedGifts(rawValue: 1 << 1)
|
||||||
public static let unique = TelegramDisallowedGifts(rawValue: 1 << 2)
|
public static let unique = TelegramDisallowedGifts(rawValue: 1 << 2)
|
||||||
|
public static let premium = TelegramDisallowedGifts(rawValue: 1 << 3)
|
||||||
|
|
||||||
|
public static let All: TelegramDisallowedGifts = [
|
||||||
|
.unlimited,
|
||||||
|
.limited,
|
||||||
|
.unique,
|
||||||
|
.premium
|
||||||
|
]
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||||
|
@ -526,7 +526,7 @@ private class AdMessagesHistoryContextImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func markAction(opaqueId: Data, media: Bool, fullscreen: Bool) {
|
func markAction(opaqueId: Data, media: Bool, fullscreen: Bool) {
|
||||||
_internal_markAdAction(account: self.account, peerId: self.peerId, opaqueId: opaqueId, media: media, fullscreen: fullscreen)
|
_internal_markAdAction(account: self.account, opaqueId: opaqueId, media: media, fullscreen: fullscreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
func remove(opaqueId: Data) {
|
func remove(opaqueId: Data) {
|
||||||
@ -601,7 +601,7 @@ public class AdMessagesHistoryContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func _internal_markAdAction(account: Account, peerId: EnginePeer.Id, opaqueId: Data, media: Bool, fullscreen: Bool) {
|
func _internal_markAdAction(account: Account, opaqueId: Data, media: Bool, fullscreen: Bool) {
|
||||||
var flags: Int32 = 0
|
var flags: Int32 = 0
|
||||||
if media {
|
if media {
|
||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
@ -616,3 +616,14 @@ func _internal_markAdAction(account: Account, peerId: EnginePeer.Id, opaqueId: D
|
|||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
let _ = signal.start()
|
let _ = signal.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _internal_markAsSeen(account: Account, opaqueId: Data) -> Signal<Never, NoError> {
|
||||||
|
return account.network.request(Api.functions.messages.viewSponsoredMessage(randomId: Buffer(data: opaqueId)))
|
||||||
|
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||||
|
return .single(.boolFalse)
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
@ -1125,6 +1125,23 @@ public struct TelegramBusinessBotRights: OptionSet, Codable {
|
|||||||
public static let transferStars = TelegramBusinessBotRights(rawValue: 1 << 12)
|
public static let transferStars = TelegramBusinessBotRights(rawValue: 1 << 12)
|
||||||
public static let manageStories = TelegramBusinessBotRights(rawValue: 1 << 13)
|
public static let manageStories = TelegramBusinessBotRights(rawValue: 1 << 13)
|
||||||
|
|
||||||
|
public static let All: TelegramBusinessBotRights = [
|
||||||
|
.reply,
|
||||||
|
.readMessages,
|
||||||
|
.deleteSentMessages,
|
||||||
|
.deleteReceivedMessages,
|
||||||
|
.editName,
|
||||||
|
.editBio,
|
||||||
|
.editProfilePhoto,
|
||||||
|
.editUsername,
|
||||||
|
.viewGifts,
|
||||||
|
.sellGifts,
|
||||||
|
.changeGiftSettings,
|
||||||
|
.transferAndUpgradeGifts,
|
||||||
|
.transferStars,
|
||||||
|
.manageStories
|
||||||
|
]
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
public init(from decoder: Decoder) throws {
|
||||||
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
let container = try decoder.container(keyedBy: StringCodingKey.self)
|
||||||
let value = try? container.decode(Int32.self, forKey: "v")
|
let value = try? container.decode(Int32.self, forKey: "v")
|
||||||
|
@ -19,7 +19,7 @@ public enum ReportAdMessageError {
|
|||||||
case premiumRequired
|
case premiumRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_reportAdMessage(account: Account, peerId: EnginePeer.Id, opaqueId: Data, option: Data?) -> Signal<ReportAdMessageResult, ReportAdMessageError> {
|
func _internal_reportAdMessage(account: Account, opaqueId: Data, option: Data?) -> Signal<ReportAdMessageResult, ReportAdMessageError> {
|
||||||
return account.network.request(Api.functions.messages.reportSponsoredMessage(randomId: Buffer(data: opaqueId), option: Buffer(data: option)))
|
return account.network.request(Api.functions.messages.reportSponsoredMessage(randomId: Buffer(data: opaqueId), option: Buffer(data: option)))
|
||||||
|> mapError { error -> ReportAdMessageError in
|
|> mapError { error -> ReportAdMessageError in
|
||||||
if error.errorDescription == "PREMIUM_ACCOUNT_REQUIRED" {
|
if error.errorDescription == "PREMIUM_ACCOUNT_REQUIRED" {
|
||||||
|
@ -1504,8 +1504,8 @@ public extension TelegramEngine {
|
|||||||
}).startStandalone()
|
}).startStandalone()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reportAdMessage(peerId: EnginePeer.Id, opaqueId: Data, option: Data?) -> Signal<ReportAdMessageResult, ReportAdMessageError> {
|
public func reportAdMessage(opaqueId: Data, option: Data?) -> Signal<ReportAdMessageResult, ReportAdMessageError> {
|
||||||
return _internal_reportAdMessage(account: self.account, peerId: peerId, opaqueId: opaqueId, option: option)
|
return _internal_reportAdMessage(account: self.account, opaqueId: opaqueId, option: option)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func reportContent(subject: ReportContentSubject, option: Data?, message: String?) -> Signal<ReportContentResult, ReportContentError> {
|
public func reportContent(subject: ReportContentSubject, option: Data?, message: String?) -> Signal<ReportContentResult, ReportContentError> {
|
||||||
@ -1516,8 +1516,8 @@ public extension TelegramEngine {
|
|||||||
return _internal_updateExtendedMedia(account: self.account, messageIds: messageIds)
|
return _internal_updateExtendedMedia(account: self.account, messageIds: messageIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func markAdAction(peerId: EnginePeer.Id, opaqueId: Data, media: Bool, fullscreen: Bool) {
|
public func markAdAction(opaqueId: Data, media: Bool, fullscreen: Bool) {
|
||||||
_internal_markAdAction(account: self.account, peerId: peerId, opaqueId: opaqueId, media: media, fullscreen: fullscreen)
|
_internal_markAdAction(account: self.account, opaqueId: opaqueId, media: media, fullscreen: fullscreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func getAllLocalChannels(count: Int) -> Signal<[EnginePeer.Id], NoError> {
|
public func getAllLocalChannels(count: Int) -> Signal<[EnginePeer.Id], NoError> {
|
||||||
|
@ -6,12 +6,14 @@ import TelegramApi
|
|||||||
public class AdPeer: Equatable {
|
public class AdPeer: Equatable {
|
||||||
public let opaqueId: Data
|
public let opaqueId: Data
|
||||||
public let peer: EnginePeer
|
public let peer: EnginePeer
|
||||||
|
public let subscribers: Int32?
|
||||||
public let sponsorInfo: String?
|
public let sponsorInfo: String?
|
||||||
public let additionalInfo: String?
|
public let additionalInfo: String?
|
||||||
|
|
||||||
public init(opaqueId: Data, peer: EnginePeer, sponsorInfo: String?, additionalInfo: String?) {
|
public init(opaqueId: Data, peer: EnginePeer, subscribers: Int32?, sponsorInfo: String?, additionalInfo: String?) {
|
||||||
self.opaqueId = opaqueId
|
self.opaqueId = opaqueId
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
|
self.subscribers = subscribers
|
||||||
self.sponsorInfo = sponsorInfo
|
self.sponsorInfo = sponsorInfo
|
||||||
self.additionalInfo = additionalInfo
|
self.additionalInfo = additionalInfo
|
||||||
}
|
}
|
||||||
@ -23,6 +25,9 @@ public class AdPeer: Equatable {
|
|||||||
if lhs.peer != rhs.peer {
|
if lhs.peer != rhs.peer {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.subscribers != rhs.subscribers {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.sponsorInfo != rhs.sponsorInfo {
|
if lhs.sponsorInfo != rhs.sponsorInfo {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -49,6 +54,20 @@ func _internal_searchAdPeers(account: Account, query: String) -> Signal<[AdPeer]
|
|||||||
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
let parsedPeers = AccumulatedPeers(transaction: transaction, chats: chats, users: users)
|
||||||
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
|
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers)
|
||||||
|
|
||||||
|
var subscribers: [PeerId: Int32] = [:]
|
||||||
|
for chat in chats {
|
||||||
|
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||||
|
switch chat {
|
||||||
|
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _, _, _):
|
||||||
|
if let participantsCount = participantsCount {
|
||||||
|
subscribers[groupOrChannel.id] = participantsCount
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var result: [AdPeer] = []
|
var result: [AdPeer] = []
|
||||||
for peer in peers {
|
for peer in peers {
|
||||||
switch peer {
|
switch peer {
|
||||||
@ -60,6 +79,7 @@ func _internal_searchAdPeers(account: Account, query: String) -> Signal<[AdPeer]
|
|||||||
AdPeer(
|
AdPeer(
|
||||||
opaqueId: randomId.makeData(),
|
opaqueId: randomId.makeData(),
|
||||||
peer: EnginePeer(peer),
|
peer: EnginePeer(peer),
|
||||||
|
subscribers: subscribers[peer.id],
|
||||||
sponsorInfo: sponsorInfo,
|
sponsorInfo: sponsorInfo,
|
||||||
additionalInfo: additionalInfo
|
additionalInfo: additionalInfo
|
||||||
)
|
)
|
||||||
@ -73,15 +93,3 @@ func _internal_searchAdPeers(account: Account, query: String) -> Signal<[AdPeer]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func _internal_markAsSeen(account: Account, opaqueId: Data) -> Signal<Never, NoError> {
|
|
||||||
let signal: Signal<Never, NoError> = account.network.request(Api.functions.messages.viewSponsoredMessage(randomId: Buffer(data: opaqueId)))
|
|
||||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
|
||||||
return .single(.boolFalse)
|
|
||||||
}
|
|
||||||
|> ignoreValues
|
|
||||||
|
|
||||||
|
|
||||||
return signal
|
|
||||||
}
|
|
||||||
|
@ -397,7 +397,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
let sendPaidMessageStars = sendPaidMessageStars.flatMap { StarsAmount(value: $0, nanos: 0) }
|
let sendPaidMessageStars = sendPaidMessageStars.flatMap { StarsAmount(value: $0, nanos: 0) }
|
||||||
|
|
||||||
var disallowedGifts: TelegramDisallowedGifts = []
|
var disallowedGifts: TelegramDisallowedGifts = []
|
||||||
if case let .disallowedStarGiftsSettings(giftFlags) = disallowedStarGifts {
|
if case let .disallowedGiftsSettings(giftFlags) = disallowedStarGifts {
|
||||||
if (giftFlags & (1 << 0)) != 0 {
|
if (giftFlags & (1 << 0)) != 0 {
|
||||||
disallowedGifts.insert(.unlimited)
|
disallowedGifts.insert(.unlimited)
|
||||||
}
|
}
|
||||||
@ -407,6 +407,9 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
|
|||||||
if (giftFlags & (1 << 2)) != 0 {
|
if (giftFlags & (1 << 2)) != 0 {
|
||||||
disallowedGifts.insert(.unique)
|
disallowedGifts.insert(.unique)
|
||||||
}
|
}
|
||||||
|
if (giftFlags & (1 << 3)) != 0 {
|
||||||
|
disallowedGifts.insert(.premium)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return previous.withUpdatedAbout(userFullAbout)
|
return previous.withUpdatedAbout(userFullAbout)
|
||||||
|
@ -34,7 +34,7 @@ func _internal_updateGlobalPrivacySettings(account: Account) -> Signal<Never, No
|
|||||||
}
|
}
|
||||||
|
|
||||||
var disallowedGifts: TelegramDisallowedGifts = []
|
var disallowedGifts: TelegramDisallowedGifts = []
|
||||||
if case let .disallowedStarGiftsSettings(giftFlags) = disallowedStarGifts {
|
if case let .disallowedGiftsSettings(giftFlags) = disallowedStarGifts {
|
||||||
if (giftFlags & (1 << 0)) != 0 {
|
if (giftFlags & (1 << 0)) != 0 {
|
||||||
disallowedGifts.insert(.unlimited)
|
disallowedGifts.insert(.unlimited)
|
||||||
}
|
}
|
||||||
@ -44,6 +44,9 @@ func _internal_updateGlobalPrivacySettings(account: Account) -> Signal<Never, No
|
|||||||
if (giftFlags & (1 << 2)) != 0 {
|
if (giftFlags & (1 << 2)) != 0 {
|
||||||
disallowedGifts.insert(.unique)
|
disallowedGifts.insert(.unique)
|
||||||
}
|
}
|
||||||
|
if (giftFlags & (1 << 3)) != 0 {
|
||||||
|
disallowedGifts.insert(.premium)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
globalSettings = GlobalPrivacySettings(
|
globalSettings = GlobalPrivacySettings(
|
||||||
@ -256,7 +259,7 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal<Account
|
|||||||
}
|
}
|
||||||
|
|
||||||
var disallowedGifts: TelegramDisallowedGifts = []
|
var disallowedGifts: TelegramDisallowedGifts = []
|
||||||
if case let .disallowedStarGiftsSettings(giftFlags) = disallowedStarGifts {
|
if case let .disallowedGiftsSettings(giftFlags) = disallowedStarGifts {
|
||||||
if (giftFlags & (1 << 0)) != 0 {
|
if (giftFlags & (1 << 0)) != 0 {
|
||||||
disallowedGifts.insert(.unlimited)
|
disallowedGifts.insert(.unlimited)
|
||||||
}
|
}
|
||||||
@ -266,6 +269,9 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal<Account
|
|||||||
if (giftFlags & (1 << 2)) != 0 {
|
if (giftFlags & (1 << 2)) != 0 {
|
||||||
disallowedGifts.insert(.unique)
|
disallowedGifts.insert(.unique)
|
||||||
}
|
}
|
||||||
|
if (giftFlags & (1 << 3)) != 0 {
|
||||||
|
disallowedGifts.insert(.premium)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
globalSettings = GlobalPrivacySettings(
|
globalSettings = GlobalPrivacySettings(
|
||||||
@ -409,10 +415,10 @@ func _internal_updateGlobalPrivacySettings(account: Account, settings: GlobalPri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags |= 1 << 6
|
flags |= 1 << 6
|
||||||
let disallowedStargifts = Api.DisallowedStarGiftsSettings.disallowedStarGiftsSettings(flags: giftFlags)
|
let disallowedStargifts = Api.DisallowedGiftsSettings.disallowedGiftsSettings(flags: giftFlags)
|
||||||
|
|
||||||
return account.network.request(Api.functions.account.setGlobalPrivacySettings(
|
return account.network.request(Api.functions.account.setGlobalPrivacySettings(
|
||||||
settings: .globalPrivacySettings(flags: flags, noncontactPeersPaidStars: noncontactPeersPaidStars, disallowedStargifts: disallowedStargifts)
|
settings: .globalPrivacySettings(flags: flags, noncontactPeersPaidStars: noncontactPeersPaidStars, disallowedGifts: disallowedStargifts)
|
||||||
))
|
))
|
||||||
|> retryRequest
|
|> retryRequest
|
||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
|
@ -1277,22 +1277,19 @@ public class AdsInfoScreen: ViewController {
|
|||||||
guard let navigationController = self?.controller?.navigationController as? NavigationController else {
|
guard let navigationController = self?.controller?.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self?.controller?.dismiss(animated: true)
|
let _ = (context.engine.messages.reportAdMessage(opaqueId: adAttribute.opaqueId, option: nil)
|
||||||
|
|
||||||
let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|
|
||||||
|> deliverOnMainQueue).start(next: { [weak navigationController] result in
|
|> deliverOnMainQueue).start(next: { [weak navigationController] result in
|
||||||
if case let .options(title, options) = result {
|
if case let .options(title, options) = result {
|
||||||
Queue.mainQueue().after(0.2) {
|
Queue.mainQueue().after(0.2) {
|
||||||
navigationController?.pushViewController(
|
navigationController?.pushViewController(
|
||||||
AdsReportScreen(
|
AdsReportScreen(
|
||||||
context: context,
|
context: context,
|
||||||
peerId: message.id.peerId,
|
|
||||||
opaqueId: adAttribute.opaqueId,
|
opaqueId: adAttribute.opaqueId,
|
||||||
title: title,
|
title: title,
|
||||||
options: options,
|
options: options,
|
||||||
completed: {
|
completed: {
|
||||||
removeAd?(adAttribute.opaqueId)
|
// removeAd?(adAttribute.opaqueId)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -250,7 +250,6 @@ private final class SheetContent: CombinedComponent {
|
|||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peerId: EnginePeer.Id
|
|
||||||
let opaqueId: Data
|
let opaqueId: Data
|
||||||
let title: String
|
let title: String
|
||||||
let options: [ReportAdMessageResult.Option]
|
let options: [ReportAdMessageResult.Option]
|
||||||
@ -262,7 +261,6 @@ private final class SheetContent: CombinedComponent {
|
|||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
peerId: EnginePeer.Id,
|
|
||||||
opaqueId: Data,
|
opaqueId: Data,
|
||||||
title: String,
|
title: String,
|
||||||
options: [ReportAdMessageResult.Option],
|
options: [ReportAdMessageResult.Option],
|
||||||
@ -273,7 +271,6 @@ private final class SheetContent: CombinedComponent {
|
|||||||
update: @escaping (ComponentTransition) -> Void
|
update: @escaping (ComponentTransition) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
|
||||||
self.opaqueId = opaqueId
|
self.opaqueId = opaqueId
|
||||||
self.title = title
|
self.title = title
|
||||||
self.options = options
|
self.options = options
|
||||||
@ -288,9 +285,6 @@ private final class SheetContent: CombinedComponent {
|
|||||||
if lhs.context !== rhs.context {
|
if lhs.context !== rhs.context {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.peerId != rhs.peerId {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lhs.opaqueId != rhs.opaqueId {
|
if lhs.opaqueId != rhs.opaqueId {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -329,7 +323,6 @@ private final class SheetContent: CombinedComponent {
|
|||||||
let update = component.update
|
let update = component.update
|
||||||
|
|
||||||
let accountContext = component.context
|
let accountContext = component.context
|
||||||
let peerId = component.peerId
|
|
||||||
let opaqueId = component.opaqueId
|
let opaqueId = component.opaqueId
|
||||||
let complete = component.complete
|
let complete = component.complete
|
||||||
let action: (SheetPageContent.Item) -> Void = { [weak state] item in
|
let action: (SheetPageContent.Item) -> Void = { [weak state] item in
|
||||||
@ -337,7 +330,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
state.disposable.set(
|
state.disposable.set(
|
||||||
(accountContext.engine.messages.reportAdMessage(peerId: peerId, opaqueId: opaqueId, option: item.option)
|
(accountContext.engine.messages.reportAdMessage(opaqueId: opaqueId, option: item.option)
|
||||||
|> deliverOnMainQueue).start(next: { [weak state] result in
|
|> deliverOnMainQueue).start(next: { [weak state] result in
|
||||||
switch result {
|
switch result {
|
||||||
case let .options(title, options):
|
case let .options(title, options):
|
||||||
@ -423,7 +416,6 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let peerId: EnginePeer.Id
|
|
||||||
let opaqueId: Data
|
let opaqueId: Data
|
||||||
let title: String
|
let title: String
|
||||||
let options: [ReportAdMessageResult.Option]
|
let options: [ReportAdMessageResult.Option]
|
||||||
@ -432,7 +424,6 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
peerId: EnginePeer.Id,
|
|
||||||
opaqueId: Data,
|
opaqueId: Data,
|
||||||
title: String,
|
title: String,
|
||||||
options: [ReportAdMessageResult.Option],
|
options: [ReportAdMessageResult.Option],
|
||||||
@ -440,7 +431,6 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||||||
complete: @escaping (ReportResult) -> Void
|
complete: @escaping (ReportResult) -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
|
||||||
self.opaqueId = opaqueId
|
self.opaqueId = opaqueId
|
||||||
self.title = title
|
self.title = title
|
||||||
self.options = options
|
self.options = options
|
||||||
@ -452,9 +442,6 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||||||
if lhs.context !== rhs.context {
|
if lhs.context !== rhs.context {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.peerId != rhs.peerId {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if lhs.opaqueId != rhs.opaqueId {
|
if lhs.opaqueId != rhs.opaqueId {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -490,7 +477,6 @@ private final class SheetContainerComponent: CombinedComponent {
|
|||||||
component: SheetComponent<EnvironmentType>(
|
component: SheetComponent<EnvironmentType>(
|
||||||
content: AnyComponent<EnvironmentType>(SheetContent(
|
content: AnyComponent<EnvironmentType>(SheetContent(
|
||||||
context: context.component.context,
|
context: context.component.context,
|
||||||
peerId: context.component.peerId,
|
|
||||||
opaqueId: context.component.opaqueId,
|
opaqueId: context.component.opaqueId,
|
||||||
title: context.component.title,
|
title: context.component.title,
|
||||||
options: context.component.options,
|
options: context.component.options,
|
||||||
@ -571,7 +557,6 @@ public final class AdsReportScreen: ViewControllerComponentContainer {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
peerId: EnginePeer.Id,
|
|
||||||
opaqueId: Data,
|
opaqueId: Data,
|
||||||
title: String,
|
title: String,
|
||||||
options: [ReportAdMessageResult.Option],
|
options: [ReportAdMessageResult.Option],
|
||||||
@ -585,7 +570,6 @@ public final class AdsReportScreen: ViewControllerComponentContainer {
|
|||||||
context: context,
|
context: context,
|
||||||
component: SheetContainerComponent(
|
component: SheetContainerComponent(
|
||||||
context: context,
|
context: context,
|
||||||
peerId: peerId,
|
|
||||||
opaqueId: opaqueId,
|
opaqueId: opaqueId,
|
||||||
title: title,
|
title: title,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -686,7 +686,7 @@ public final class ChatInlineSearchResultsListComponent: Component {
|
|||||||
},
|
},
|
||||||
openPhotoSetup: {
|
openPhotoSetup: {
|
||||||
},
|
},
|
||||||
openAdInfo: { _ in
|
openAdInfo: { _, _ in
|
||||||
},
|
},
|
||||||
openAccountFreezeInfo: {
|
openAccountFreezeInfo: {
|
||||||
}
|
}
|
||||||
|
@ -69,11 +69,19 @@ public final class GiftItemComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Font {
|
||||||
|
case generic
|
||||||
|
case monospaced
|
||||||
|
}
|
||||||
|
|
||||||
public let text: String
|
public let text: String
|
||||||
|
public let font: Font
|
||||||
public let color: Color
|
public let color: Color
|
||||||
|
|
||||||
public init(text: String, color: Color) {
|
public init(text: String, font: Font = .generic, color: Color) {
|
||||||
self.text = text
|
self.text = text
|
||||||
|
self.font = font
|
||||||
self.color = color
|
self.color = color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -593,11 +601,19 @@ public final class GiftItemComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
ribbonFontSize = 10.0
|
ribbonFontSize = 10.0
|
||||||
}
|
}
|
||||||
|
let ribbonFont: UIFont
|
||||||
|
switch ribbon.font {
|
||||||
|
case .generic:
|
||||||
|
ribbonFont = Font.semibold(ribbonFontSize)
|
||||||
|
case .monospaced:
|
||||||
|
ribbonFont = Font.with(size: 10.0, design: .monospace, weight: .semibold)
|
||||||
|
}
|
||||||
|
|
||||||
let ribbonTextSize = self.ribbonText.update(
|
let ribbonTextSize = self.ribbonText.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
MultilineTextComponent(
|
MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: ribbon.text, font: Font.semibold(ribbonFontSize), textColor: .white)),
|
text: .plain(NSAttributedString(string: ribbon.text, font: ribbonFont, textColor: .white)),
|
||||||
horizontalAlignment: .center
|
horizontalAlignment: .center
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -778,7 +794,11 @@ public final class GiftItemComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
selectionLayer = SimpleShapeLayer()
|
selectionLayer = SimpleShapeLayer()
|
||||||
self.selectionLayer = selectionLayer
|
self.selectionLayer = selectionLayer
|
||||||
self.layer.addSublayer(selectionLayer)
|
if self.ribbon.layer.superlayer != nil {
|
||||||
|
self.layer.insertSublayer(selectionLayer, below: self.ribbon.layer)
|
||||||
|
} else {
|
||||||
|
self.layer.addSublayer(selectionLayer)
|
||||||
|
}
|
||||||
|
|
||||||
selectionLayer.fillColor = UIColor.clear.cgColor
|
selectionLayer.fillColor = UIColor.clear.cgColor
|
||||||
selectionLayer.strokeColor = UIColor.white.cgColor
|
selectionLayer.strokeColor = UIColor.white.cgColor
|
||||||
|
@ -430,10 +430,15 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
)
|
)
|
||||||
mainController.push(giftController)
|
mainController.push(giftController)
|
||||||
} else {
|
} else {
|
||||||
|
var forceUnique = false
|
||||||
|
if let disallowedGifts = self.state?.disallowedGifts, disallowedGifts.contains(.limited) && !disallowedGifts.contains(.unique) {
|
||||||
|
forceUnique = true
|
||||||
|
}
|
||||||
|
|
||||||
let giftController = GiftSetupScreen(
|
let giftController = GiftSetupScreen(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
peerId: component.peerId,
|
peerId: component.peerId,
|
||||||
subject: .starGift(gift),
|
subject: .starGift(gift, forceUnique),
|
||||||
completion: component.completion
|
completion: component.completion
|
||||||
)
|
)
|
||||||
mainController.push(giftController)
|
mainController.push(giftController)
|
||||||
@ -714,7 +719,7 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
|
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled
|
let isPremiumDisabled = premiumConfiguration.isPremiumDisabled || state.disallowedGifts?.contains(.premium) == true
|
||||||
let isSelfGift = component.peerId == component.context.account.peerId
|
let isSelfGift = component.peerId == component.context.account.peerId
|
||||||
let isChannelGift = component.peerId.namespace == Namespaces.Peer.CloudChannel
|
let isChannelGift = component.peerId.namespace == Namespaces.Peer.CloudChannel
|
||||||
|
|
||||||
@ -1425,7 +1430,11 @@ final class GiftOptionsScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
if disallowedGifts.contains(.limited) {
|
if disallowedGifts.contains(.limited) {
|
||||||
if gift.availability != nil {
|
if gift.availability != nil {
|
||||||
return false
|
if !disallowedGifts.contains(.unique) && gift.upgradeStars != nil {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,7 +371,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
case let .starGift(starGift):
|
case let .starGift(starGift, _):
|
||||||
finalPrice = starGift.price
|
finalPrice = starGift.price
|
||||||
if self.includeUpgrade, let upgradeStars = starGift.upgradeStars {
|
if self.includeUpgrade, let upgradeStars = starGift.upgradeStars {
|
||||||
finalPrice += upgradeStars
|
finalPrice += upgradeStars
|
||||||
@ -403,7 +403,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if peerId.namespace == Namespaces.Peer.CloudChannel, case let .starGift(starGift) = component.subject {
|
if peerId.namespace == Namespaces.Peer.CloudChannel, case let .starGift(starGift, _) = component.subject {
|
||||||
var controllers = navigationController.viewControllers
|
var controllers = navigationController.viewControllers
|
||||||
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) }
|
controllers = controllers.filter { !($0 is GiftSetupScreen) && !($0 is GiftOptionsScreenProtocol) }
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
@ -555,6 +555,10 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
self.hideName = true
|
self.hideName = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if case let .starGift(gift, true) = component.subject, gift.upgradeStars != nil {
|
||||||
|
self.includeUpgrade = true
|
||||||
|
}
|
||||||
|
|
||||||
let _ = (component.context.engine.data.get(
|
let _ = (component.context.engine.data.get(
|
||||||
TelegramEngine.EngineData.Item.Peer.Peer(id: component.peerId),
|
TelegramEngine.EngineData.Item.Peer.Peer(id: component.peerId),
|
||||||
TelegramEngine.EngineData.Item.Peer.Peer(id: component.context.account.peerId),
|
TelegramEngine.EngineData.Item.Peer.Peer(id: component.context.account.peerId),
|
||||||
@ -684,7 +688,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
self.options = options
|
self.options = options
|
||||||
})
|
})
|
||||||
|
|
||||||
if case let .starGift(gift) = component.subject {
|
if case let .starGift(gift, _) = component.subject {
|
||||||
if let _ = gift.upgradeStars {
|
if let _ = gift.upgradeStars {
|
||||||
self.previewPromise.set(
|
self.previewPromise.set(
|
||||||
component.context.engine.payments.starGiftUpgradePreview(giftId: gift.id)
|
component.context.engine.payments.starGiftUpgradePreview(giftId: gift.id)
|
||||||
@ -742,7 +746,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
contentHeight += environment.navigationHeight
|
contentHeight += environment.navigationHeight
|
||||||
contentHeight += 26.0
|
contentHeight += 26.0
|
||||||
|
|
||||||
if case let .starGift(starGift) = component.subject, let availability = starGift.availability {
|
if case let .starGift(starGift, _) = component.subject, let availability = starGift.availability {
|
||||||
let remains: Int32 = availability.remains
|
let remains: Int32 = availability.remains
|
||||||
let total: Int32 = availability.total
|
let total: Int32 = availability.total
|
||||||
let position = CGFloat(remains) / CGFloat(total)
|
let position = CGFloat(remains) / CGFloat(total)
|
||||||
@ -909,7 +913,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
let (currency, amount) = product.storeProduct?.priceCurrencyAndAmount ?? ("USD", 1)
|
let (currency, amount) = product.storeProduct?.priceCurrencyAndAmount ?? ("USD", 1)
|
||||||
subject = .premium(months: product.months, amount: amount, currency: currency)
|
subject = .premium(months: product.months, amount: amount, currency: currency)
|
||||||
}
|
}
|
||||||
case let .starGift(gift):
|
case let .starGift(gift, _):
|
||||||
subject = .starGift(gift: gift)
|
subject = .starGift(gift: gift)
|
||||||
upgradeStars = gift.upgradeStars
|
upgradeStars = gift.upgradeStars
|
||||||
}
|
}
|
||||||
@ -1061,13 +1065,17 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
contentHeight += starsSectionSize.height
|
contentHeight += starsSectionSize.height
|
||||||
contentHeight += sectionSpacing
|
contentHeight += sectionSpacing
|
||||||
}
|
}
|
||||||
case let .starGift(gift):
|
case let .starGift(gift, forceUnique):
|
||||||
if let upgradeStars = gift.upgradeStars, component.peerId != component.context.account.peerId {
|
if let upgradeStars = gift.upgradeStars, component.peerId != component.context.account.peerId {
|
||||||
let upgradeFooterRawString: String
|
let upgradeFooterRawString: String
|
||||||
if isChannelGift {
|
if isChannelGift {
|
||||||
upgradeFooterRawString = environment.strings.Gift_SendChannel_Upgrade_Info(peerName).string
|
upgradeFooterRawString = environment.strings.Gift_SendChannel_Upgrade_Info(peerName).string
|
||||||
} else {
|
} else {
|
||||||
upgradeFooterRawString = environment.strings.Gift_Send_Upgrade_Info(peerName).string
|
if forceUnique {
|
||||||
|
upgradeFooterRawString = environment.strings.Gift_Send_Upgrade_ForcedInfo(peerName).string
|
||||||
|
} else {
|
||||||
|
upgradeFooterRawString = environment.strings.Gift_Send_Upgrade_Info(peerName).string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let parsedString = parseMarkdownIntoAttributedString(upgradeFooterRawString, attributes: footerAttributes)
|
let parsedString = parseMarkdownIntoAttributedString(upgradeFooterRawString, attributes: footerAttributes)
|
||||||
|
|
||||||
@ -1136,8 +1144,8 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
)
|
)
|
||||||
)),
|
)),
|
||||||
], alignment: .left, spacing: 2.0)),
|
], alignment: .left, spacing: 2.0)),
|
||||||
accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: self.includeUpgrade, action: { [weak self] _ in
|
accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: self.includeUpgrade, isEnabled: !forceUnique, action: { [weak self] _ in
|
||||||
guard let self else {
|
guard let self, !forceUnique else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.includeUpgrade = !self.includeUpgrade
|
self.includeUpgrade = !self.includeUpgrade
|
||||||
@ -1263,7 +1271,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
let amountString = product.price
|
let amountString = product.price
|
||||||
buttonString = "\(environment.strings.Gift_Send_Send) \(amountString)"
|
buttonString = "\(environment.strings.Gift_Send_Send) \(amountString)"
|
||||||
}
|
}
|
||||||
case let .starGift(starGift):
|
case let .starGift(starGift, _):
|
||||||
var finalPrice: Int64 = starGift.price
|
var finalPrice: Int64 = starGift.price
|
||||||
if self.includeUpgrade, let upgradePrice = starGift.upgradeStars {
|
if self.includeUpgrade, let upgradePrice = starGift.upgradeStars {
|
||||||
finalPrice += upgradePrice
|
finalPrice += upgradePrice
|
||||||
@ -1685,7 +1693,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
public final class GiftSetupScreen: ViewControllerComponentContainer {
|
public final class GiftSetupScreen: ViewControllerComponentContainer {
|
||||||
public enum Subject: Equatable {
|
public enum Subject: Equatable {
|
||||||
case premium(PremiumGiftProduct)
|
case premium(PremiumGiftProduct)
|
||||||
case starGift(StarGift.Gift)
|
case starGift(StarGift.Gift, Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
|
@ -141,3 +141,24 @@ private func generateCloseButtonImage() -> UIImage? {
|
|||||||
context.strokePath()
|
context.strokePath()
|
||||||
})?.withRenderingMode(.alwaysTemplate)
|
})?.withRenderingMode(.alwaysTemplate)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateCloseButtonImage(backgroundColor: UIColor, foregroundColor: UIColor) -> UIImage? {
|
||||||
|
return generateImage(CGSize(width: 30.0, height: 30.0), contextGenerator: { size, context in
|
||||||
|
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setFillColor(backgroundColor.cgColor)
|
||||||
|
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
|
context.setLineWidth(2.0)
|
||||||
|
context.setLineCap(.round)
|
||||||
|
context.setStrokeColor(foregroundColor.cgColor)
|
||||||
|
|
||||||
|
context.move(to: CGPoint(x: 10.0, y: 10.0))
|
||||||
|
context.addLine(to: CGPoint(x: 20.0, y: 20.0))
|
||||||
|
context.strokePath()
|
||||||
|
|
||||||
|
context.move(to: CGPoint(x: 20.0, y: 10.0))
|
||||||
|
context.addLine(to: CGPoint(x: 10.0, y: 20.0))
|
||||||
|
context.strokePath()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -0,0 +1,381 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import Display
|
||||||
|
import ComponentFlow
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramCore
|
||||||
|
import Markdown
|
||||||
|
import TextFormat
|
||||||
|
import TelegramPresentationData
|
||||||
|
import ViewControllerComponent
|
||||||
|
import SheetComponent
|
||||||
|
import BundleIconComponent
|
||||||
|
import BalancedTextComponent
|
||||||
|
import MultilineTextComponent
|
||||||
|
import ButtonComponent
|
||||||
|
import PlainButtonComponent
|
||||||
|
import GiftItemComponent
|
||||||
|
import AccountContext
|
||||||
|
|
||||||
|
private final class SheetContent: CombinedComponent {
|
||||||
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
|
let context: AccountContext
|
||||||
|
let gifts: [ProfileGiftsContext.State.StarGift]
|
||||||
|
let completion: (StarGiftReference) -> Void
|
||||||
|
let dismiss: () -> Void
|
||||||
|
|
||||||
|
init(
|
||||||
|
context: AccountContext,
|
||||||
|
gifts: [ProfileGiftsContext.State.StarGift],
|
||||||
|
completion: @escaping (StarGiftReference) -> Void,
|
||||||
|
dismiss: @escaping () -> Void
|
||||||
|
) {
|
||||||
|
self.context = context
|
||||||
|
self.gifts = gifts
|
||||||
|
self.completion = completion
|
||||||
|
self.dismiss = dismiss
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SheetContent, rhs: SheetContent) -> Bool {
|
||||||
|
if lhs.context !== rhs.context {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.gifts != rhs.gifts {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
final class State: ComponentState {
|
||||||
|
var selectedGift: StarGiftReference?
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeState() -> State {
|
||||||
|
return State()
|
||||||
|
}
|
||||||
|
|
||||||
|
static var body: Body {
|
||||||
|
let closeButton = Child(Button.self)
|
||||||
|
|
||||||
|
let title = Child(BalancedTextComponent.self)
|
||||||
|
let text = Child(BalancedTextComponent.self)
|
||||||
|
let gifts = ChildMap(environment: Empty.self, keyedBy: AnyHashable.self)
|
||||||
|
let button = Child(ButtonComponent.self)
|
||||||
|
|
||||||
|
return { context in
|
||||||
|
let environment = context.environment[EnvironmentType.self]
|
||||||
|
let component = context.component
|
||||||
|
let state = context.state
|
||||||
|
|
||||||
|
let theme = environment.theme
|
||||||
|
let strings = environment.strings
|
||||||
|
|
||||||
|
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
||||||
|
let textSideInset: CGFloat = 32.0 + environment.safeInsets.left
|
||||||
|
|
||||||
|
let titleFont = Font.semibold(17.0)
|
||||||
|
let subtitleFont = Font.regular(12.0)
|
||||||
|
let textColor = theme.actionSheet.primaryTextColor
|
||||||
|
let secondaryTextColor = theme.actionSheet.secondaryTextColor
|
||||||
|
|
||||||
|
var contentSize = CGSize(width: context.availableSize.width, height: 10.0)
|
||||||
|
|
||||||
|
let closeButton = closeButton.update(
|
||||||
|
component: Button(
|
||||||
|
content: AnyComponent(Text(text: strings.Common_Cancel, font: Font.regular(17.0), color: theme.actionSheet.controlAccentColor)),
|
||||||
|
action: { [weak component] in
|
||||||
|
component?.dismiss()
|
||||||
|
}
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: 100.0, height: 30.0),
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
context.add(closeButton
|
||||||
|
.position(CGPoint(x: environment.safeInsets.left + 16.0 + closeButton.size.width / 2.0, y: 28.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
let title = title.update(
|
||||||
|
component: BalancedTextComponent(
|
||||||
|
text: .plain(NSAttributedString(string: "Too Many Pinned Gifts", font: titleFont, textColor: textColor)),
|
||||||
|
horizontalAlignment: .center,
|
||||||
|
maximumNumberOfLines: 1,
|
||||||
|
lineSpacing: 0.1
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
context.add(title
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + title.size.height / 2.0))
|
||||||
|
)
|
||||||
|
contentSize.height += title.size.height
|
||||||
|
|
||||||
|
let text = text.update(
|
||||||
|
component: BalancedTextComponent(
|
||||||
|
text: .plain(NSAttributedString(string: "Select a gift to unpin below:", font: subtitleFont, textColor: secondaryTextColor)),
|
||||||
|
horizontalAlignment: .center,
|
||||||
|
maximumNumberOfLines: 1,
|
||||||
|
lineSpacing: 0.2
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
context.add(text
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + text.size.height / 2.0))
|
||||||
|
)
|
||||||
|
contentSize.height += text.size.height
|
||||||
|
contentSize.height += 17.0
|
||||||
|
|
||||||
|
let itemsSideInset = environment.safeInsets.left + 16.0
|
||||||
|
let spacing: CGFloat = 10.0
|
||||||
|
let itemsInRow = 3
|
||||||
|
let width = (context.availableSize.width - itemsSideInset * 2.0 - spacing * CGFloat(itemsInRow - 1)) / CGFloat(itemsInRow)
|
||||||
|
|
||||||
|
var updatedGifts: [_UpdatedChildComponent] = []
|
||||||
|
var index = 0
|
||||||
|
var nextOriginX = itemsSideInset
|
||||||
|
for gift in component.gifts {
|
||||||
|
guard case let .unique(uniqueGift) = gift.gift else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var ribbonColor: GiftItemComponent.Ribbon.Color = .blue
|
||||||
|
for attribute in uniqueGift.attributes {
|
||||||
|
if case let .backdrop(_, innerColor, outerColor, _, _, _) = attribute {
|
||||||
|
ribbonColor = .custom(outerColor, innerColor)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedGifts.append(
|
||||||
|
gifts[index].update(
|
||||||
|
component: AnyComponent(
|
||||||
|
PlainButtonComponent(
|
||||||
|
content: AnyComponent(
|
||||||
|
GiftItemComponent(
|
||||||
|
context: component.context,
|
||||||
|
theme: theme,
|
||||||
|
strings: strings,
|
||||||
|
subject: .uniqueGift(gift: uniqueGift),
|
||||||
|
ribbon: GiftItemComponent.Ribbon(text: "#\(uniqueGift.number)", font: .monospaced, color: ribbonColor),
|
||||||
|
isSelected: state.selectedGift == gift.reference,
|
||||||
|
mode: .grid
|
||||||
|
)
|
||||||
|
),
|
||||||
|
effectAlignment: .center,
|
||||||
|
action: { [weak state] in
|
||||||
|
guard let state else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.selectedGift = gift.reference
|
||||||
|
state.updated(transition: .spring(duration: 0.3))
|
||||||
|
},
|
||||||
|
animateAlpha: false
|
||||||
|
)
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: width, height: width),
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
)
|
||||||
|
context.add(updatedGifts[index]
|
||||||
|
.position(CGPoint(x: nextOriginX + updatedGifts[index].size.width / 2.0, y: contentSize.height + updatedGifts[index].size.height / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
nextOriginX += updatedGifts[index].size.width + spacing
|
||||||
|
if nextOriginX > context.availableSize.width - itemsSideInset {
|
||||||
|
contentSize.height += updatedGifts[index].size.height + spacing
|
||||||
|
nextOriginX = itemsSideInset
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1
|
||||||
|
}
|
||||||
|
contentSize.height += 14.0
|
||||||
|
|
||||||
|
let button = button.update(
|
||||||
|
component: ButtonComponent(
|
||||||
|
background: ButtonComponent.Background(
|
||||||
|
color: theme.list.itemCheckColors.fillColor,
|
||||||
|
foreground: theme.list.itemCheckColors.foregroundColor,
|
||||||
|
pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9)
|
||||||
|
),
|
||||||
|
content: AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("unpin"),
|
||||||
|
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Unpin", font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||||
|
),
|
||||||
|
isEnabled: state.selectedGift != nil,
|
||||||
|
displaysProgress: false,
|
||||||
|
action: { [weak state] in
|
||||||
|
guard let state else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let selectedGift = state.selectedGift {
|
||||||
|
component.completion(selectedGift)
|
||||||
|
component.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
context.add(button
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: contentSize.height + button.size.height / 2.0))
|
||||||
|
.cornerRadius(10.0)
|
||||||
|
)
|
||||||
|
contentSize.height += button.size.height
|
||||||
|
contentSize.height += 7.0
|
||||||
|
|
||||||
|
let effectiveBottomInset: CGFloat = environment.metrics.isTablet ? 0.0 : environment.safeInsets.bottom
|
||||||
|
contentSize.height += 5.0 + effectiveBottomInset
|
||||||
|
|
||||||
|
return contentSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class SheetContainerComponent: CombinedComponent {
|
||||||
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
|
let context: AccountContext
|
||||||
|
let gifts: [ProfileGiftsContext.State.StarGift]
|
||||||
|
let completion: (StarGiftReference) -> Void
|
||||||
|
|
||||||
|
init(
|
||||||
|
context: AccountContext,
|
||||||
|
gifts: [ProfileGiftsContext.State.StarGift],
|
||||||
|
completion: @escaping (StarGiftReference) -> Void
|
||||||
|
) {
|
||||||
|
self.context = context
|
||||||
|
self.gifts = gifts
|
||||||
|
self.completion = completion
|
||||||
|
}
|
||||||
|
|
||||||
|
static func ==(lhs: SheetContainerComponent, rhs: SheetContainerComponent) -> Bool {
|
||||||
|
if lhs.context !== rhs.context {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.gifts != rhs.gifts {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
static var body: Body {
|
||||||
|
let sheet = Child(SheetComponent<EnvironmentType>.self)
|
||||||
|
let animateOut = StoredActionSlot(Action<Void>.self)
|
||||||
|
|
||||||
|
let sheetExternalState = SheetComponent<EnvironmentType>.ExternalState()
|
||||||
|
|
||||||
|
return { context in
|
||||||
|
let environment = context.environment[EnvironmentType.self]
|
||||||
|
|
||||||
|
let controller = environment.controller
|
||||||
|
|
||||||
|
let sheet = sheet.update(
|
||||||
|
component: SheetComponent<EnvironmentType>(
|
||||||
|
content: AnyComponent<EnvironmentType>(SheetContent(
|
||||||
|
context: context.component.context,
|
||||||
|
gifts: context.component.gifts,
|
||||||
|
completion: context.component.completion,
|
||||||
|
dismiss: {
|
||||||
|
animateOut.invoke(Action { _ in
|
||||||
|
if let controller = controller() {
|
||||||
|
controller.dismiss(completion: nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)),
|
||||||
|
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
|
||||||
|
followContentSizeChanges: true,
|
||||||
|
externalState: sheetExternalState,
|
||||||
|
animateOut: animateOut
|
||||||
|
),
|
||||||
|
environment: {
|
||||||
|
environment
|
||||||
|
SheetComponentEnvironment(
|
||||||
|
isDisplaying: environment.value.isVisible,
|
||||||
|
isCentered: environment.metrics.widthClass == .regular,
|
||||||
|
hasInputHeight: !environment.inputHeight.isZero,
|
||||||
|
regularMetricsSize: CGSize(width: 430.0, height: 900.0),
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
availableSize: context.availableSize,
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
|
||||||
|
context.add(sheet
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
if let controller = controller(), !controller.automaticallyControlPresentationContextLayout {
|
||||||
|
let layout = ContainerViewLayout(
|
||||||
|
size: context.availableSize,
|
||||||
|
metrics: environment.metrics,
|
||||||
|
deviceMetrics: environment.deviceMetrics,
|
||||||
|
intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: max(environment.safeInsets.bottom, sheetExternalState.contentHeight), right: 0.0),
|
||||||
|
safeInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
|
||||||
|
additionalInsets: .zero,
|
||||||
|
statusBarHeight: environment.statusBarHeight,
|
||||||
|
inputHeight: nil,
|
||||||
|
inputHeightIsInteractivellyChanging: false,
|
||||||
|
inVoiceOver: false
|
||||||
|
)
|
||||||
|
controller.presentationContext.containerLayoutUpdated(layout, transition: context.transition.containedViewLayoutTransition)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.availableSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class GiftUnpinScreen: ViewControllerComponentContainer {
|
||||||
|
private let context: AccountContext
|
||||||
|
private let gifts: [ProfileGiftsContext.State.StarGift]
|
||||||
|
private let completion: (StarGiftReference) -> Void
|
||||||
|
|
||||||
|
public init(
|
||||||
|
context: AccountContext,
|
||||||
|
gifts: [ProfileGiftsContext.State.StarGift],
|
||||||
|
completion: @escaping (StarGiftReference) -> Void
|
||||||
|
) {
|
||||||
|
self.context = context
|
||||||
|
self.gifts = gifts
|
||||||
|
self.completion = completion
|
||||||
|
|
||||||
|
super.init(
|
||||||
|
context: context,
|
||||||
|
component: SheetContainerComponent(
|
||||||
|
context: context,
|
||||||
|
gifts: gifts,
|
||||||
|
completion: completion
|
||||||
|
),
|
||||||
|
navigationBarAppearance: .none,
|
||||||
|
statusBarStyle: .ignore,
|
||||||
|
theme: .default
|
||||||
|
)
|
||||||
|
|
||||||
|
self.navigationPresentation = .flatModal
|
||||||
|
}
|
||||||
|
|
||||||
|
required public init(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func dismissAnimated() {
|
||||||
|
if let view = self.node.hostView.findTaggedView(tag: SheetComponent<ViewControllerComponentContainer.Environment>.View.Tag()) as? SheetComponent<ViewControllerComponentContainer.Environment>.View {
|
||||||
|
view.dismissAnimated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3007,12 +3007,6 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
self.subject = .profileGift(peerId, gift.withPinnedToTop(false))
|
self.subject = .profileGift(peerId, gift.withPinnedToTop(false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
var maxPinnedCount: Int = 6
|
|
||||||
if let value = context.currentAppConfiguration.with({ $0 }).data?["stargifts_pinned_to_top_limit"] as? Double {
|
|
||||||
maxPinnedCount = Int(value)
|
|
||||||
}
|
|
||||||
self.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: strings.PeerInfo_Gifts_ToastPinLimit_Text(Int32(maxPinnedCount)), timeout: nil, customUndoText: nil), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})))
|
})))
|
||||||
|
@ -18,12 +18,14 @@ public final class ListActionItemComponent: Component {
|
|||||||
public var style: ToggleStyle
|
public var style: ToggleStyle
|
||||||
public var isOn: Bool
|
public var isOn: Bool
|
||||||
public var isInteractive: Bool
|
public var isInteractive: Bool
|
||||||
|
public var isEnabled: Bool
|
||||||
public var action: ((Bool) -> Void)?
|
public var action: ((Bool) -> Void)?
|
||||||
|
|
||||||
public init(style: ToggleStyle, isOn: Bool, isInteractive: Bool = true, action: ((Bool) -> Void)? = nil) {
|
public init(style: ToggleStyle, isOn: Bool, isInteractive: Bool = true, isEnabled: Bool = true, action: ((Bool) -> Void)? = nil) {
|
||||||
self.style = style
|
self.style = style
|
||||||
self.isOn = isOn
|
self.isOn = isOn
|
||||||
self.isInteractive = isInteractive
|
self.isInteractive = isInteractive
|
||||||
|
self.isEnabled = isEnabled
|
||||||
self.action = action
|
self.action = action
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +39,9 @@ public final class ListActionItemComponent: Component {
|
|||||||
if lhs.isInteractive != rhs.isInteractive {
|
if lhs.isInteractive != rhs.isInteractive {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isEnabled != rhs.isEnabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (lhs.action == nil) != (rhs.action == nil) {
|
if (lhs.action == nil) != (rhs.action == nil) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -648,7 +653,9 @@ public final class ListActionItemComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switchNode.isUserInteractionEnabled = toggle.isInteractive
|
switchNode.isUserInteractionEnabled = toggle.isInteractive && toggle.isEnabled
|
||||||
|
switchNode.alpha = toggle.isEnabled ? 1.0 : 0.3
|
||||||
|
switchNode.layer.allowsGroupOpacity = !toggle.isEnabled
|
||||||
|
|
||||||
if updateSwitchTheme {
|
if updateSwitchTheme {
|
||||||
switchNode.frameColor = component.theme.list.itemSwitchColors.frameColor
|
switchNode.frameColor = component.theme.list.itemSwitchColors.frameColor
|
||||||
|
@ -187,7 +187,7 @@ public final class LoadingOverlayNode: ASDisplayNode {
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -548,7 +548,7 @@ private final class PeerInfoScreenPersonalChannelItemNode: PeerInfoScreenItemNod
|
|||||||
},
|
},
|
||||||
openPhotoSetup: {
|
openPhotoSetup: {
|
||||||
},
|
},
|
||||||
openAdInfo: { _ in
|
openAdInfo: { _, _ in
|
||||||
},
|
},
|
||||||
openAccountFreezeInfo: {
|
openAccountFreezeInfo: {
|
||||||
}
|
}
|
||||||
|
@ -540,14 +540,18 @@ private final class PeerInfoPendingPane {
|
|||||||
switch key {
|
switch key {
|
||||||
case .gifts:
|
case .gifts:
|
||||||
var canManage = false
|
var canManage = false
|
||||||
|
var canGift = true
|
||||||
if let peer = data.peer {
|
if let peer = data.peer {
|
||||||
|
if let cachedUserData = data.cachedData as? CachedUserData, cachedUserData.disallowedGifts == .All {
|
||||||
|
canGift = false
|
||||||
|
}
|
||||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||||
if channel.hasPermission(.sendSomething) {
|
if channel.hasPermission(.sendSomething) {
|
||||||
canManage = true
|
canManage = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paneNode = PeerInfoGiftsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, profileGifts: data.profileGiftsContext!, canManage: canManage)
|
paneNode = PeerInfoGiftsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, profileGifts: data.profileGiftsContext!, canManage: canManage, canGift: canGift)
|
||||||
case .stories, .storyArchive, .botPreview:
|
case .stories, .storyArchive, .botPreview:
|
||||||
var canManage = false
|
var canManage = false
|
||||||
if let peer = data.peer {
|
if let peer = data.peer {
|
||||||
|
@ -6435,15 +6435,18 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser, !user.isDeleted && user.botInfo == nil && !user.flags.contains(.isSupport) {
|
if strongSelf.peerId.namespace == Namespaces.Peer.CloudUser, !user.isDeleted && user.botInfo == nil && !user.flags.contains(.isSupport) {
|
||||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Profile_SendGift, icon: { theme in
|
if let cachedData = data.cachedData as? CachedUserData, cachedData.disallowedGifts == .All {
|
||||||
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Gift"), color: theme.contextMenu.primaryColor)
|
} else {
|
||||||
}, action: { [weak self] _, f in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Profile_SendGift, icon: { theme in
|
||||||
f(.dismissWithoutContent)
|
generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Gift"), color: theme.contextMenu.primaryColor)
|
||||||
|
}, action: { [weak self] _, f in
|
||||||
if let self {
|
f(.dismissWithoutContent)
|
||||||
self.openPremiumGift()
|
|
||||||
}
|
if let self {
|
||||||
})))
|
self.openPremiumGift()
|
||||||
|
}
|
||||||
|
})))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let cachedData = data.cachedData as? CachedUserData, cachedData.flags.contains(.translationHidden) {
|
if let cachedData = data.cachedData as? CachedUserData, cachedData.flags.contains(.translationHidden) {
|
||||||
|
@ -33,6 +33,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let profileGifts: ProfileGiftsContext
|
private let profileGifts: ProfileGiftsContext
|
||||||
private let canManage: Bool
|
private let canManage: Bool
|
||||||
|
private let canGift: Bool
|
||||||
|
|
||||||
private var dataDisposable: Disposable?
|
private var dataDisposable: Disposable?
|
||||||
|
|
||||||
@ -101,12 +102,13 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
private let maxPinnedCount: Int
|
private let maxPinnedCount: Int
|
||||||
|
|
||||||
public init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, profileGifts: ProfileGiftsContext, canManage: Bool) {
|
public init(context: AccountContext, peerId: PeerId, chatControllerInteraction: ChatControllerInteraction, profileGifts: ProfileGiftsContext, canManage: Bool, canGift: Bool) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.chatControllerInteraction = chatControllerInteraction
|
self.chatControllerInteraction = chatControllerInteraction
|
||||||
self.profileGifts = profileGifts
|
self.profileGifts = profileGifts
|
||||||
self.canManage = canManage
|
self.canManage = canManage
|
||||||
|
self.canGift = canGift
|
||||||
|
|
||||||
self.backgroundNode = ASDisplayNode()
|
self.backgroundNode = ASDisplayNode()
|
||||||
self.scrollNode = ASScrollNode()
|
self.scrollNode = ASScrollNode()
|
||||||
@ -434,6 +436,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
|
|
||||||
let ribbonText: String?
|
let ribbonText: String?
|
||||||
var ribbonColor: GiftItemComponent.Ribbon.Color = .blue
|
var ribbonColor: GiftItemComponent.Ribbon.Color = .blue
|
||||||
|
var ribbonFont: GiftItemComponent.Ribbon.Font = .generic
|
||||||
switch product.gift {
|
switch product.gift {
|
||||||
case let .generic(gift):
|
case let .generic(gift):
|
||||||
if let availability = gift.availability {
|
if let availability = gift.availability {
|
||||||
@ -442,7 +445,8 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
ribbonText = nil
|
ribbonText = nil
|
||||||
}
|
}
|
||||||
case let .unique(gift):
|
case let .unique(gift):
|
||||||
ribbonText = params.presentationData.strings.PeerInfo_Gifts_OneOf(compactNumericCountString(Int(gift.availability.issued), decimalSeparator: params.presentationData.dateTimeFormat.decimalSeparator)).string
|
ribbonFont = .monospaced
|
||||||
|
ribbonText = "#\(gift.number)"
|
||||||
for attribute in gift.attributes {
|
for attribute in gift.attributes {
|
||||||
if case let .backdrop(_, innerColor, outerColor, _, _, _) = attribute {
|
if case let .backdrop(_, innerColor, outerColor, _, _, _) = attribute {
|
||||||
ribbonColor = .custom(outerColor, innerColor)
|
ribbonColor = .custom(outerColor, innerColor)
|
||||||
@ -471,7 +475,7 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
strings: params.presentationData.strings,
|
strings: params.presentationData.strings,
|
||||||
peer: peer,
|
peer: peer,
|
||||||
subject: subject,
|
subject: subject,
|
||||||
ribbon: ribbonText.flatMap { GiftItemComponent.Ribbon(text: $0, color: ribbonColor) },
|
ribbon: ribbonText.flatMap { GiftItemComponent.Ribbon(text: $0, font: ribbonFont, color: ribbonColor) },
|
||||||
isHidden: !product.savedToProfile,
|
isHidden: !product.savedToProfile,
|
||||||
isPinned: product.pinnedToTop,
|
isPinned: product.pinnedToTop,
|
||||||
isEditing: self.isReordering,
|
isEditing: self.isReordering,
|
||||||
@ -542,6 +546,19 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if pinnedToTop && self.pinnedReferences.count >= self.maxPinnedCount {
|
if pinnedToTop && self.pinnedReferences.count >= self.maxPinnedCount {
|
||||||
|
if let gifts = self.profileGifts.currentState?.gifts.filter({ $0.pinnedToTop }) {
|
||||||
|
let controller = GiftUnpinScreen(
|
||||||
|
context: context,
|
||||||
|
gifts: gifts,
|
||||||
|
completion: { [weak self] reference in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.profileGifts.updateStarGiftPinnedToTop(reference: reference, pinnedToTop: false)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.parentController?.push(controller)
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if let reference = product.reference {
|
if let reference = product.reference {
|
||||||
@ -657,7 +674,10 @@ public final class PeerInfoGiftsPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
let panelSeparator: ASDisplayNode
|
let panelSeparator: ASDisplayNode
|
||||||
let panelButton: SolidRoundedButtonNode
|
let panelButton: SolidRoundedButtonNode
|
||||||
|
|
||||||
let panelAlpha = params.expandProgress
|
var panelAlpha = params.expandProgress
|
||||||
|
if !self.canGift {
|
||||||
|
panelAlpha = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
if let current = self.panelBackground {
|
if let current = self.panelBackground {
|
||||||
panelBackground = current
|
panelBackground = current
|
||||||
|
@ -212,7 +212,7 @@ final class GreetingMessageListItemComponent: Component {
|
|||||||
},
|
},
|
||||||
openPhotoSetup: {
|
openPhotoSetup: {
|
||||||
},
|
},
|
||||||
openAdInfo: { _ in
|
openAdInfo: { _, _ in
|
||||||
},
|
},
|
||||||
openAccountFreezeInfo: {
|
openAccountFreezeInfo: {
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ final class QuickReplySetupScreenComponent: Component {
|
|||||||
},
|
},
|
||||||
openPhotoSetup: {
|
openPhotoSetup: {
|
||||||
},
|
},
|
||||||
openAdInfo: { _ in
|
openAdInfo: { _, _ in
|
||||||
},
|
},
|
||||||
openAccountFreezeInfo: {
|
openAccountFreezeInfo: {
|
||||||
}
|
}
|
||||||
|
@ -112,14 +112,24 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
|
|
||||||
final class Permission {
|
final class Permission {
|
||||||
var id: String
|
var id: String
|
||||||
|
var key: TelegramBusinessBotRights?
|
||||||
var title: String
|
var title: String
|
||||||
var value: Bool?
|
var value: Bool?
|
||||||
var enabled: Bool
|
var enabled: Bool
|
||||||
var subpermissions: [Permission]?
|
var subpermissions: [Permission]?
|
||||||
var expanded: Bool?
|
var expanded: Bool?
|
||||||
|
|
||||||
init(id: String, title: String, value: Bool? = nil, enabled: Bool = true, subpermissions: [Permission]? = nil, expanded: Bool? = nil) {
|
init(
|
||||||
|
id: String,
|
||||||
|
key: TelegramBusinessBotRights? = nil,
|
||||||
|
title: String,
|
||||||
|
value: Bool? = nil,
|
||||||
|
enabled: Bool = true,
|
||||||
|
subpermissions: [Permission]? = nil,
|
||||||
|
expanded: Bool? = nil
|
||||||
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
|
self.key = key
|
||||||
self.title = title
|
self.title = title
|
||||||
self.value = value
|
self.value = value
|
||||||
self.enabled = enabled
|
self.enabled = enabled
|
||||||
@ -162,7 +172,6 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private var permissions: [Permission] = []
|
private var permissions: [Permission] = []
|
||||||
|
|
||||||
private var botRights: TelegramBusinessBotRights = []
|
private var botRights: TelegramBusinessBotRights = []
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
@ -184,30 +193,6 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
self.addSubview(self.scrollView)
|
self.addSubview(self.scrollView)
|
||||||
|
|
||||||
self.scrollView.layer.addSublayer(self.topOverscrollLayer)
|
self.scrollView.layer.addSublayer(self.topOverscrollLayer)
|
||||||
|
|
||||||
self.permissions = [
|
|
||||||
Permission(id: "message", title: "Manage Messages", subpermissions: [
|
|
||||||
Permission(id: "read", title: "Read Messages", value: true, enabled: false),
|
|
||||||
Permission(id: "reply", title: "Reply to Messages", value: true),
|
|
||||||
Permission(id: "mark", title: "Mark Messages as Read", value: true),
|
|
||||||
Permission(id: "deleteSent", title: "Delete Sent Messages", value: true),
|
|
||||||
Permission(id: "deleteReceived", title: "Delete Received Messages", value: true)
|
|
||||||
], expanded: false),
|
|
||||||
Permission(id: "profile", title: "Manage Profile", subpermissions: [
|
|
||||||
Permission(id: "name", title: "Edit Name", value: true),
|
|
||||||
Permission(id: "bio", title: "Edit Bio", value: true),
|
|
||||||
Permission(id: "avatar", title: "Edit Profile Picture", value: true),
|
|
||||||
Permission(id: "username", title: "Edit Username", value: true)
|
|
||||||
], expanded: false),
|
|
||||||
Permission(id: "gifts", title: "Manage Gifts and Stars", subpermissions: [
|
|
||||||
Permission(id: "view", title: "View Gifts", value: true),
|
|
||||||
Permission(id: "sell", title: "Sell Gifts", value: true),
|
|
||||||
Permission(id: "settings", title: "Change Gift Settings", value: true),
|
|
||||||
Permission(id: "transfer", title: "Transfer and Upgrade Gifts", value: true),
|
|
||||||
Permission(id: "transferStars", title: "Transfer Stars", value: true)
|
|
||||||
], expanded: false),
|
|
||||||
Permission(id: "stories", title: "Manage Stories", value: true)
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
@ -250,7 +235,7 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
let _ = component.context.engine.accountData.setAccountConnectedBot(bot: TelegramAccountConnectedBot(
|
let _ = component.context.engine.accountData.setAccountConnectedBot(bot: TelegramAccountConnectedBot(
|
||||||
id: peer.id,
|
id: peer.id,
|
||||||
recipients: recipients,
|
recipients: recipients,
|
||||||
rights: []
|
rights: self.botRights
|
||||||
)).startStandalone()
|
)).startStandalone()
|
||||||
} else {
|
} else {
|
||||||
let _ = component.context.engine.accountData.setAccountConnectedBot(bot: nil).startStandalone()
|
let _ = component.context.engine.accountData.setAccountConnectedBot(bot: nil).startStandalone()
|
||||||
@ -526,13 +511,17 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
self.isUpdating = false
|
self.isUpdating = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let environment = environment[EnvironmentType.self].value
|
||||||
|
let themeUpdated = self.environment?.theme !== environment.theme
|
||||||
|
self.environment = environment
|
||||||
|
|
||||||
if self.component == nil {
|
if self.component == nil {
|
||||||
if let bot = component.initialData.bot, let botPeer = component.initialData.botPeer, let addressName = botPeer.addressName {
|
if let bot = component.initialData.bot, let botPeer = component.initialData.botPeer, let addressName = botPeer.addressName {
|
||||||
self.botResolutionState = BotResolutionState(query: addressName, state: .found(peer: botPeer, isInstalled: true))
|
self.botResolutionState = BotResolutionState(query: addressName, state: .found(peer: botPeer, isInstalled: true))
|
||||||
self.resetQueryText = addressName.lowercased()
|
self.resetQueryText = addressName.lowercased()
|
||||||
|
|
||||||
self.botRights = bot.rights
|
self.botRights = bot.rights
|
||||||
|
|
||||||
let initialRecipients = bot.recipients
|
let initialRecipients = bot.recipients
|
||||||
|
|
||||||
var mappedCategories = Set<AdditionalPeerList.Category>()
|
var mappedCategories = Set<AdditionalPeerList.Category>()
|
||||||
@ -571,12 +560,32 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
|
|
||||||
self.hasAccessToAllChatsByDefault = initialRecipients.exclude
|
self.hasAccessToAllChatsByDefault = initialRecipients.exclude
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.permissions = [
|
||||||
|
Permission(id: "message", title: environment.strings.ChatbotSetup_Rights_ManageMessages, subpermissions: [
|
||||||
|
Permission(id: "read", title: environment.strings.ChatbotSetup_Rights_ReadMessages, value: true, enabled: false),
|
||||||
|
Permission(id: "reply", key: .reply, title: environment.strings.ChatbotSetup_Rights_ReplyToMessages),
|
||||||
|
Permission(id: "mark", key: .readMessages, title: environment.strings.ChatbotSetup_Rights_MarkAsRead),
|
||||||
|
Permission(id: "deleteSent", key: .deleteSentMessages, title: environment.strings.ChatbotSetup_Rights_DeleteSentMessages),
|
||||||
|
Permission(id: "deleteReceived", key: .deleteReceivedMessages, title: environment.strings.ChatbotSetup_Rights_DeleteReceivedMessages)
|
||||||
|
], expanded: false),
|
||||||
|
Permission(id: "profile", title: environment.strings.ChatbotSetup_Rights_ManageProfile, subpermissions: [
|
||||||
|
Permission(id: "name", key: .editName, title: environment.strings.ChatbotSetup_Rights_EditName),
|
||||||
|
Permission(id: "bio", key: .editBio, title: environment.strings.ChatbotSetup_Rights_EditBio),
|
||||||
|
Permission(id: "avatar", key: .editProfilePhoto, title: environment.strings.ChatbotSetup_Rights_EditProfilePhoto),
|
||||||
|
Permission(id: "username", key: .editUsername, title: environment.strings.ChatbotSetup_Rights_EditUsername)
|
||||||
|
], expanded: false),
|
||||||
|
Permission(id: "gifts", title: environment.strings.ChatbotSetup_Rights_ManageGiftsAndStars, subpermissions: [
|
||||||
|
Permission(id: "view", key: .viewGifts, title: environment.strings.ChatbotSetup_Rights_ViewGifts),
|
||||||
|
Permission(id: "sell", key: .sellGifts, title: environment.strings.ChatbotSetup_Rights_SellGifts),
|
||||||
|
Permission(id: "settings", key: .changeGiftSettings, title: environment.strings.ChatbotSetup_Rights_ChangeGiftSettings),
|
||||||
|
Permission(id: "transfer", key: .transferAndUpgradeGifts, title: environment.strings.ChatbotSetup_Rights_TransferAndUpgradeGifts),
|
||||||
|
Permission(id: "transferStars", key: .transferStars, title: environment.strings.ChatbotSetup_Rights_TransferStars)
|
||||||
|
], expanded: false),
|
||||||
|
Permission(id: "stories", key: .manageStories, title: environment.strings.ChatbotSetup_Rights_ManageStories)
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
let environment = environment[EnvironmentType.self].value
|
|
||||||
let themeUpdated = self.environment?.theme !== environment.theme
|
|
||||||
self.environment = environment
|
|
||||||
|
|
||||||
self.component = component
|
self.component = component
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
@ -732,6 +741,7 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
if case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.isBusiness) {
|
if case let .user(user) = peer, let botInfo = user.botInfo, botInfo.flags.contains(.isBusiness) {
|
||||||
botResolutionState.state = .found(peer: peer, isInstalled: true)
|
botResolutionState.state = .found(peer: peer, isInstalled: true)
|
||||||
self.botResolutionState = botResolutionState
|
self.botResolutionState = botResolutionState
|
||||||
|
self.botRights = .All
|
||||||
self.state?.updated(transition: .spring(duration: 0.3))
|
self.state?.updated(transition: .spring(duration: 0.3))
|
||||||
} else {
|
} else {
|
||||||
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.ChatbotSetup_ErrorBotNotBusinessCapable, actions: [
|
self.environment?.controller()?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: presentationData.strings.ChatbotSetup_ErrorBotNotBusinessCapable, actions: [
|
||||||
@ -1027,158 +1037,192 @@ final class ChatbotSetupScreenComponent: Component {
|
|||||||
if !self.hasAccessToAllChatsByDefault {
|
if !self.hasAccessToAllChatsByDefault {
|
||||||
contentHeight += excludedUsersContentHeight
|
contentHeight += excludedUsersContentHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
var permissionsItems: [AnyComponentWithIdentity<Empty>] = []
|
|
||||||
|
|
||||||
for permission in self.permissions {
|
if case .found(_, true) = self.botResolutionState?.state {
|
||||||
var value = permission.value == true
|
var permissionsItems: [AnyComponentWithIdentity<Empty>] = []
|
||||||
|
for permission in self.permissions {
|
||||||
var titleItems: [AnyComponentWithIdentity<Empty>] = []
|
var value: Bool
|
||||||
titleItems.append(
|
if let key = permission.key {
|
||||||
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
|
value = self.botRights.contains(key)
|
||||||
text: .plain(NSAttributedString(
|
} else {
|
||||||
string: permission.title,
|
value = permission.value == true
|
||||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
|
||||||
textColor: environment.theme.list.itemPrimaryTextColor
|
|
||||||
)),
|
|
||||||
maximumNumberOfLines: 1
|
|
||||||
)))
|
|
||||||
)
|
|
||||||
|
|
||||||
if let subpermissions = permission.subpermissions {
|
|
||||||
value = false
|
|
||||||
var selectedCount = 0
|
|
||||||
for subpermission in subpermissions {
|
|
||||||
if subpermission.value == true {
|
|
||||||
value = true
|
|
||||||
selectedCount += 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var titleItems: [AnyComponentWithIdentity<Empty>] = []
|
||||||
titleItems.append(
|
titleItems.append(
|
||||||
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
|
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: "\(selectedCount)/\(subpermissions.count)",
|
string: permission.title,
|
||||||
font: Font.with(size: presentationData.listsFontSize.baseDisplaySize / 17.0 * 13.0, design: .round, weight: .semibold),
|
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||||
textColor: environment.theme.list.itemPrimaryTextColor
|
textColor: environment.theme.list.itemPrimaryTextColor
|
||||||
)),
|
)),
|
||||||
maximumNumberOfLines: 1
|
maximumNumberOfLines: 1
|
||||||
)))
|
)))
|
||||||
)
|
)
|
||||||
titleItems.append(
|
|
||||||
AnyComponentWithIdentity(id: AnyHashable(2), component: AnyComponent(BundleIconComponent(
|
if let subpermissions = permission.subpermissions {
|
||||||
name: "Item List/ExpandingItemVerticalRegularArrow",
|
value = false
|
||||||
tintColor: environment.theme.list.itemPrimaryTextColor,
|
var selectedCount = 0
|
||||||
flipVertically: permission.expanded == true
|
for subpermission in subpermissions {
|
||||||
)))
|
if subpermission.value == true {
|
||||||
)
|
value = true
|
||||||
}
|
selectedCount += 1
|
||||||
permissionsItems.append(
|
|
||||||
AnyComponentWithIdentity(id: permission.id, component: AnyComponent(ListActionItemComponent(
|
|
||||||
theme: environment.theme,
|
|
||||||
title: AnyComponent(HStack(titleItems, spacing: 6.0)),
|
|
||||||
accessory: .toggle(ListActionItemComponent.Toggle(style: .icons, isOn: value, action: { [weak self] value in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if let subpermissions = permission.subpermissions {
|
}
|
||||||
for subpermission in subpermissions {
|
titleItems.append(
|
||||||
if subpermission.enabled {
|
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
|
||||||
subpermission.value = value
|
text: .plain(NSAttributedString(
|
||||||
}
|
string: "\(selectedCount)/\(subpermissions.count)",
|
||||||
}
|
font: Font.with(size: presentationData.listsFontSize.baseDisplaySize / 17.0 * 13.0, design: .round, weight: .semibold),
|
||||||
} else if let value = permission.value {
|
textColor: environment.theme.list.itemPrimaryTextColor
|
||||||
permission.value = value
|
)),
|
||||||
}
|
maximumNumberOfLines: 1
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
)))
|
||||||
})),
|
)
|
||||||
action: permission.subpermissions != nil ? { [weak self] _ in
|
titleItems.append(
|
||||||
guard let self else {
|
AnyComponentWithIdentity(id: AnyHashable(2), component: AnyComponent(BundleIconComponent(
|
||||||
return
|
name: "Item List/ExpandingItemVerticalRegularArrow",
|
||||||
}
|
tintColor: environment.theme.list.itemPrimaryTextColor,
|
||||||
var scrollToBottom = false
|
flipVertically: permission.expanded == true
|
||||||
if let expanded = permission.expanded {
|
|
||||||
permission.expanded = !expanded
|
|
||||||
if !expanded {
|
|
||||||
scrollToBottom = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
|
||||||
if scrollToBottom {
|
|
||||||
self.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.scrollView.contentSize.height - self.scrollView.bounds.height), animated: true)
|
|
||||||
}
|
|
||||||
} : nil
|
|
||||||
)))
|
|
||||||
)
|
|
||||||
|
|
||||||
if let subpermissions = permission.subpermissions, permission.expanded == true {
|
|
||||||
for subpermission in subpermissions {
|
|
||||||
permissionsItems.append(
|
|
||||||
AnyComponentWithIdentity(id: subpermission.id, component: AnyComponent(ListActionItemComponent(
|
|
||||||
theme: environment.theme,
|
|
||||||
title: AnyComponent(VStack([
|
|
||||||
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
|
|
||||||
text: .plain(NSAttributedString(
|
|
||||||
string: subpermission.title,
|
|
||||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
|
||||||
textColor: environment.theme.list.itemPrimaryTextColor
|
|
||||||
)),
|
|
||||||
maximumNumberOfLines: 1
|
|
||||||
))),
|
|
||||||
], alignment: .left, spacing: 2.0)),
|
|
||||||
leftIcon: .check(ListActionItemComponent.LeftIcon.Check(isSelected: subpermission.value == true, isEnabled: subpermission.enabled, toggle: nil)),
|
|
||||||
accessory: nil,
|
|
||||||
action: subpermission.enabled ? { [weak self] _ in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if let value = subpermission.value {
|
|
||||||
subpermission.value = !value
|
|
||||||
}
|
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
|
||||||
} : nil
|
|
||||||
)))
|
)))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
//permissionsItems.append(AnyComponentWithIdentity(id: "\(permission.id)_sub", component: AnyComponent(VStack(stackItems, spacing: 0.0))))
|
permissionsItems.append(
|
||||||
|
AnyComponentWithIdentity(id: permission.id, component: AnyComponent(ListActionItemComponent(
|
||||||
|
theme: environment.theme,
|
||||||
|
title: AnyComponent(HStack(titleItems, spacing: 6.0)),
|
||||||
|
accessory: .toggle(ListActionItemComponent.Toggle(style: .icons, isOn: value, action: { [weak self] value in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let subpermissions = permission.subpermissions {
|
||||||
|
for subpermission in subpermissions {
|
||||||
|
if subpermission.enabled {
|
||||||
|
if let key = subpermission.key {
|
||||||
|
if value {
|
||||||
|
self.botRights.insert(key)
|
||||||
|
} else {
|
||||||
|
self.botRights.remove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let key = permission.key {
|
||||||
|
if value {
|
||||||
|
self.botRights.insert(key)
|
||||||
|
} else {
|
||||||
|
self.botRights.remove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
|
})),
|
||||||
|
action: permission.subpermissions != nil ? { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var scrollToBottom = false
|
||||||
|
if let expanded = permission.expanded {
|
||||||
|
permission.expanded = !expanded
|
||||||
|
if !expanded {
|
||||||
|
scrollToBottom = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
|
if scrollToBottom {
|
||||||
|
self.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.scrollView.contentSize.height - self.scrollView.bounds.height), animated: true)
|
||||||
|
}
|
||||||
|
} : nil
|
||||||
|
)))
|
||||||
|
)
|
||||||
|
|
||||||
|
if let subpermissions = permission.subpermissions, permission.expanded == true {
|
||||||
|
for subpermission in subpermissions {
|
||||||
|
var value = false
|
||||||
|
if let key = permission.key {
|
||||||
|
value = self.botRights.contains(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
permissionsItems.append(
|
||||||
|
AnyComponentWithIdentity(id: subpermission.id, component: AnyComponent(ListActionItemComponent(
|
||||||
|
theme: environment.theme,
|
||||||
|
title: AnyComponent(VStack([
|
||||||
|
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(
|
||||||
|
string: subpermission.title,
|
||||||
|
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
||||||
|
textColor: environment.theme.list.itemPrimaryTextColor
|
||||||
|
)),
|
||||||
|
maximumNumberOfLines: 1
|
||||||
|
))),
|
||||||
|
], alignment: .left, spacing: 2.0)),
|
||||||
|
leftIcon: .check(ListActionItemComponent.LeftIcon.Check(isSelected: value, isEnabled: subpermission.enabled, toggle: nil)),
|
||||||
|
accessory: nil,
|
||||||
|
action: subpermission.enabled ? { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let key = subpermission.key {
|
||||||
|
if !value {
|
||||||
|
self.botRights.insert(key)
|
||||||
|
} else {
|
||||||
|
self.botRights.remove(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
|
} : nil
|
||||||
|
)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
//permissionsItems.append(AnyComponentWithIdentity(id: "\(permission.id)_sub", component: AnyComponent(VStack(stackItems, spacing: 0.0))))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
var permissionsTransition = transition
|
||||||
|
if self.permissionsSection.view?.superview == nil {
|
||||||
|
permissionsTransition = .immediate
|
||||||
|
|
||||||
let permissionsSectionSize = self.permissionsSection.update(
|
|
||||||
transition: transition,
|
|
||||||
component: AnyComponent(ListSectionComponent(
|
|
||||||
theme: environment.theme,
|
|
||||||
header: AnyComponent(MultilineTextComponent(
|
|
||||||
text: .plain(NSAttributedString(
|
|
||||||
string: environment.strings.ChatbotSetup_PermissionsSectionHeader,
|
|
||||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
|
||||||
textColor: environment.theme.list.freeTextColor
|
|
||||||
)),
|
|
||||||
maximumNumberOfLines: 0
|
|
||||||
)),
|
|
||||||
footer: AnyComponent(MultilineTextComponent(
|
|
||||||
text: .plain(NSAttributedString(
|
|
||||||
string: environment.strings.ChatbotSetup_PermissionsSectionFooter,
|
|
||||||
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
|
||||||
textColor: environment.theme.list.freeTextColor
|
|
||||||
)),
|
|
||||||
maximumNumberOfLines: 0
|
|
||||||
)),
|
|
||||||
items: permissionsItems
|
|
||||||
)),
|
|
||||||
environment: {},
|
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 10000.0)
|
|
||||||
)
|
|
||||||
let permissionsSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: permissionsSectionSize)
|
|
||||||
if let permissionsSectionView = self.permissionsSection.view {
|
|
||||||
if permissionsSectionView.superview == nil {
|
|
||||||
self.scrollView.addSubview(permissionsSectionView)
|
|
||||||
}
|
}
|
||||||
transition.setFrame(view: permissionsSectionView, frame: permissionsSectionFrame)
|
|
||||||
|
let permissionsSectionSize = self.permissionsSection.update(
|
||||||
|
transition: permissionsTransition,
|
||||||
|
component: AnyComponent(ListSectionComponent(
|
||||||
|
theme: environment.theme,
|
||||||
|
header: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(
|
||||||
|
string: environment.strings.ChatbotSetup_PermissionsSectionHeader,
|
||||||
|
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||||
|
textColor: environment.theme.list.freeTextColor
|
||||||
|
)),
|
||||||
|
maximumNumberOfLines: 0
|
||||||
|
)),
|
||||||
|
footer: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(
|
||||||
|
string: environment.strings.ChatbotSetup_PermissionsSectionFooter,
|
||||||
|
font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize),
|
||||||
|
textColor: environment.theme.list.freeTextColor
|
||||||
|
)),
|
||||||
|
maximumNumberOfLines: 0
|
||||||
|
)),
|
||||||
|
items: permissionsItems
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 10000.0)
|
||||||
|
)
|
||||||
|
let permissionsSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: permissionsSectionSize)
|
||||||
|
if let permissionsSectionView = self.permissionsSection.view {
|
||||||
|
if permissionsSectionView.superview == nil {
|
||||||
|
self.scrollView.addSubview(permissionsSectionView)
|
||||||
|
|
||||||
|
permissionsSectionView.alpha = 1.0
|
||||||
|
transition.animateAlpha(view: permissionsSectionView, from: 0.0, to: 1.0)
|
||||||
|
}
|
||||||
|
permissionsTransition.setFrame(view: permissionsSectionView, frame: permissionsSectionFrame)
|
||||||
|
}
|
||||||
|
contentHeight += permissionsSectionSize.height
|
||||||
|
} else if let permissionsSectionView = self.permissionsSection.view {
|
||||||
|
transition.setAlpha(view: permissionsSectionView, alpha: 0.0, completion: { _ in
|
||||||
|
permissionsSectionView.removeFromSuperview()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
contentHeight += permissionsSectionSize.height
|
|
||||||
|
|
||||||
contentHeight += bottomContentInset
|
contentHeight += bottomContentInset
|
||||||
contentHeight += environment.safeInsets.bottom
|
contentHeight += environment.safeInsets.bottom
|
||||||
|
@ -875,7 +875,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true)
|
||||||
|
@ -9265,8 +9265,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
if let value = value {
|
if let value = value {
|
||||||
self.present(UndoOverlayController(presentationData: self.presentationData, content: .dice(dice: dice, context: self.context, text: value, action: canSendMessagesToChat(self.presentationInterfaceState) ? self.presentationData.strings.Conversation_SendDice : nil), elevatedLayout: false, action: { [weak self] action in
|
self.present(UndoOverlayController(presentationData: self.presentationData, content: .dice(dice: dice, context: self.context, text: value, action: canSendMessagesToChat(self.presentationInterfaceState) ? self.presentationData.strings.Conversation_SendDice : nil), elevatedLayout: false, action: { [weak self] action in
|
||||||
if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState), action == .undo {
|
if let self, canSendMessagesToChat(self.presentationInterfaceState), action == .undo {
|
||||||
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), threadId: strongSelf.chatLocation.threadId, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|
self.presentPaidMessageAlertIfNeeded(completion: { [weak self] postpone in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), threadId: self.chatLocation.threadId, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])], postpone: postpone)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}), in: .current)
|
}), in: .current)
|
||||||
|
@ -559,13 +559,12 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
}, iconSource: nil, action: { _, f in
|
}, iconSource: nil, action: { _, f in
|
||||||
f(.default)
|
f(.default)
|
||||||
|
|
||||||
let _ = (context.engine.messages.reportAdMessage(peerId: message.id.peerId, opaqueId: adAttribute.opaqueId, option: nil)
|
let _ = (context.engine.messages.reportAdMessage(opaqueId: adAttribute.opaqueId, option: nil)
|
||||||
|> deliverOnMainQueue).start(next: { result in
|
|> deliverOnMainQueue).start(next: { result in
|
||||||
if case let .options(title, options) = result {
|
if case let .options(title, options) = result {
|
||||||
controllerInteraction.navigationController()?.pushViewController(
|
controllerInteraction.navigationController()?.pushViewController(
|
||||||
AdsReportScreen(
|
AdsReportScreen(
|
||||||
context: context,
|
context: context,
|
||||||
peerId: message.id.peerId,
|
|
||||||
opaqueId: adAttribute.opaqueId,
|
opaqueId: adAttribute.opaqueId,
|
||||||
title: title,
|
title: title,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -295,7 +295,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, ASScrollViewDe
|
|||||||
}, editPeer: { _ in
|
}, editPeer: { _ in
|
||||||
}, openWebApp: { _ in
|
}, openWebApp: { _ in
|
||||||
}, openPhotoSetup: {
|
}, openPhotoSetup: {
|
||||||
}, openAdInfo: { _ in
|
}, openAdInfo: { _, _ in
|
||||||
}, openAccountFreezeInfo: {
|
}, openAccountFreezeInfo: {
|
||||||
})
|
})
|
||||||
interaction.searchTextHighightState = searchQuery
|
interaction.searchTextHighightState = searchQuery
|
||||||
|
@ -182,7 +182,7 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
|
|||||||
},
|
},
|
||||||
openPhotoSetup: {
|
openPhotoSetup: {
|
||||||
},
|
},
|
||||||
openAdInfo: { _ in
|
openAdInfo: { _, _ in
|
||||||
},
|
},
|
||||||
openAccountFreezeInfo: {
|
openAccountFreezeInfo: {
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user