Folder improvements

This commit is contained in:
Ali 2023-04-01 23:18:58 +04:00
parent 195b4a0159
commit dfe8e80232
6 changed files with 141 additions and 71 deletions

View File

@ -1547,7 +1547,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
for filter in filters {
if filter.id == filterId, case let .filter(_, title, _, data) = filter {
if !data.includePeers.peers.isEmpty && data.categories.isEmpty && !data.excludeRead && !data.excludeMuted && !data.excludeArchived && data.excludePeers.isEmpty {
items.append(.action(ContextMenuActionItem(text: "Share", textColor: .primary, badge: ContextMenuActionBadge(value: "NEW", color: .accent, style: .label), icon: { theme in
items.append(.action(ContextMenuActionItem(text: "Share", textColor: .primary, badge: data.hasSharedLinks ? nil : ContextMenuActionBadge(value: "NEW", color: .accent, style: .label), icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor)
}, action: { c, f in
c.dismiss(completion: {

View File

@ -1044,7 +1044,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
var includePeers = ChatListFilterIncludePeers()
includePeers.setPeers(state.additionallyIncludePeers)
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, hasSharedLinks: currentPreset?.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
if let data = filter.data {
switch chatListFilterType(data) {
case .generic:
@ -1189,7 +1189,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let state = stateValue.with { $0 }
var includePeers = ChatListFilterIncludePeers()
includePeers.setPeers(state.additionallyIncludePeers)
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, hasSharedLinks: currentPreset?.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
let _ = (context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { filters in
@ -1211,7 +1211,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
let state = stateValue.with { $0 }
var includePeers = ChatListFilterIncludePeers()
includePeers.setPeers(state.additionallyIncludePeers)
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
let filter: ChatListFilter = .filter(id: currentPreset?.id ?? -1, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, hasSharedLinks: currentPreset?.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
let _ = (context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { filters in
@ -1328,9 +1328,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
previousLink = updatedLink
let _ = (sharedLinks.get() |> take(1) |> deliverOnMainQueue).start(next: { links in
guard var links else {
return
}
var links = links ?? []
if let updatedLink {
if let index = links.firstIndex(where: { $0.link == updatedLink.link }) {
@ -1356,9 +1354,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
pushControllerImpl?(folderInviteLinkListController(context: context, filterId: currentPreset.id, title: currentPreset.title, allPeerIds: state.additionallyIncludePeers, currentInvitation: link, linkUpdated: { updatedLink in
if updatedLink != link {
let _ = (sharedLinks.get() |> take(1) |> deliverOnMainQueue).start(next: { links in
guard var links else {
return
}
var links = links ?? []
if let updatedLink {
if let index = links.firstIndex(where: { $0.link == link.link }) {
@ -1381,9 +1377,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
removeLink: { link in
if let currentPreset {
let _ = (sharedLinks.get() |> take(1) |> deliverOnMainQueue).start(next: { links in
guard var links else {
return
}
var links = links ?? []
if let index = links.firstIndex(where: { $0.link == link.link }) {
links.remove(at: index)
@ -1407,7 +1401,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
if currentPreset == nil {
filterId = context.engine.peers.generateNewChatListFilterId(filters: filters)
}
var updatedFilter: ChatListFilter = .filter(id: filterId, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
var updatedFilter: ChatListFilter = .filter(id: filterId, title: state.name, emoticon: currentPreset?.emoticon, data: ChatListFilterData(isShared: currentPreset?.data?.isShared ?? false, hasSharedLinks: currentPreset?.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
var filters = filters
if let _ = currentPreset {
@ -1554,7 +1548,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat
var includePeers = ChatListFilterIncludePeers()
includePeers.setPeers(state.additionallyIncludePeers)
let filter: ChatListFilter = .filter(id: currentPreset.id, title: state.name, emoticon: currentPreset.emoticon, data: ChatListFilterData(isShared: currentPreset.data?.isShared ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
let filter: ChatListFilter = .filter(id: currentPreset.id, title: state.name, emoticon: currentPreset.emoticon, data: ChatListFilterData(isShared: currentPreset.data?.isShared ?? false, hasSharedLinks: currentPreset.data?.hasSharedLinks ?? false, categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers))
if currentPresetWithoutPinnedPeers != filter {
displaySaveAlert()
return false

View File

@ -30,7 +30,7 @@ private final class FolderInviteLinkListControllerArguments {
let copyLink: (String) -> Void
let mainLinkContextAction: (ExportedChatFolderLink?, ASDisplayNode, ContextGesture?) -> Void
let peerAction: (EnginePeer, Bool) -> Void
let generateLink: () -> Void
let toggleAllSelected: () -> Void
init(
context: AccountContext,
@ -39,7 +39,7 @@ private final class FolderInviteLinkListControllerArguments {
copyLink: @escaping (String) -> Void,
mainLinkContextAction: @escaping (ExportedChatFolderLink?, ASDisplayNode, ContextGesture?) -> Void,
peerAction: @escaping (EnginePeer, Bool) -> Void,
generateLink: @escaping () -> Void
toggleAllSelected: @escaping () -> Void
) {
self.context = context
self.shareMainLink = shareMainLink
@ -47,7 +47,7 @@ private final class FolderInviteLinkListControllerArguments {
self.copyLink = copyLink
self.mainLinkContextAction = mainLinkContextAction
self.peerAction = peerAction
self.generateLink = generateLink
self.toggleAllSelected = toggleAllSelected
}
}
@ -68,7 +68,7 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
case mainLinkHeader(String)
case mainLink(link: ExportedChatFolderLink?, isGenerating: Bool)
case peersHeader(String)
case peersHeader(String, String?)
case peer(index: Int, peer: EnginePeer, isSelected: Bool, disabledReasonText: String?)
case peersInfo(String)
@ -137,8 +137,8 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
} else {
return false
}
case let .peersHeader(text):
if case .peersHeader(text) = rhs {
case let .peersHeader(text, action):
if case .peersHeader(text, action) = rhs {
return true
} else {
return false
@ -177,8 +177,6 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
}, shareAction: {
if let link {
arguments.copyLink(link.link)
} else {
arguments.generateLink()
}
}, secondaryAction: {
if let link {
@ -191,8 +189,10 @@ private enum InviteLinksListEntry: ItemListNodeEntry {
arguments.openMainLink(link.link)
}
})
case let .peersHeader(text):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
case let .peersHeader(text, action):
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, actionText: action, action: action == nil ? nil : {
arguments.toggleAllSelected()
}, sectionId: self.section)
case let .peersInfo(text):
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
case let .peer(_, peer, isSelected, disabledReasonText):
@ -239,6 +239,9 @@ private func folderInviteLinkListControllerEntries(
let peersHeaderString: String
let canShareChats = !allPeers.allSatisfy({ !canShareLinkToPeer(peer: $0) })
let allSelected = allPeers.filter({ canShareLinkToPeer(peer: $0) }).allSatisfy({ state.selectedPeerIds.contains($0.id) })
var selectAllString: String?
if !canShareChats {
infoString = "You can only share groups and channels in which you are allowed to create invite links."
@ -247,12 +250,21 @@ private func folderInviteLinkListControllerEntries(
} else if state.selectedPeerIds.isEmpty {
chatCountString = "Anyone with this link can add **\(title)** folder and the chats selected below."
peersHeaderString = "CHATS"
if allPeers.count > 1 {
selectAllString = allSelected ? "DESELECT ALL" : "SELECT ALL"
}
} else if state.selectedPeerIds.count == 1 {
chatCountString = "Anyone with this link can add **\(title)** folder and the 1 chat selected below."
peersHeaderString = "1 CHAT SELECTED"
if allPeers.count > 1 {
selectAllString = allSelected ? "DESELECT ALL" : "SELECT ALL"
}
} else {
chatCountString = "Anyone with this link can add **\(title)** folder and the \(state.selectedPeerIds.count) chats selected below."
peersHeaderString = "\(state.selectedPeerIds.count) CHATS SELECTED"
if allPeers.count > 1 {
selectAllString = allSelected ? "DESELECT ALL" : "SELECT ALL"
}
}
entries.append(.header(chatCountString))
@ -263,7 +275,7 @@ private func folderInviteLinkListControllerEntries(
entries.append(.mainLink(link: state.currentLink, isGenerating: state.generatingLink))
}
entries.append(.peersHeader(peersHeaderString))
entries.append(.peersHeader(peersHeaderString, selectAllString))
var sortedPeers: [EnginePeer] = []
for peer in allPeers.filter({ canShareLinkToPeer(peer: $0) }) {
@ -338,6 +350,20 @@ public func folderInviteLinkListController(context: AccountContext, updatedPrese
var didDisplayAddPeerNotice: Bool = false
var combinedPeerIds: [EnginePeer.Id] = []
if let currentInvitation {
for peerId in currentInvitation.peerIds {
if !combinedPeerIds.contains(peerId) {
combinedPeerIds.append(peerId)
}
}
}
for peerId in allPeerIds {
if !combinedPeerIds.contains(peerId) {
combinedPeerIds.append(peerId)
}
}
let arguments = FolderInviteLinkListControllerArguments(context: context, shareMainLink: { inviteLink in
let shareController = ShareController(context: context, subject: .url(inviteLink), updatedPresentationData: updatedPresentationData)
shareController.completed = { peerIds in
@ -500,47 +526,33 @@ public func folderInviteLinkListController(context: AccountContext, updatedPrese
dismissTooltipsImpl?()
displayTooltipImpl?(.peers(context: context, peers: [peer], title: nil, text: text, customUndoText: nil))
}
}, generateLink: {
let currentState = stateValue.with({ $0 })
if !currentState.generatingLink {
updateState { state in
var state = state
}, toggleAllSelected: {
let _ = (context.engine.data.get(
EngineDataList(combinedPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
)
|> deliverOnMainQueue).start(next: { allPeers in
let allPeers = allPeers.compactMap({ $0 })
state.generatingLink = true
return state
}
actionsDisposable.add((context.engine.peers.exportChatFolder(filterId: filterId, title: "", peerIds: Array(currentState.selectedPeerIds))
|> deliverOnMainQueue).start(next: { result in
linkUpdated(result)
let selectablePeers = allPeers.filter({ canShareLinkToPeer(peer: $0) })
let state = stateValue.with({ $0 })
let allSelected = selectablePeers.allSatisfy({ state.selectedPeerIds.contains($0.id) })
updateState { state in
var state = state
state.generatingLink = false
state.currentLink = result
if allSelected {
state.selectedPeerIds.removeAll()
} else {
state.selectedPeerIds.removeAll()
for peer in selectablePeers {
state.selectedPeerIds.insert(peer.id)
}
}
return state
}
}, error: { _ in
}))
}
})
var combinedPeerIds: [EnginePeer.Id] = []
if let currentInvitation {
for peerId in currentInvitation.peerIds {
if !combinedPeerIds.contains(peerId) {
combinedPeerIds.append(peerId)
}
}
}
for peerId in allPeerIds {
if !combinedPeerIds.contains(peerId) {
combinedPeerIds.append(peerId)
}
}
})
let allPeers = context.engine.data.subscribe(
EngineDataList(combinedPeerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))

View File

@ -45,17 +45,21 @@ public class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
let multiline: Bool
let activityIndicator: ItemListSectionHeaderActivityIndicator
let accessoryText: ItemListSectionHeaderAccessoryText?
let actionText: String?
let action: (() -> Void)?
public let sectionId: ItemListSectionId
public let isAlwaysPlain: Bool = true
public init(presentationData: ItemListPresentationData, text: String, badge: String? = nil, multiline: Bool = false, activityIndicator: ItemListSectionHeaderActivityIndicator = .none, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
public init(presentationData: ItemListPresentationData, text: String, badge: String? = nil, multiline: Bool = false, activityIndicator: ItemListSectionHeaderActivityIndicator = .none, accessoryText: ItemListSectionHeaderAccessoryText? = nil, actionText: String? = nil, action: (() -> Void)? = nil, sectionId: ItemListSectionId) {
self.presentationData = presentationData
self.text = text
self.badge = badge
self.multiline = multiline
self.activityIndicator = activityIndicator
self.accessoryText = accessoryText
self.actionText = actionText
self.action = action
self.sectionId = sectionId
}
@ -104,6 +108,8 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
private let accessoryTextNode: TextNode
private var accessoryImageNode: ASImageNode?
private var activityIndicator: ActivityIndicator?
private var actionNode: TextNode?
private var actionButtonNode: HighlightableButtonNode?
private let activateArea: AccessibilityAreaNode
@ -130,6 +136,7 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
public func asyncLayout() -> (_ item: ItemListSectionHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let makeActionLayout = TextNode.asyncLayout(self.actionNode)
let makeBadgeTextLayout = TextNode.asyncLayout(self.badgeTextNode)
let makeAccessoryTextLayout = TextNode.asyncLayout(self.accessoryTextNode)
@ -152,6 +159,13 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
textRightInset += badgeLayoutAndApply.0.size.width + badgeSpacing
}
var actionLayoutAndApply: (TextNodeLayout, () -> TextNode)?
if let actionText = item.actionText {
let actionLayoutAndApplyValue = makeActionLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: actionText, font: titleFont, textColor: item.presentationData.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
actionLayoutAndApply = actionLayoutAndApplyValue
textRightInset += actionLayoutAndApplyValue.0.size.width + 2.0
}
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.text, font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
var accessoryTextString: NSAttributedString?
var accessoryIcon: UIImage?
@ -195,6 +209,39 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 7.0), size: titleLayout.size)
if let (actionLayout, actionApply) = actionLayoutAndApply {
let actionButtonNode: HighlightableButtonNode
if let current = strongSelf.actionButtonNode {
actionButtonNode = current
} else {
actionButtonNode = HighlightableButtonNode()
strongSelf.actionButtonNode = actionButtonNode
actionButtonNode.hitTestSlop = UIEdgeInsets(top: -4.0, left: -4.0, bottom: -4.0, right: -4.0)
strongSelf.addSubnode(actionButtonNode)
actionButtonNode.addTarget(strongSelf, action: #selector(strongSelf.actionButtonPressed), forControlEvents: .touchUpInside)
}
let actionNode = actionApply()
if strongSelf.actionNode !== actionNode {
strongSelf.actionNode?.removeFromSupernode()
strongSelf.actionNode = actionNode
actionButtonNode.addSubnode(actionNode)
}
actionButtonNode.frame = CGRect(origin: CGPoint(x: params.width - leftInset - actionLayout.size.width, y: 7.0), size: actionLayout.size)
actionNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: actionLayout.size)
} else {
if let actionNode = strongSelf.actionNode {
strongSelf.actionNode = nil
actionNode.removeFromSupernode()
}
if let actionButtonNode = strongSelf.actionButtonNode {
strongSelf.actionButtonNode = nil
actionButtonNode.removeFromSupernode()
}
}
if let badgeLayoutAndApply {
let badgeTextNode = badgeLayoutAndApply.1()
let badgeSideInset: CGFloat = 4.0
@ -296,6 +343,10 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
}
}
@objc private func actionButtonPressed() {
self.item?.action?()
}
override public func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
}

View File

@ -175,6 +175,7 @@ extension ChatListFilterIncludePeers {
public struct ChatListFilterData: Equatable, Hashable {
public var isShared: Bool
public var hasSharedLinks: Bool
public var categories: ChatListFilterPeerCategories
public var excludeMuted: Bool
public var excludeRead: Bool
@ -184,6 +185,7 @@ public struct ChatListFilterData: Equatable, Hashable {
public init(
isShared: Bool,
hasSharedLinks: Bool,
categories: ChatListFilterPeerCategories,
excludeMuted: Bool,
excludeRead: Bool,
@ -192,6 +194,7 @@ public struct ChatListFilterData: Equatable, Hashable {
excludePeers: [PeerId]
) {
self.isShared = isShared
self.hasSharedLinks = hasSharedLinks
self.categories = categories
self.excludeMuted = excludeMuted
self.excludeRead = excludeRead
@ -250,6 +253,7 @@ public enum ChatListFilter: Codable, Equatable {
let data = ChatListFilterData(
isShared: try container.decodeIfPresent(Bool.self, forKey: "isShared") ?? false,
hasSharedLinks: try container.decodeIfPresent(Bool.self, forKey: "hasSharedLinks") ?? false,
categories: ChatListFilterPeerCategories(rawValue: try container.decode(Int32.self, forKey: "categories")),
excludeMuted: (try container.decode(Int32.self, forKey: "excludeMuted")) != 0,
excludeRead: (try container.decode(Int32.self, forKey: "excludeRead")) != 0,
@ -280,6 +284,7 @@ public enum ChatListFilter: Codable, Equatable {
try container.encodeIfPresent(emoticon, forKey: "emoticon")
try container.encode(data.isShared, forKey: "isShared")
try container.encode(data.hasSharedLinks, forKey: "hasSharedLinks")
try container.encode(data.categories.rawValue, forKey: "categories")
try container.encode((data.excludeMuted ? 1 : 0) as Int32, forKey: "excludeMuted")
try container.encode((data.excludeRead ? 1 : 0) as Int32, forKey: "excludeRead")
@ -303,6 +308,7 @@ extension ChatListFilter {
emoticon: emoticon,
data: ChatListFilterData(
isShared: false,
hasSharedLinks: false,
categories: ChatListFilterPeerCategories(apiFlags: flags),
excludeMuted: (flags & (1 << 11)) != 0,
excludeRead: (flags & (1 << 12)) != 0,
@ -344,13 +350,14 @@ extension ChatListFilter {
}
)
)
case let .dialogFilterCommunity(_, id, title, emoticon, pinnedPeers, includePeers):
case let .dialogFilterCommunity(flags, id, title, emoticon, pinnedPeers, includePeers):
self = .filter(
id: id,
title: title,
emoticon: emoticon,
data: ChatListFilterData(
isShared: true,
hasSharedLinks: (flags & (1 << 26)) != 0,
categories: [],
excludeMuted: false,
excludeRead: false,
@ -1078,7 +1085,8 @@ public struct ChatListFeaturedFilter: Codable, Equatable {
self.title = try container.decode(String.self, forKey: "title")
self.description = try container.decode(String.self, forKey: "description")
self.data = ChatListFilterData(
isShared: try container.decodeIfPresent(Bool.self, forKey: "isShared") ?? false,
isShared: false,
hasSharedLinks: false,
categories: ChatListFilterPeerCategories(rawValue: try container.decode(Int32.self, forKey: "categories")),
excludeMuted: (try container.decode(Int32.self, forKey: "excludeMuted")) != 0,
excludeRead: (try container.decode(Int32.self, forKey: "excludeRead")) != 0,

View File

@ -539,24 +539,29 @@ private struct FirstTimeFolderUpdatesKey: Hashable {
private var firstTimeFolderUpdates = Set<FirstTimeFolderUpdatesKey>()
func _internal_pollChatFolderUpdatesOnce(account: Account, folderId: Int32) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> ChatListFiltersState in
return _internal_currentChatListFiltersState(transaction: transaction)
return account.postbox.transaction { transaction -> (ChatListFiltersState, AppConfiguration) in
return (_internal_currentChatListFiltersState(transaction: transaction), currentAppConfiguration(transaction: transaction))
}
|> mapToSignal { state -> Signal<Never, NoError> in
|> mapToSignal { state, appConfig -> Signal<Never, NoError> in
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
let key = FirstTimeFolderUpdatesKey(accountId: account.id, folderId: folderId)
if firstTimeFolderUpdates.contains(key) {
if let current = state.updates.first(where: { $0.folderId == folderId }) {
let updateInterval: Int32
var updateInterval: Int32 = 3600
if let data = appConfig.data {
if let value = data["community_update_period"] as? Double {
updateInterval = Int32(value)
}
}
#if DEBUG
if "".isEmpty {
updateInterval = 5
#else
updateInterval = 60 * 60
}
#endif
if current.timestamp + updateInterval >= timestamp {
return .complete()
}
}