mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Folder improvements
This commit is contained in:
parent
8d79979422
commit
6c57ab1765
@ -9097,3 +9097,11 @@ Sorry for the inconvenience.";
|
||||
"ChatList.ChatFolderUpdateCount_any" = "%d new chats";
|
||||
"ChatList.ChatFolderUpdateHintTitle" = "You can join %@";
|
||||
"ChatList.ChatFolderUpdateHintText" = "Tap here to view them";
|
||||
|
||||
"Premium.MaxSharedFolderMembershipText" = "You can only add **%1$@** shareable folders. Upgrade to **Telegram Premium** to increase this limit up to **%2$@**.";
|
||||
"Premium.MaxSharedFolderMembershipNoPremiumText" = "You can only add **%1$@** shareable folders. We are working to let you increase this limit in the future.";
|
||||
"Premium.MaxSharedFolderMembershipFinalText" = "Sorry, you can only add **%1$@** shareable folders.";
|
||||
|
||||
"Premium.MaxSharedFolderLinksText" = "You can only create **%1$@** invite links. Upgrade to **Telegram Premium** to increase the links limit to **%2$@**.";
|
||||
"Premium.MaxSharedFolderLinksNoPremiumText" = "You can only create **%1$@** invite links. We are working to let you increase this limit in the future.";
|
||||
"Premium.MaxSharedFolderLinksFinalText" = "Sorry, you can only create **%1$@** invite links";
|
||||
|
@ -896,6 +896,8 @@ public enum PremiumLimitSubject {
|
||||
case pins
|
||||
case files
|
||||
case accounts
|
||||
case linksPerSharedFolder
|
||||
case membershipInSharedFolders
|
||||
}
|
||||
|
||||
public protocol ComposeController: ViewController {
|
||||
|
@ -44,6 +44,7 @@ import ComponentDisplayAdapters
|
||||
import ChatListHeaderComponent
|
||||
import ChatListTitleView
|
||||
import InviteLinksUI
|
||||
import ChatFolderLinkPreviewScreen
|
||||
|
||||
private func fixListNodeScrolling(_ listNode: ListView, searchNode: NavigationBarSearchContentNode) -> Bool {
|
||||
if listNode.scroller.isDragging {
|
||||
@ -2735,7 +2736,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
}
|
||||
}
|
||||
|
||||
let _ = (context.engine.peers.currentChatListFilters()
|
||||
let _ = (self.context.engine.peers.currentChatListFilters()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] filters in
|
||||
guard let self else {
|
||||
@ -2745,17 +2746,55 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
return
|
||||
}
|
||||
|
||||
if case let .filter(_, _, _, data) = filter, data.isShared {
|
||||
let presentationData = self.presentationData
|
||||
|
||||
//TODO:localize
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Delete Folder", text: "Are you sure you want to delete this folder? This will also deactivate all the invite links used to share this folder.", actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: presentationData.strings.Common_Delete, action: {
|
||||
apply()
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
})
|
||||
]), in: .window(.root))
|
||||
if case let .filter(_, title, _, data) = filter, data.isShared {
|
||||
let _ = (self.context.engine.data.get(
|
||||
EngineDataList(data.includePeers.peers.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] peers in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let presentationData = self.presentationData
|
||||
|
||||
//TODO:localize
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Delete Folder", text: "Are you sure you want to delete this folder? This will also deactivate all the invite links used to share this folder.", actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: presentationData.strings.Common_Delete, action: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let previewScreen = ChatFolderLinkPreviewScreen(
|
||||
context: self.context,
|
||||
subject: .remove(folderId: id),
|
||||
contents: ChatFolderLinkContents(
|
||||
localFilterId: id,
|
||||
title: title,
|
||||
peers: peers.compactMap { $0 }.filter { peer in
|
||||
if case .channel = peer {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
alreadyMemberPeerIds: Set()
|
||||
),
|
||||
completion: { [weak self] in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if self.chatListDisplayNode.mainContainerNode.currentItemNode.chatListFilter?.id == id {
|
||||
self.chatListDisplayNode.mainContainerNode.switchToFilter(id: .all, completion: {
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
self.push(previewScreen)
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
})
|
||||
]), in: .window(.root))
|
||||
})
|
||||
} else {
|
||||
let actionSheet = ActionSheetController(presentationData: self.presentationData)
|
||||
|
||||
|
@ -1334,7 +1334,14 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
|
||||
switch error {
|
||||
case .generic:
|
||||
text = "An error occurred"
|
||||
case .limitExceeded:
|
||||
case let .limitExceeded(limit, premiumLimit):
|
||||
if limit < premiumLimit {
|
||||
let limitController = context.sharedContext.makePremiumLimitController(context: context, subject: .linksPerSharedFolder, count: limit, action: {
|
||||
})
|
||||
pushControllerImpl?(limitController)
|
||||
|
||||
return
|
||||
}
|
||||
text = "You can't create more links."
|
||||
}
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
@ -12,6 +12,7 @@ import ItemListPeerActionItem
|
||||
import ChatListFilterSettingsHeaderItem
|
||||
import PremiumUI
|
||||
import UndoUI
|
||||
import ChatFolderLinkPreviewScreen
|
||||
|
||||
private final class ChatListFilterPresetListControllerArguments {
|
||||
let context: AccountContext
|
||||
@ -389,22 +390,38 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
if case let .filter(_, _, _, data) = filter, data.isShared {
|
||||
//TODO:localize
|
||||
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Delete Folder", text: "Are you sure you want to delete this folder? This will also deactivate all the invite links used to share this folder.", actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: presentationData.strings.Common_Delete, action: {
|
||||
let _ = (context.engine.peers.updateChatListFiltersInteractively { filters in
|
||||
var filters = filters
|
||||
if let index = filters.firstIndex(where: { $0.id == id }) {
|
||||
filters.remove(at: index)
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|> deliverOnMainQueue).start()
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
})
|
||||
]))
|
||||
if case let .filter(_, title, _, data) = filter, data.isShared {
|
||||
let _ = (context.engine.data.get(
|
||||
EngineDataList(data.includePeers.peers.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { peers in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
//TODO:localize
|
||||
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: "Delete Folder", text: "Are you sure you want to delete this folder? This will also deactivate all the invite links used to share this folder.", actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: presentationData.strings.Common_Delete, action: {
|
||||
let previewScreen = ChatFolderLinkPreviewScreen(
|
||||
context: context,
|
||||
subject: .remove(folderId: id),
|
||||
contents: ChatFolderLinkContents(
|
||||
localFilterId: id,
|
||||
title: title,
|
||||
peers: peers.compactMap { $0 }.filter { peer in
|
||||
if case .channel = peer {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
alreadyMemberPeerIds: Set()
|
||||
)
|
||||
)
|
||||
pushControllerImpl?(previewScreen)
|
||||
}),
|
||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
})
|
||||
]))
|
||||
})
|
||||
} else {
|
||||
let actionSheet = ActionSheetController(presentationData: presentationData)
|
||||
|
||||
|
@ -125,6 +125,7 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
private let titleNode: TextNode
|
||||
private let labelNode: TextNode
|
||||
private let arrowNode: ASImageNode
|
||||
private let sharedIconNode: ASImageNode
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
|
||||
@ -169,6 +170,11 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
self.arrowNode.displaysAsynchronously = false
|
||||
self.arrowNode.isLayerBacked = true
|
||||
|
||||
self.sharedIconNode = ASImageNode()
|
||||
self.sharedIconNode.displayWithoutProcessing = true
|
||||
self.sharedIconNode.displaysAsynchronously = false
|
||||
self.sharedIconNode.isLayerBacked = true
|
||||
|
||||
self.activateArea = AccessibilityAreaNode()
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
@ -180,6 +186,7 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
self.containerNode.addSubnode(self.titleNode)
|
||||
self.containerNode.addSubnode(self.labelNode)
|
||||
self.containerNode.addSubnode(self.arrowNode)
|
||||
self.containerNode.addSubnode(self.sharedIconNode)
|
||||
self.addSubnode(self.activateArea)
|
||||
|
||||
self.activateArea.activate = { [weak self] in
|
||||
@ -199,6 +206,7 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
return { item, params, neighbors in
|
||||
var updatedTheme: PresentationTheme?
|
||||
var updateArrowImage: UIImage?
|
||||
var updatedSharedIconImage: UIImage?
|
||||
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme || currentItem?.isDisabled != item.isDisabled {
|
||||
updatedTheme = item.presentationData.theme
|
||||
@ -207,6 +215,7 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
} else {
|
||||
updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.presentationData.theme)
|
||||
}
|
||||
updatedSharedIconImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Links/Share"), color: item.presentationData.theme.list.disclosureArrowColor)
|
||||
}
|
||||
|
||||
let peerRevealOptions: [ItemListRevealOption]
|
||||
@ -379,10 +388,14 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
|
||||
transition.updateAlpha(node: strongSelf.labelNode, alpha: reorderControlSizeAndApply != nil ? 0.0 : 1.0)
|
||||
transition.updateAlpha(node: strongSelf.arrowNode, alpha: reorderControlSizeAndApply != nil ? 0.0 : 1.0)
|
||||
transition.updateAlpha(node: strongSelf.sharedIconNode, alpha: reorderControlSizeAndApply != nil ? 0.0 : 1.0)
|
||||
|
||||
if let updateArrowImage = updateArrowImage {
|
||||
strongSelf.arrowNode.image = updateArrowImage
|
||||
}
|
||||
if let updatedSharedIconImage {
|
||||
strongSelf.sharedIconNode.image = updatedSharedIconImage
|
||||
}
|
||||
|
||||
if let arrowImage = strongSelf.arrowNode.image {
|
||||
var rightArrowInset = 0.0
|
||||
@ -393,6 +406,15 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
}
|
||||
strongSelf.arrowNode.isHidden = item.isAllChats
|
||||
|
||||
if let sharedIconImage = strongSelf.sharedIconNode.image {
|
||||
strongSelf.sharedIconNode.frame = CGRect(origin: CGPoint(x: strongSelf.arrowNode.frame.minX + 2.0 - sharedIconImage.size.width, y: floorToScreenPixels((layout.contentSize.height - sharedIconImage.size.height) / 2.0) + 1.0), size: sharedIconImage.size)
|
||||
}
|
||||
var isShared = false
|
||||
if case let .filter(_, _, _, data) = item.preset, data.isShared {
|
||||
isShared = true
|
||||
}
|
||||
strongSelf.sharedIconNode.isHidden = !isShared
|
||||
|
||||
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 0.0), size: CGSize(width: params.width - params.rightInset - 56.0 - (leftInset + revealOffset + editingOffset), height: layout.contentSize.height))
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: layout.contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||
@ -483,6 +505,10 @@ private final class ChatListFilterPresetListItemNode: ItemListRevealOptionsItemN
|
||||
var arrowFrame = self.arrowNode.frame
|
||||
arrowFrame.origin.x = params.width - params.rightInset - 7.0 - arrowFrame.width + revealOffset
|
||||
transition.updateFrame(node: self.arrowNode, frame: arrowFrame)
|
||||
|
||||
var sharedIconFrame = self.sharedIconNode.frame
|
||||
sharedIconFrame.origin.x = arrowFrame.minX + 2.0 - sharedIconFrame.width
|
||||
transition.updateFrame(node: self.sharedIconNode, frame: sharedIconFrame)
|
||||
}
|
||||
|
||||
override func revealOptionsInteractivelyOpened() {
|
||||
|
@ -765,6 +765,36 @@ private final class LimitSheetContent: CombinedComponent {
|
||||
badgeText = "\(limit)"
|
||||
string = strings.Premium_MaxChatsInFolderNoPremiumText("\(limit)").string
|
||||
}
|
||||
case .linksPerSharedFolder:
|
||||
//TODO:localize
|
||||
let limit = state.limits.maxSharedFolderInviteLinks
|
||||
let premiumLimit = state.premiumLimits.maxSharedFolderInviteLinks
|
||||
iconName = "Premium/Link"
|
||||
badgeText = "\(component.count)"
|
||||
string = component.count >= premiumLimit ? strings.Premium_MaxSharedFolderLinksFinalText("\(premiumLimit)").string : strings.Premium_MaxSharedFolderLinksText("\(limit)", "\(premiumLimit)").string
|
||||
defaultValue = component.count > limit ? "\(limit)" : ""
|
||||
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
||||
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
||||
|
||||
if isPremiumDisabled {
|
||||
badgeText = "\(limit)"
|
||||
string = strings.Premium_MaxSharedFolderLinksNoPremiumText("\(limit)").string
|
||||
}
|
||||
case .membershipInSharedFolders:
|
||||
//TODO:localize
|
||||
let limit = state.limits.maxSharedFolderJoin
|
||||
let premiumLimit = state.premiumLimits.maxSharedFolderJoin
|
||||
iconName = "Premium/Folder"
|
||||
badgeText = "\(component.count)"
|
||||
string = component.count >= premiumLimit ? strings.Premium_MaxSharedFolderMembershipFinalText("\(premiumLimit)").string : strings.Premium_MaxSharedFolderMembershipText("\(limit)", "\(premiumLimit)").string
|
||||
defaultValue = component.count > limit ? "\(limit)" : ""
|
||||
premiumValue = component.count >= premiumLimit ? "" : "\(premiumLimit)"
|
||||
badgePosition = CGFloat(component.count) / CGFloat(premiumLimit)
|
||||
|
||||
if isPremiumDisabled {
|
||||
badgeText = "\(limit)"
|
||||
string = strings.Premium_MaxSharedFolderMembershipNoPremiumText("\(limit)").string
|
||||
}
|
||||
case .pins:
|
||||
let limit = state.limits.maxPinnedChatCount
|
||||
let premiumLimit = state.premiumLimits.maxPinnedChatCount
|
||||
@ -1048,6 +1078,8 @@ public class PremiumLimitScreen: ViewControllerComponentContainer {
|
||||
case pins
|
||||
case files
|
||||
case accounts
|
||||
case linksPerSharedFolder
|
||||
case membershipInSharedFolders
|
||||
}
|
||||
|
||||
public init(context: AccountContext, subject: PremiumLimitScreen.Subject, count: Int32, action: @escaping () -> Void) {
|
||||
|
@ -5,7 +5,6 @@ public enum Api {
|
||||
public enum bots {}
|
||||
public enum channels {}
|
||||
public enum communities {}
|
||||
public enum community {}
|
||||
public enum contacts {}
|
||||
public enum help {}
|
||||
public enum messages {}
|
||||
@ -998,11 +997,11 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1699676497] = { return Api.channels.ChannelParticipants.parse_channelParticipants($0) }
|
||||
dict[-266911767] = { return Api.channels.ChannelParticipants.parse_channelParticipantsNotModified($0) }
|
||||
dict[-191450938] = { return Api.channels.SendAsPeers.parse_sendAsPeers($0) }
|
||||
dict[-557919187] = { return Api.communities.CommunityInvite.parse_communityInvite($0) }
|
||||
dict[-1997845037] = { return Api.communities.CommunityInvite.parse_communityInviteAlready($0) }
|
||||
dict[-414818125] = { return Api.communities.CommunityUpdates.parse_communityUpdates($0) }
|
||||
dict[1805101290] = { return Api.communities.ExportedCommunityInvite.parse_exportedCommunityInvite($0) }
|
||||
dict[-2662489] = { return Api.communities.ExportedInvites.parse_exportedInvites($0) }
|
||||
dict[988463765] = { return Api.community.CommunityInvite.parse_communityInvite($0) }
|
||||
dict[74184410] = { return Api.community.CommunityInvite.parse_communityInviteAlready($0) }
|
||||
dict[182326673] = { return Api.contacts.Blocked.parse_blocked($0) }
|
||||
dict[-513392236] = { return Api.contacts.Blocked.parse_blockedSlice($0) }
|
||||
dict[-353862078] = { return Api.contacts.Contacts.parse_contacts($0) }
|
||||
@ -1802,14 +1801,14 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.channels.SendAsPeers:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.communities.CommunityInvite:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.communities.CommunityUpdates:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.communities.ExportedCommunityInvite:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.communities.ExportedInvites:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.community.CommunityInvite:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.contacts.Blocked:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.contacts.Contacts:
|
||||
|
@ -894,6 +894,122 @@ public extension Api.channels {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.communities {
|
||||
enum CommunityInvite: TypeConstructorDescription {
|
||||
case communityInvite(title: String, peers: [Api.Peer], chats: [Api.Chat], users: [Api.User])
|
||||
case communityInviteAlready(filterId: Int32, missingPeers: [Api.Peer], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .communityInvite(let title, let peers, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-557919187)
|
||||
}
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(peers.count))
|
||||
for item in peers {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .communityInviteAlready(let filterId, let missingPeers, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1997845037)
|
||||
}
|
||||
serializeInt32(filterId, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(missingPeers.count))
|
||||
for item in missingPeers {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .communityInvite(let title, let peers, let chats, let users):
|
||||
return ("communityInvite", [("title", title as Any), ("peers", peers as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .communityInviteAlready(let filterId, let missingPeers, let chats, let users):
|
||||
return ("communityInviteAlready", [("filterId", filterId as Any), ("missingPeers", missingPeers as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_communityInvite(_ reader: BufferReader) -> CommunityInvite? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: [Api.Peer]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self)
|
||||
}
|
||||
var _3: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _4: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.communities.CommunityInvite.communityInvite(title: _1!, peers: _2!, chats: _3!, users: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_communityInviteAlready(_ reader: BufferReader) -> CommunityInvite? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: [Api.Peer]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self)
|
||||
}
|
||||
var _3: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _4: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.communities.CommunityInvite.communityInviteAlready(filterId: _1!, missingPeers: _2!, chats: _3!, users: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.communities {
|
||||
enum CommunityUpdates: TypeConstructorDescription {
|
||||
case communityUpdates(missingPeers: [Api.Peer], chats: [Api.Chat], users: [Api.User])
|
||||
@ -1000,181 +1116,3 @@ public extension Api.communities {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.communities {
|
||||
enum ExportedInvites: TypeConstructorDescription {
|
||||
case exportedInvites(invites: [Api.ExportedCommunityInvite], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .exportedInvites(let invites, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2662489)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(invites.count))
|
||||
for item in invites {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .exportedInvites(let invites, let chats, let users):
|
||||
return ("exportedInvites", [("invites", invites as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_exportedInvites(_ reader: BufferReader) -> ExportedInvites? {
|
||||
var _1: [Api.ExportedCommunityInvite]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ExportedCommunityInvite.self)
|
||||
}
|
||||
var _2: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _3: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.communities.ExportedInvites.exportedInvites(invites: _1!, chats: _2!, users: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.community {
|
||||
enum CommunityInvite: TypeConstructorDescription {
|
||||
case communityInvite(title: String, peers: [Api.Peer], chats: [Api.Chat], users: [Api.User])
|
||||
case communityInviteAlready(filterId: Int32, missingPeers: [Api.Peer], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .communityInvite(let title, let peers, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(988463765)
|
||||
}
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(peers.count))
|
||||
for item in peers {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .communityInviteAlready(let filterId, let missingPeers, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(74184410)
|
||||
}
|
||||
serializeInt32(filterId, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(missingPeers.count))
|
||||
for item in missingPeers {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .communityInvite(let title, let peers, let chats, let users):
|
||||
return ("communityInvite", [("title", title as Any), ("peers", peers as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .communityInviteAlready(let filterId, let missingPeers, let chats, let users):
|
||||
return ("communityInviteAlready", [("filterId", filterId as Any), ("missingPeers", missingPeers as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_communityInvite(_ reader: BufferReader) -> CommunityInvite? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: [Api.Peer]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self)
|
||||
}
|
||||
var _3: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _4: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.community.CommunityInvite.communityInvite(title: _1!, peers: _2!, chats: _3!, users: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_communityInviteAlready(_ reader: BufferReader) -> CommunityInvite? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: [Api.Peer]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.self)
|
||||
}
|
||||
var _3: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _4: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.community.CommunityInvite.communityInviteAlready(filterId: _1!, missingPeers: _2!, chats: _3!, users: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,65 @@
|
||||
public extension Api.communities {
|
||||
enum ExportedInvites: TypeConstructorDescription {
|
||||
case exportedInvites(invites: [Api.ExportedCommunityInvite], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .exportedInvites(let invites, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2662489)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(invites.count))
|
||||
for item in invites {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .exportedInvites(let invites, let chats, let users):
|
||||
return ("exportedInvites", [("invites", invites as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_exportedInvites(_ reader: BufferReader) -> ExportedInvites? {
|
||||
var _1: [Api.ExportedCommunityInvite]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ExportedCommunityInvite.self)
|
||||
}
|
||||
var _2: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _3: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.communities.ExportedInvites.exportedInvites(invites: _1!, chats: _2!, users: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.contacts {
|
||||
enum Blocked: TypeConstructorDescription {
|
||||
case blocked(blocked: [Api.PeerBlocked], chats: [Api.Chat], users: [Api.User])
|
||||
|
@ -2953,15 +2953,15 @@ public extension Api.functions.channels {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.communities {
|
||||
static func checkCommunityInvite(slug: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.community.CommunityInvite>) {
|
||||
static func checkCommunityInvite(slug: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.communities.CommunityInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1753956947)
|
||||
buffer.appendInt32(161196517)
|
||||
serializeString(slug, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "communities.checkCommunityInvite", parameters: [("slug", String(describing: slug))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.community.CommunityInvite? in
|
||||
return (FunctionDescription(name: "communities.checkCommunityInvite", parameters: [("slug", String(describing: slug))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.communities.CommunityInvite? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.community.CommunityInvite?
|
||||
var result: Api.communities.CommunityInvite?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.community.CommunityInvite
|
||||
result = Api.parse(reader, signature: signature) as? Api.communities.CommunityInvite
|
||||
}
|
||||
return result
|
||||
})
|
||||
@ -3112,6 +3112,26 @@ public extension Api.functions.communities {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.communities {
|
||||
static func leaveCommunity(community: Api.InputCommunity, peers: [Api.InputPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(903443807)
|
||||
community.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(peers.count))
|
||||
for item in peers {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
return (FunctionDescription(name: "communities.leaveCommunity", parameters: [("community", String(describing: community)), ("peers", String(describing: peers))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.contacts {
|
||||
static func acceptContact(id: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
|
@ -15,6 +15,8 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
public let maxAboutLength: Int32
|
||||
public let maxAnimatedEmojisInText: Int32
|
||||
public let maxReactionsPerMessage: Int32
|
||||
public let maxSharedFolderInviteLinks: Int32
|
||||
public let maxSharedFolderJoin: Int32
|
||||
|
||||
public static var defaultValue: UserLimitsConfiguration {
|
||||
return UserLimitsConfiguration(
|
||||
@ -30,7 +32,9 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
maxUploadFileParts: 4000,
|
||||
maxAboutLength: 70,
|
||||
maxAnimatedEmojisInText: 10,
|
||||
maxReactionsPerMessage: 1
|
||||
maxReactionsPerMessage: 1,
|
||||
maxSharedFolderInviteLinks: 3,
|
||||
maxSharedFolderJoin: 2
|
||||
)
|
||||
}
|
||||
|
||||
@ -47,7 +51,9 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
maxUploadFileParts: Int32,
|
||||
maxAboutLength: Int32,
|
||||
maxAnimatedEmojisInText: Int32,
|
||||
maxReactionsPerMessage: Int32
|
||||
maxReactionsPerMessage: Int32,
|
||||
maxSharedFolderInviteLinks: Int32,
|
||||
maxSharedFolderJoin: Int32
|
||||
) {
|
||||
self.maxPinnedChatCount = maxPinnedChatCount
|
||||
self.maxArchivedPinnedChatCount = maxArchivedPinnedChatCount
|
||||
@ -62,6 +68,8 @@ public struct UserLimitsConfiguration: Equatable {
|
||||
self.maxAboutLength = maxAboutLength
|
||||
self.maxAnimatedEmojisInText = maxAnimatedEmojisInText
|
||||
self.maxReactionsPerMessage = maxReactionsPerMessage
|
||||
self.maxSharedFolderInviteLinks = maxSharedFolderInviteLinks
|
||||
self.maxSharedFolderJoin = maxSharedFolderJoin
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,5 +107,7 @@ extension UserLimitsConfiguration {
|
||||
self.maxAboutLength = getValue("about_length_limit", orElse: defaultValue.maxAboutLength)
|
||||
self.maxAnimatedEmojisInText = getGeneralValue("message_animated_emoji_max", orElse: defaultValue.maxAnimatedEmojisInText)
|
||||
self.maxReactionsPerMessage = getValue("reactions_user_max", orElse: 1)
|
||||
self.maxSharedFolderInviteLinks = getValue("community_invites_limit", orElse: 3)
|
||||
self.maxSharedFolderJoin = getValue("communities_joined_limit", orElse: 2)
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ public enum EngineConfiguration {
|
||||
public let maxAboutLength: Int32
|
||||
public let maxAnimatedEmojisInText: Int32
|
||||
public let maxReactionsPerMessage: Int32
|
||||
public let maxSharedFolderInviteLinks: Int32
|
||||
public let maxSharedFolderJoin: Int32
|
||||
|
||||
public static var defaultValue: UserLimits {
|
||||
return UserLimits(UserLimitsConfiguration.defaultValue)
|
||||
@ -67,7 +69,9 @@ public enum EngineConfiguration {
|
||||
maxUploadFileParts: Int32,
|
||||
maxAboutLength: Int32,
|
||||
maxAnimatedEmojisInText: Int32,
|
||||
maxReactionsPerMessage: Int32
|
||||
maxReactionsPerMessage: Int32,
|
||||
maxSharedFolderInviteLinks: Int32,
|
||||
maxSharedFolderJoin: Int32
|
||||
) {
|
||||
self.maxPinnedChatCount = maxPinnedChatCount
|
||||
self.maxArchivedPinnedChatCount = maxArchivedPinnedChatCount
|
||||
@ -82,6 +86,8 @@ public enum EngineConfiguration {
|
||||
self.maxAboutLength = maxAboutLength
|
||||
self.maxAnimatedEmojisInText = maxAnimatedEmojisInText
|
||||
self.maxReactionsPerMessage = maxReactionsPerMessage
|
||||
self.maxSharedFolderInviteLinks = maxSharedFolderInviteLinks
|
||||
self.maxSharedFolderJoin = maxSharedFolderJoin
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -131,7 +137,9 @@ public extension EngineConfiguration.UserLimits {
|
||||
maxUploadFileParts: userLimitsConfiguration.maxUploadFileParts,
|
||||
maxAboutLength: userLimitsConfiguration.maxAboutLength,
|
||||
maxAnimatedEmojisInText: userLimitsConfiguration.maxAnimatedEmojisInText,
|
||||
maxReactionsPerMessage: userLimitsConfiguration.maxReactionsPerMessage
|
||||
maxReactionsPerMessage: userLimitsConfiguration.maxReactionsPerMessage,
|
||||
maxSharedFolderInviteLinks: userLimitsConfiguration.maxSharedFolderInviteLinks,
|
||||
maxSharedFolderJoin: userLimitsConfiguration.maxSharedFolderJoin
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ public func canShareLinkToPeer(peer: EnginePeer) -> Bool {
|
||||
|
||||
public enum ExportChatFolderError {
|
||||
case generic
|
||||
case limitExceeded
|
||||
case limitExceeded(limit: Int32, premiumLimit: Int32)
|
||||
}
|
||||
|
||||
public struct ExportedChatFolderLink: Equatable {
|
||||
@ -59,11 +59,24 @@ func _internal_exportChatFolder(account: Account, filterId: Int32, title: String
|
||||
|> castError(ExportChatFolderError.self)
|
||||
|> mapToSignal { inputPeers -> Signal<ExportedChatFolderLink, ExportChatFolderError> in
|
||||
return account.network.request(Api.functions.communities.exportCommunityInvite(community: .inputCommunityDialogFilter(filterId: filterId), title: title, peers: inputPeers))
|
||||
|> mapError { error -> ExportChatFolderError in
|
||||
|> `catch` { error -> Signal<Api.communities.ExportedCommunityInvite, ExportChatFolderError> in
|
||||
if error.errorDescription == "INVITES_TOO_MUCH" {
|
||||
return .limitExceeded
|
||||
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
|
||||
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
|
||||
}
|
||||
|> castError(ExportChatFolderError.self)
|
||||
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.communities.ExportedCommunityInvite, ExportChatFolderError> in
|
||||
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
if isPremium {
|
||||
return .fail(.limitExceeded(limit: userPremiumLimits.maxSharedFolderInviteLinks, premiumLimit: userPremiumLimits.maxSharedFolderInviteLinks))
|
||||
} else {
|
||||
return .fail(.limitExceeded(limit: userDefaultLimits.maxSharedFolderInviteLinks, premiumLimit: userPremiumLimits.maxSharedFolderInviteLinks))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .generic
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<ExportedChatFolderLink, ExportChatFolderError> in
|
||||
@ -335,7 +348,8 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
|
||||
|
||||
public enum JoinChatFolderLinkError {
|
||||
case generic
|
||||
case limitExceeded
|
||||
case dialogFilterLimitExceeded(limit: Int32, premiumLimit: Int32)
|
||||
case sharedFolderLimitExceeded(limit: Int32, premiumLimit: Int32)
|
||||
}
|
||||
|
||||
func _internal_joinChatFolderLink(account: Account, slug: String, peerIds: [EnginePeer.Id]) -> Signal<Never, JoinChatFolderLinkError> {
|
||||
@ -345,11 +359,39 @@ func _internal_joinChatFolderLink(account: Account, slug: String, peerIds: [Engi
|
||||
|> castError(JoinChatFolderLinkError.self)
|
||||
|> mapToSignal { inputPeers -> Signal<Never, JoinChatFolderLinkError> in
|
||||
return account.network.request(Api.functions.communities.joinCommunityInvite(slug: slug, peers: inputPeers))
|
||||
|> mapError { error -> JoinChatFolderLinkError in
|
||||
if error.errorDescription.hasPrefix("DIALOG_FILTERS_TOO_MUCH") {
|
||||
return .limitExceeded
|
||||
|> `catch` { error -> Signal<Api.Updates, JoinChatFolderLinkError> in
|
||||
if error.errorDescription == "DIALOG_FILTERS_TOO_MUCH" {
|
||||
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
|
||||
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
|
||||
}
|
||||
|> castError(JoinChatFolderLinkError.self)
|
||||
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.Updates, JoinChatFolderLinkError> in
|
||||
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
if isPremium {
|
||||
return .fail(.dialogFilterLimitExceeded(limit: userPremiumLimits.maxFoldersCount, premiumLimit: userPremiumLimits.maxFoldersCount))
|
||||
} else {
|
||||
return .fail(.dialogFilterLimitExceeded(limit: userDefaultLimits.maxFoldersCount, premiumLimit: userPremiumLimits.maxFoldersCount))
|
||||
}
|
||||
}
|
||||
} else if error.errorDescription == "FILTERS_TOO_MUCH" {
|
||||
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
|
||||
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
|
||||
}
|
||||
|> castError(JoinChatFolderLinkError.self)
|
||||
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.Updates, JoinChatFolderLinkError> in
|
||||
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
if isPremium {
|
||||
return .fail(.sharedFolderLimitExceeded(limit: userPremiumLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
|
||||
} else {
|
||||
return .fail(.sharedFolderLimitExceeded(limit: userDefaultLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .generic
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, JoinChatFolderLinkError> in
|
||||
@ -442,11 +484,39 @@ func _internal_joinAvailableChatsInFolder(account: Account, updates: ChatFolderU
|
||||
|> castError(JoinChatFolderLinkError.self)
|
||||
|> mapToSignal { inputPeers -> Signal<Never, JoinChatFolderLinkError> in
|
||||
return account.network.request(Api.functions.communities.joinCommunityUpdates(community: .inputCommunityDialogFilter(filterId: updates.folderId), peers: inputPeers))
|
||||
|> mapError { error -> JoinChatFolderLinkError in
|
||||
|> `catch` { error -> Signal<Api.Updates, JoinChatFolderLinkError> in
|
||||
if error.errorDescription == "DIALOG_FILTERS_TOO_MUCH" {
|
||||
return .limitExceeded
|
||||
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
|
||||
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
|
||||
}
|
||||
|> castError(JoinChatFolderLinkError.self)
|
||||
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.Updates, JoinChatFolderLinkError> in
|
||||
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
if isPremium {
|
||||
return .fail(.dialogFilterLimitExceeded(limit: userPremiumLimits.maxFoldersCount, premiumLimit: userPremiumLimits.maxFoldersCount))
|
||||
} else {
|
||||
return .fail(.dialogFilterLimitExceeded(limit: userDefaultLimits.maxFoldersCount, premiumLimit: userPremiumLimits.maxFoldersCount))
|
||||
}
|
||||
}
|
||||
} else if error.errorDescription == "FILTERS_TOO_MUCH" {
|
||||
return account.postbox.transaction { transaction -> (AppConfiguration, Bool) in
|
||||
return (currentAppConfiguration(transaction: transaction), transaction.getPeer(account.peerId)?.isPremium ?? false)
|
||||
}
|
||||
|> castError(JoinChatFolderLinkError.self)
|
||||
|> mapToSignal { appConfiguration, isPremium -> Signal<Api.Updates, JoinChatFolderLinkError> in
|
||||
let userDefaultLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: false)
|
||||
let userPremiumLimits = UserLimitsConfiguration(appConfiguration: appConfiguration, isPremium: true)
|
||||
|
||||
if isPremium {
|
||||
return .fail(.sharedFolderLimitExceeded(limit: userPremiumLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
|
||||
} else {
|
||||
return .fail(.sharedFolderLimitExceeded(limit: userDefaultLimits.maxSharedFolderJoin, premiumLimit: userPremiumLimits.maxSharedFolderJoin))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .generic
|
||||
return .fail(.generic)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Never, JoinChatFolderLinkError> in
|
||||
@ -464,3 +534,24 @@ func _internal_hideChatFolderUpdates(account: Account, folderId: Int32) -> Signa
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
|
||||
func _internal_leaveChatFolder(account: Account, folderId: Int32, removePeerIds: [EnginePeer.Id]) -> Signal<Never, NoError> {
|
||||
return account.postbox.transaction { transaction -> [Api.InputPeer] in
|
||||
return removePeerIds.compactMap(transaction.getPeer).compactMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeers -> Signal<Never, NoError> in
|
||||
return account.network.request(Api.functions.communities.leaveCommunity(community: .inputCommunityDialogFilter(filterId: folderId), peers: inputPeers))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<Never, NoError> in
|
||||
if let updates = updates {
|
||||
account.stateManager.addUpdates(updates)
|
||||
}
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1061,6 +1061,10 @@ public extension TelegramEngine {
|
||||
public func hideChatFolderUpdates(folderId: Int32) -> Signal<Never, NoError> {
|
||||
return _internal_hideChatFolderUpdates(account: self.account, folderId: folderId)
|
||||
}
|
||||
|
||||
public func leaveChatFolder(folderId: Int32, removePeerIds: [EnginePeer.Id]) -> Signal<Never, NoError> {
|
||||
return _internal_leaveChatFolder(account: self.account, folderId: folderId, removePeerIds: removePeerIds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,15 +23,18 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
let context: AccountContext
|
||||
let subject: ChatFolderLinkPreviewScreen.Subject
|
||||
let linkContents: ChatFolderLinkContents?
|
||||
let completion: (() -> Void)?
|
||||
|
||||
init(
|
||||
context: AccountContext,
|
||||
subject: ChatFolderLinkPreviewScreen.Subject,
|
||||
linkContents: ChatFolderLinkContents?
|
||||
linkContents: ChatFolderLinkContents?,
|
||||
completion: (() -> Void)?
|
||||
) {
|
||||
self.context = context
|
||||
self.subject = subject
|
||||
self.linkContents = linkContents
|
||||
self.completion = completion
|
||||
}
|
||||
|
||||
static func ==(lhs: ChatFolderLinkPreviewScreenComponent, rhs: ChatFolderLinkPreviewScreenComponent) -> Bool {
|
||||
@ -107,6 +110,8 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
|
||||
private var joinDisposable: Disposable?
|
||||
|
||||
private var inProgress: Bool = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.bottomOverscrollLimit = 200.0
|
||||
|
||||
@ -322,10 +327,19 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
}
|
||||
|
||||
let titleString: String
|
||||
var allChatsAdded = false
|
||||
if let linkContents = component.linkContents {
|
||||
//TODO:localize
|
||||
if linkContents.localFilterId != nil {
|
||||
if self.selectedItems.count == 1 {
|
||||
if case .remove = component.subject {
|
||||
titleString = "Remove Folder"
|
||||
} else if linkContents.localFilterId != nil {
|
||||
if linkContents.alreadyMemberPeerIds == Set(linkContents.peers.map(\.id)) {
|
||||
allChatsAdded = true
|
||||
}
|
||||
|
||||
if allChatsAdded {
|
||||
titleString = "Add Folder"
|
||||
} else if self.selectedItems.count == 1 {
|
||||
titleString = "Add \(self.selectedItems.count) chat"
|
||||
} else {
|
||||
titleString = "Add \(self.selectedItems.count) chats"
|
||||
@ -356,7 +370,7 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
contentHeight += 14.0
|
||||
|
||||
var topBadge: String?
|
||||
if let linkContents = component.linkContents, linkContents.localFilterId != nil {
|
||||
if !allChatsAdded, let linkContents = component.linkContents, linkContents.localFilterId != nil {
|
||||
topBadge = "+\(linkContents.peers.count)"
|
||||
}
|
||||
|
||||
@ -385,7 +399,11 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
|
||||
let text: String
|
||||
if let linkContents = component.linkContents {
|
||||
if linkContents.localFilterId == nil {
|
||||
if case .remove = component.subject {
|
||||
text = "Do you want to quit the chats you joined when\nadding the folder \(linkContents.title ?? "Folder")?"
|
||||
} else if allChatsAdded {
|
||||
text = "You have already added this\nfolder and its chats."
|
||||
} else if linkContents.localFilterId == nil {
|
||||
text = "Do you want to add a new chat folder\nand join its groups and channels?"
|
||||
} else {
|
||||
let chatCountString: String
|
||||
@ -473,7 +491,14 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
return
|
||||
}
|
||||
|
||||
if linkContents.alreadyMemberPeerIds.contains(peer.id) {
|
||||
if case .remove = component.subject {
|
||||
if self.selectedItems.contains(peer.id) {
|
||||
self.selectedItems.remove(peer.id)
|
||||
} else {
|
||||
self.selectedItems.insert(peer.id)
|
||||
}
|
||||
self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .easeInOut)))
|
||||
} else if linkContents.alreadyMemberPeerIds.contains(peer.id) {
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String
|
||||
if case let .channel(channel) = peer, case .broadcast = channel.info {
|
||||
@ -522,10 +547,28 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
}
|
||||
|
||||
let listHeaderTitle: String
|
||||
if self.selectedItems.count == 1 {
|
||||
listHeaderTitle = "1 CHAT IN FOLDER TO JOIN"
|
||||
if let linkContents = component.linkContents {
|
||||
if case .remove = component.subject {
|
||||
if linkContents.peers.count == 1 {
|
||||
listHeaderTitle = "1 CHAT TO QUIT"
|
||||
} else {
|
||||
listHeaderTitle = "\(linkContents.peers.count) CHATS TO QUIT"
|
||||
}
|
||||
} else if allChatsAdded {
|
||||
if linkContents.peers.count == 1 {
|
||||
listHeaderTitle = "1 CHAT IN THIS FOLDER"
|
||||
} else {
|
||||
listHeaderTitle = "\(linkContents.peers.count) CHATS IN THIS FOLDER"
|
||||
}
|
||||
} else {
|
||||
if linkContents.peers.count == 1 {
|
||||
listHeaderTitle = "1 CHAT IN FOLDER TO JOIN"
|
||||
} else {
|
||||
listHeaderTitle = "\(linkContents.peers.count) CHATS IN FOLDER TO JOIN"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
listHeaderTitle = "\(self.selectedItems.count) CHATS IN FOLDER TO JOIN"
|
||||
listHeaderTitle = " "
|
||||
}
|
||||
|
||||
let listHeaderActionTitle: String
|
||||
@ -607,7 +650,7 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
let listHeaderActionFrame = CGRect(origin: CGPoint(x: availableSize.width - sideInset - 15.0 - listHeaderActionSize.width, y: contentHeight), size: listHeaderActionSize)
|
||||
contentTransition.setPosition(view: listHeaderActionView, position: CGPoint(x: listHeaderActionFrame.maxX, y: listHeaderActionFrame.minY))
|
||||
listHeaderActionView.bounds = CGRect(origin: CGPoint(), size: listHeaderActionFrame.size)
|
||||
listHeaderActionView.isHidden = component.linkContents == nil
|
||||
listHeaderActionView.isHidden = component.linkContents == nil || allChatsAdded
|
||||
}
|
||||
|
||||
contentHeight += listHeaderTextSize.height
|
||||
@ -623,7 +666,15 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
initialContentHeight += 24.0
|
||||
|
||||
let actionButtonTitle: String
|
||||
if let linkContents = component.linkContents {
|
||||
if case .remove = component.subject {
|
||||
if self.selectedItems.isEmpty {
|
||||
actionButtonTitle = "Remove Folder"
|
||||
} else {
|
||||
actionButtonTitle = "Remove Folder and Chats"
|
||||
}
|
||||
} else if allChatsAdded {
|
||||
actionButtonTitle = "OK"
|
||||
} else if let linkContents = component.linkContents {
|
||||
if linkContents.localFilterId != nil {
|
||||
if self.selectedItems.isEmpty {
|
||||
actionButtonTitle = "Do Not Join Any Chats"
|
||||
@ -641,7 +692,7 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
transition: transition,
|
||||
component: AnyComponent(SolidRoundedButtonComponent(
|
||||
title: actionButtonTitle,
|
||||
badge: (self.selectedItems.isEmpty) ? nil : "\(self.selectedItems.count)",
|
||||
badge: (self.selectedItems.isEmpty || allChatsAdded) ? nil : "\(self.selectedItems.count)",
|
||||
theme: SolidRoundedButtonComponent.Theme(theme: environment.theme),
|
||||
font: .bold,
|
||||
fontSize: 17.0,
|
||||
@ -652,22 +703,42 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
animationName: nil,
|
||||
iconPosition: .right,
|
||||
iconSpacing: 4.0,
|
||||
isLoading: component.linkContents == nil,
|
||||
isLoading: self.inProgress,
|
||||
action: { [weak self] in
|
||||
guard let self, let component = self.component, let controller = self.environment?.controller() else {
|
||||
return
|
||||
}
|
||||
|
||||
if let _ = component.linkContents {
|
||||
if case let .remove(folderId) = component.subject {
|
||||
self.inProgress = true
|
||||
self.state?.updated(transition: .immediate)
|
||||
|
||||
component.completion?()
|
||||
|
||||
self.joinDisposable = (component.context.engine.peers.leaveChatFolder(folderId: folderId, removePeerIds: Array(self.selectedItems))
|
||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
||||
guard let self, let controller = self.environment?.controller() else {
|
||||
return
|
||||
}
|
||||
controller.dismiss()
|
||||
})
|
||||
} else if allChatsAdded {
|
||||
controller.dismiss()
|
||||
} else if let _ = component.linkContents {
|
||||
if self.joinDisposable == nil, !self.selectedItems.isEmpty {
|
||||
let joinSignal: Signal<Never, JoinChatFolderLinkError>
|
||||
switch component.subject {
|
||||
case .remove:
|
||||
return
|
||||
case let .slug(slug):
|
||||
joinSignal = component.context.engine.peers.joinChatFolderLink(slug: slug, peerIds: Array(self.selectedItems))
|
||||
case let .updates(updates):
|
||||
joinSignal = component.context.engine.peers.joinAvailableChatsInFolder(updates: updates, peerIds: Array(self.selectedItems))
|
||||
}
|
||||
|
||||
self.inProgress = true
|
||||
self.state?.updated(transition: .immediate)
|
||||
|
||||
self.joinDisposable = (joinSignal
|
||||
|> deliverOnMainQueue).start(error: { [weak self] error in
|
||||
guard let self, let component = self.component, let controller = self.environment?.controller() else {
|
||||
@ -677,9 +748,12 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
switch error {
|
||||
case .generic:
|
||||
controller.dismiss()
|
||||
case .limitExceeded:
|
||||
//TODO:localize
|
||||
let limitController = PremiumLimitScreen(context: component.context, subject: .folders, count: 5, action: {})
|
||||
case let .dialogFilterLimitExceeded(limit, _):
|
||||
let limitController = PremiumLimitScreen(context: component.context, subject: .folders, count: limit, action: {})
|
||||
controller.push(limitController)
|
||||
controller.dismiss()
|
||||
case let .sharedFolderLimitExceeded(limit, _):
|
||||
let limitController = PremiumLimitScreen(context: component.context, subject: .membershipInSharedFolders, count: limit, action: {})
|
||||
controller.push(limitController)
|
||||
controller.dismiss()
|
||||
}
|
||||
@ -693,29 +767,6 @@ private final class ChatFolderLinkPreviewScreenComponent: Component {
|
||||
controller.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
/*if self.selectedItems.isEmpty {
|
||||
controller.dismiss()
|
||||
} else if let link = component.link {
|
||||
let selectedPeers = component.peers.filter { self.selectedItems.contains($0.id) }
|
||||
|
||||
let _ = enqueueMessagesToMultiplePeers(account: component.context.account, peerIds: Array(self.selectedItems), threadIds: [:], messages: [.message(text: link, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
|
||||
let text: String
|
||||
if selectedPeers.count == 1 {
|
||||
text = environment.strings.Conversation_ShareLinkTooltip_Chat_One(selectedPeers[0].displayTitle(strings: environment.strings, displayOrder: .firstLast).replacingOccurrences(of: "*", with: "")).string
|
||||
} else if selectedPeers.count == 2 {
|
||||
text = environment.strings.Conversation_ShareLinkTooltip_TwoChats_One(selectedPeers[0].displayTitle(strings: environment.strings, displayOrder: .firstLast).replacingOccurrences(of: "*", with: ""), selectedPeers[1].displayTitle(strings: environment.strings, displayOrder: .firstLast).replacingOccurrences(of: "*", with: "")).string
|
||||
} else {
|
||||
text = environment.strings.Conversation_ShareLinkTooltip_ManyChats_One(selectedPeers[0].displayTitle(strings: environment.strings, displayOrder: .firstLast).replacingOccurrences(of: "*", with: ""), "\(selectedPeers.count - 1)").string
|
||||
}
|
||||
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
controller.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: false, text: text), elevatedLayout: false, action: { _ in return false }), in: .window(.root))
|
||||
|
||||
controller.dismiss()
|
||||
} else {
|
||||
controller.dismiss()
|
||||
}*/
|
||||
}
|
||||
)),
|
||||
environment: {},
|
||||
@ -793,6 +844,7 @@ public class ChatFolderLinkPreviewScreen: ViewControllerComponentContainer {
|
||||
public enum Subject: Equatable {
|
||||
case slug(String)
|
||||
case updates(ChatFolderUpdates)
|
||||
case remove(folderId: Int32)
|
||||
}
|
||||
|
||||
private let context: AccountContext
|
||||
@ -800,31 +852,15 @@ public class ChatFolderLinkPreviewScreen: ViewControllerComponentContainer {
|
||||
|
||||
private var isDismissed: Bool = false
|
||||
|
||||
public init(context: AccountContext, subject: Subject, contents: ChatFolderLinkContents) {
|
||||
public init(context: AccountContext, subject: Subject, contents: ChatFolderLinkContents, completion: (() -> Void)? = nil) {
|
||||
self.context = context
|
||||
|
||||
super.init(context: context, component: ChatFolderLinkPreviewScreenComponent(context: context, subject: subject, linkContents: contents), navigationBarAppearance: .none)
|
||||
super.init(context: context, component: ChatFolderLinkPreviewScreenComponent(context: context, subject: subject, linkContents: contents, completion: completion), navigationBarAppearance: .none)
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
self.navigationPresentation = .flatModal
|
||||
self.blocksBackgroundWhenInOverlay = true
|
||||
self.automaticallyControlPresentationContextLayout = false
|
||||
|
||||
/*self.linkContentsDisposable = (context.engine.peers.checkChatFolderLink(subject: subject)
|
||||
|> delay(0.2, queue: .mainQueue())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.updateComponent(component: AnyComponent(ChatFolderLinkPreviewScreenComponent(context: context, subject: subject, linkContents: result)), transition: Transition(animation: .curve(duration: 0.2, curve: .easeInOut)).withUserData(ChatFolderLinkPreviewScreenComponent.AnimationHint()))
|
||||
}, error: { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "The folder link has expired."), elevatedLayout: false, action: { _ in true }), in: .window(.root))
|
||||
self.dismiss()
|
||||
})*/
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
|
@ -837,7 +837,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
|
||||
}
|
||||
}
|
||||
handleResolvedUrl(.premiumOffer(reference: reference))
|
||||
} else if parsedUrl.host == "folder" {
|
||||
} else if parsedUrl.host == "list" {
|
||||
if let components = URLComponents(string: "/?" + query) {
|
||||
var slug: String?
|
||||
if let queryItems = components.queryItems {
|
||||
@ -850,7 +850,7 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
|
||||
}
|
||||
}
|
||||
if let slug = slug {
|
||||
convertedUrl = "https://t.me/folder/\(slug)"
|
||||
convertedUrl = "https://t.me/list/\(slug)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1676,6 +1676,10 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
mappedSubject = .files
|
||||
case .accounts:
|
||||
mappedSubject = .accounts
|
||||
case .linksPerSharedFolder:
|
||||
mappedSubject = .linksPerSharedFolder
|
||||
case .membershipInSharedFolders:
|
||||
mappedSubject = .membershipInSharedFolders
|
||||
}
|
||||
return PremiumLimitScreen(context: context, subject: mappedSubject, count: count, action: action)
|
||||
}
|
||||
|
@ -418,7 +418,7 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
|
||||
return .wallpaper(parameter)
|
||||
} else if pathComponents[0] == "addtheme" {
|
||||
return .theme(pathComponents[1])
|
||||
} else if pathComponents[0] == "folder" {
|
||||
} else if pathComponents[0] == "list" || pathComponents[0] == "folder" {
|
||||
return .chatFolder(slug: pathComponents[1])
|
||||
} else if pathComponents.count == 3 && pathComponents[0] == "c" {
|
||||
if let channelId = Int64(pathComponents[1]), let messageId = Int32(pathComponents[2]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user