Refactoring

This commit is contained in:
Ali 2021-07-07 01:59:12 +04:00
parent 9973b37e97
commit 9134bae908
123 changed files with 509 additions and 1477 deletions

View File

@ -322,7 +322,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
isMuted = true
}
items.append(.action(ContextMenuActionItem(text: isMuted ? strings.ChatList_Context_Unmute : strings.ChatList_Context_Mute, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: isMuted ? "Chat/Context Menu/Unmute" : "Chat/Context Menu/Muted"), color: theme.contextMenu.primaryColor) }, action: { _, f in
let _ = (togglePeerMuted(account: context.account, peerId: peerId)
let _ = (context.engine.peers.togglePeerMuted(peerId: peerId)
|> deliverOnMainQueue).start(completed: {
f(.default)
})
@ -332,7 +332,7 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch
if case .search = source {
if let _ = peer as? TelegramChannel {
items.append(.action(ContextMenuActionItem(text: strings.ChatList_Context_JoinChannel, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { _, f in
var createSignal = context.peerChannelMemberCategoriesContextsManager.join(account: context.account, peerId: peerId, hash: nil)
var createSignal = context.peerChannelMemberCategoriesContextsManager.join(engine: context.engine, peerId: peerId, hash: nil)
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }

View File

@ -688,7 +688,7 @@ public final class ChatListNode: ListView {
return
}
strongSelf.setCurrentRemovingPeerId(peerId)
let _ = (togglePeerMuted(account: context.account, peerId: peerId)
let _ = (context.engine.peers.togglePeerMuted(peerId: peerId)
|> deliverOnMainQueue).start(completed: {
self?.updateState { state in
var state = state

View File

@ -365,7 +365,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
return DeviceContactNormalizedPhoneNumber(rawValue: formatPhoneNumber(phoneNumber.value))
})))
}
return deviceContactsImportedByCount(postbox: context.account.postbox, contacts: mappedContacts)
return context.engine.contacts.deviceContactsImportedByCount(contacts: mappedContacts)
|> map { counts -> [(DeviceContactStableId, DeviceContactBasicData, Int32)]? in
var result: [(DeviceContactStableId, DeviceContactBasicData, Int32)] = []
var contactValues: [DeviceContactStableId: DeviceContactBasicData] = [:]

View File

@ -310,7 +310,7 @@ final class InstantPagePeerReferenceNode: ASDisplayNode, InstantPageNode {
@objc func joinPressed() {
if let peer = self.peer, case .notJoined = self.joinState {
self.updateJoinState(.inProgress)
self.joinDisposable.set((joinChannel(account: self.context.account, peerId: peer.id, hash: nil) |> deliverOnMainQueue).start(error: { [weak self] _ in
self.joinDisposable.set((self.context.engine.peers.joinChannel(peerId: peer.id, hash: nil) |> deliverOnMainQueue).start(error: { [weak self] _ in
if let strongSelf = self {
if case .inProgress = strongSelf.joinState {
strongSelf.updateJoinState(.notJoined)

View File

@ -1,24 +0,0 @@
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
swift_library(
name = "MessageReactionListUI",
module_name = "MessageReactionListUI",
srcs = glob([
"Sources/**/*.swift",
]),
deps = [
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
"//submodules/TelegramCore:TelegramCore",
"//submodules/SyncCore:SyncCore",
"//submodules/Postbox:Postbox",
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
"//submodules/Display:Display",
"//submodules/TelegramPresentationData:TelegramPresentationData",
"//submodules/AccountContext:AccountContext",
"//submodules/MergeLists:MergeLists",
"//submodules/ItemListPeerItem:ItemListPeerItem",
],
visibility = [
"//visibility:public",
],
)

View File

@ -1,104 +0,0 @@
import Foundation
import AsyncDisplayKit
import Display
import TelegramPresentationData
import TelegramCore
import SyncCore
final class MessageReactionCategoryNode: ASDisplayNode {
let category: MessageReactionListCategory
private let action: () -> Void
private let buttonNode: HighlightableButtonNode
private let highlightedBackgroundNode: ASImageNode
private let iconNode: ASImageNode
private let emojiNode: ImmediateTextNode
private let countNode: ImmediateTextNode
var isSelected = false {
didSet {
self.highlightedBackgroundNode.alpha = self.isSelected ? 1.0 : 0.0
}
}
init(theme: PresentationTheme, category: MessageReactionListCategory, count: Int, action: @escaping () -> Void) {
self.category = category
self.action = action
self.buttonNode = HighlightableButtonNode()
self.highlightedBackgroundNode = ASImageNode()
self.highlightedBackgroundNode.displaysAsynchronously = false
self.highlightedBackgroundNode.displayWithoutProcessing = true
self.highlightedBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 18.0, color: UIColor(rgb: 0xe6e6e8))
self.highlightedBackgroundNode.alpha = 1.0
self.iconNode = ASImageNode()
self.emojiNode = ImmediateTextNode()
self.emojiNode.displaysAsynchronously = false
let emojiText: String
switch category {
case .all:
emojiText = ""
self.iconNode.image = PresentationResourcesChat.chatInputTextFieldTimerImage(theme)
case let .reaction(value):
emojiText = value
}
self.emojiNode.attributedText = NSAttributedString(string: emojiText, font: Font.regular(18.0), textColor: .black)
self.countNode = ImmediateTextNode()
self.countNode.displaysAsynchronously = false
self.countNode.attributedText = NSAttributedString(string: "\(count)", font: Font.regular(16.0), textColor: .black)
super.init()
self.addSubnode(self.highlightedBackgroundNode)
self.addSubnode(self.iconNode)
self.addSubnode(self.emojiNode)
self.addSubnode(self.countNode)
self.addSubnode(self.buttonNode)
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
}
func updateLayout() -> CGSize {
let sideInset: CGFloat = 6.0
let spacing: CGFloat = 2.0
let emojiSize = self.emojiNode.updateLayout(CGSize(width: 100.0, height: 100.0))
let iconSize = self.iconNode.image?.size ?? CGSize()
let countSize = self.countNode.updateLayout(CGSize(width: 100.0, height: 100.0))
let height: CGFloat = 60.0
let backgroundHeight: CGFloat = 36.0
self.emojiNode.frame = CGRect(origin: CGPoint(x: sideInset, y: floor((height - emojiSize.height) / 2.0)), size: emojiSize)
self.iconNode.frame = CGRect(origin: CGPoint(x: sideInset, y: floor((height - iconSize.height) / 2.0)), size: iconSize)
let iconFrame: CGRect
if self.iconNode.image != nil {
iconFrame = self.iconNode.frame
} else {
iconFrame = self.emojiNode.frame
}
self.countNode.frame = CGRect(origin: CGPoint(x: iconFrame.maxX + spacing, y: floor((height - countSize.height) / 2.0)), size: countSize)
let contentWidth = sideInset * 2.0 + spacing + iconFrame.width + countSize.width
self.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((height - backgroundHeight) / 2.0)), size: CGSize(width: contentWidth, height: backgroundHeight))
let size = CGSize(width: contentWidth, height: height)
self.buttonNode.frame = CGRect(origin: CGPoint(), size: size)
return size
}
@objc private func buttonPressed() {
self.action()
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.buttonNode.frame.contains(point) {
return self.buttonNode.view
}
return nil
}
}

View File

@ -1,447 +0,0 @@
import Foundation
import UIKit
import AsyncDisplayKit
import Display
import AccountContext
import TelegramPresentationData
import Postbox
import TelegramCore
import SyncCore
import SwiftSignalKit
import MergeLists
import ItemListPeerItem
import ItemListUI
public final class MessageReactionListController: ViewController {
private let context: AccountContext
private let messageId: MessageId
private let presentationData: PresentationData
private let initialReactions: [MessageReaction]
private var controllerNode: MessageReactionListControllerNode {
return self.displayNode as! MessageReactionListControllerNode
}
private var animatedIn: Bool = false
private let _ready = Promise<Bool>()
override public var ready: Promise<Bool> {
return self._ready
}
public init(context: AccountContext, messageId: MessageId, initialReactions: [MessageReaction]) {
self.context = context
self.messageId = messageId
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.initialReactions = initialReactions
super.init(navigationBarPresentationData: nil)
self.statusBar.statusBarStyle = .Ignore
}
required public init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func loadDisplayNode() {
self.displayNode = MessageReactionListControllerNode(context: self.context, presentationData: self.presentationData, messageId: messageId, initialReactions: initialReactions, dismiss: { [weak self] in
self?.dismiss()
})
super.displayNodeDidLoad()
self._ready.set(self.controllerNode.isReady.get())
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition)
self.controllerNode.containerLayoutUpdated(layout: layout, transition: transition)
}
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if !self.animatedIn {
self.animatedIn = true
self.controllerNode.animateIn()
}
}
override public func dismiss(completion: (() -> Void)? = nil) {
self.controllerNode.animateOut(completion: { [weak self] in
self?.presentingViewController?.dismiss(animated: false, completion: nil)
completion?()
})
}
}
private struct MessageReactionListTransaction {
let deletions: [ListViewDeleteItem]
let insertions: [ListViewInsertItem]
let updates: [ListViewUpdateItem]
}
private struct MessageReactionListEntry: Comparable, Identifiable {
let index: Int
let item: MessageReactionListCategoryItem
var stableId: PeerId {
return self.item.peer.id
}
static func <(lhs: MessageReactionListEntry, rhs: MessageReactionListEntry) -> Bool {
return lhs.index < rhs.index
}
func item(context: AccountContext, presentationData: PresentationData) -> ListViewItem {
return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: self.item.peer, height: .peerList, nameStyle: .distinctBold, presence: nil, text: .none, label: .text(self.item.reaction, .custom(Font.regular(19.0))), editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: false, sectionId: 0, action: {
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, noInsets: true, tag: nil)
}
}
private func preparedTransition(from fromEntries: [MessageReactionListEntry], to toEntries: [MessageReactionListEntry], context: AccountContext, presentationData: PresentationData) -> MessageReactionListTransaction {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData), directionHint: nil) }
return MessageReactionListTransaction(deletions: deletions, insertions: insertions, updates: updates)
}
private let headerHeight: CGFloat = 60.0
private let itemHeight: CGFloat = 50.0
private func topInsetForLayout(layout: ContainerViewLayout, itemCount: Int) -> CGFloat {
let contentHeight = CGFloat(itemCount) * itemHeight
let minimumItemHeights: CGFloat = max(contentHeight, itemHeight * 5.0)
return max(layout.size.height - layout.intrinsicInsets.bottom - minimumItemHeights, headerHeight)
}
private final class MessageReactionListControllerNode: ViewControllerTracingNode {
private let context: AccountContext
private let presentationData: PresentationData
private let dismiss: () -> Void
private let listContext: MessageReactionListContext
private let dimNode: ASDisplayNode
private let backgroundNode: ASDisplayNode
private let contentHeaderContainerNode: ASDisplayNode
private let contentHeaderContainerBackgroundNode: ASImageNode
private let contentHeaderContainerSeparatorNode: ASDisplayNode
private var categoryItemNodes: [MessageReactionCategoryNode] = []
private let categoryScrollNode: ASScrollNode
private let listNode: ListView
private var placeholderNode: MessageReactionListLoadingPlaceholder?
private var placeholderNodeIsAnimatingOut = false
private var validLayout: ContainerViewLayout?
private var currentCategory: MessageReactionListCategory = .all
private var currentState: MessageReactionListState?
private var enqueuedTransactions: [MessageReactionListTransaction] = []
private let disposable = MetaDisposable()
let isReady = Promise<Bool>()
private var forceHeaderTransition: ContainedViewLayoutTransition?
init(context: AccountContext, presentationData: PresentationData, messageId: MessageId, initialReactions: [MessageReaction], dismiss: @escaping () -> Void) {
self.context = context
self.presentationData = presentationData
self.dismiss = dismiss
self.dimNode = ASDisplayNode()
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor
self.contentHeaderContainerNode = ASDisplayNode()
self.contentHeaderContainerBackgroundNode = ASImageNode()
self.contentHeaderContainerBackgroundNode.displaysAsynchronously = false
self.contentHeaderContainerSeparatorNode = ASDisplayNode()
self.contentHeaderContainerSeparatorNode.backgroundColor = self.presentationData.theme.list.itemPlainSeparatorColor
self.categoryScrollNode = ASScrollNode()
self.contentHeaderContainerBackgroundNode.displayWithoutProcessing = true
self.contentHeaderContainerBackgroundNode.image = generateImage(CGSize(width: 10.0, height: 10.0), rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setFillColor(presentationData.theme.rootController.navigationBar.opaqueBackgroundColor.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
context.fill(CGRect(origin: CGPoint(x: 0.0, y: size.height / 2.0), size: CGSize(width: size.width, height: size.height / 2.0)))
})?.stretchableImage(withLeftCapWidth: 5, topCapHeight: 5)
self.listNode = ListView()
self.listNode.limitHitTestToNodes = true
self.listNode.accessibilityPageScrolledString = { row, count in
return presentationData.strings.VoiceOver_ScrollStatus(row, count).0
}
self.placeholderNode = MessageReactionListLoadingPlaceholder(theme: presentationData.theme, itemHeight: itemHeight)
self.placeholderNode?.isUserInteractionEnabled = false
self.listContext = MessageReactionListContext(postbox: self.context.account.postbox, network: self.context.account.network, messageId: messageId, initialReactions: initialReactions)
super.init()
self.addSubnode(self.dimNode)
self.addSubnode(self.backgroundNode)
self.listNode.stackFromBottom = false
self.addSubnode(self.listNode)
self.placeholderNode.flatMap(self.addSubnode)
self.addSubnode(self.contentHeaderContainerNode)
self.contentHeaderContainerNode.addSubnode(self.contentHeaderContainerBackgroundNode)
self.contentHeaderContainerNode.addSubnode(self.contentHeaderContainerSeparatorNode)
self.contentHeaderContainerNode.addSubnode(self.categoryScrollNode)
self.listNode.updateFloatingHeaderOffset = { [weak self] offset, listTransition in
guard let strongSelf = self, let layout = strongSelf.validLayout else {
return
}
let transition = strongSelf.forceHeaderTransition ?? listTransition
strongSelf.forceHeaderTransition = nil
let topOffset = offset
transition.updateFrame(node: strongSelf.contentHeaderContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: topOffset - headerHeight), size: CGSize(width: layout.size.width, height: headerHeight)))
transition.updateFrame(node: strongSelf.contentHeaderContainerBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: layout.size.width, height: headerHeight)))
transition.updateFrame(node: strongSelf.contentHeaderContainerSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: headerHeight), size: CGSize(width: layout.size.width, height: UIScreenPixel)))
if let placeholderNode = strongSelf.placeholderNode {
transition.updateFrame(node: placeholderNode, frame: CGRect(origin: CGPoint(x: 0.0, y: topOffset), size: placeholderNode.bounds.size))
}
transition.updateFrame(node: strongSelf.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: topOffset - headerHeight / 2.0), size: CGSize(width: layout.size.width, height: layout.size.height + 300.0)))
}
self.disposable.set((self.listContext.state
|> deliverOnMainQueue).start(next: { [weak self] state in
self?.updateState(state)
}))
}
deinit {
self.disposable.dispose()
}
override func didLoad() {
super.didLoad()
self.dimNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimNodeTapGesture)))
}
func containerLayoutUpdated(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
let isFirstLayout = self.validLayout == nil
self.validLayout = layout
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
transition.updateBounds(node: self.listNode, bounds: CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height))
transition.updatePosition(node: self.listNode, position: CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0))
var currentCategoryItemCount = 0
if let currentState = self.currentState {
for (category, categoryState) in currentState.states {
if category == self.currentCategory {
currentCategoryItemCount = categoryState.count
break
}
}
}
var insets = UIEdgeInsets()
insets.top = topInsetForLayout(layout: layout, itemCount: currentCategoryItemCount)
insets.bottom = layout.intrinsicInsets.bottom
if let placeholderNode = self.placeholderNode, !self.placeholderNodeIsAnimatingOut {
let placeholderHeight = min(CGFloat(currentCategoryItemCount) * itemHeight, layout.size.height) + UIScreenPixel
placeholderNode.frame = CGRect(origin: placeholderNode.frame.origin, size: CGSize(width: layout.size.width, height: placeholderHeight))
placeholderNode.updateLayout(size: CGSize(width: layout.size.width, height: placeholderHeight))
}
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, duration: duration, curve: curve), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
let sideInset: CGFloat = 12.0
let spacing: CGFloat = 6.0
var leftX = sideInset
for itemNode in self.categoryItemNodes {
let itemSize = itemNode.updateLayout()
itemNode.frame = CGRect(origin: CGPoint(x: leftX, y: 0.0), size: itemSize)
leftX += spacing + itemSize.width
}
leftX += sideInset
self.categoryScrollNode.view.contentSize = CGSize(width: leftX, height: 60.0)
self.categoryScrollNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: 60.0))
if isFirstLayout {
while !self.enqueuedTransactions.isEmpty {
self.dequeueTransaction()
}
}
}
func animateIn() {
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
self.dimNode.layer.animatePosition(from: CGPoint(x: self.dimNode.position.x, y: self.dimNode.position.y - self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in
})
self.layer.animatePosition(from: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), to: self.layer.position, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in
})
}
func animateOut(completion: @escaping () -> Void) {
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
self.dimNode.layer.animatePosition(from: self.dimNode.position, to: CGPoint(x: self.dimNode.position.x, y: self.dimNode.position.y - self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false)
self.layer.animatePosition(from: self.layer.position, to: CGPoint(x: self.layer.position.x, y: self.layer.position.y + self.layer.bounds.size.height), duration: 0.2, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue, removeOnCompletion: false, completion: { _ in
completion()
})
}
func updateState(_ state: MessageReactionListState) {
if self.currentState != state {
self.currentState = state
self.updateItems()
if let validLayout = self.validLayout {
self.containerLayoutUpdated(layout: validLayout, transition: .immediate)
}
}
}
private var currentEntries: [MessageReactionListEntry]?
private func updateItems() {
var entries: [MessageReactionListEntry] = []
var index = 0
let states = self.currentState?.states ?? []
for (category, categoryState) in states {
if self.categoryItemNodes.count <= index {
let itemNode = MessageReactionCategoryNode(theme: self.presentationData.theme, category: category, count: categoryState.count, action: { [weak self] in
self?.setCategory(category)
})
self.categoryItemNodes.append(itemNode)
self.categoryScrollNode.addSubnode(itemNode)
if category == self.currentCategory {
itemNode.isSelected = true
} else {
itemNode.isSelected = false
}
}
if category == self.currentCategory {
for item in categoryState.items {
entries.append(MessageReactionListEntry(index: entries.count, item: item))
}
}
index += 1
}
let transaction = preparedTransition(from: self.currentEntries ?? [], to: entries, context: self.context, presentationData: self.presentationData)
let previousWasEmpty = self.currentEntries == nil || self.currentEntries?.count == 0
let isEmpty = entries.isEmpty
self.currentEntries = entries
self.enqueuedTransactions.append(transaction)
self.dequeueTransaction()
if previousWasEmpty && !isEmpty {
if let placeholderNode = self.placeholderNode {
self.placeholderNodeIsAnimatingOut = true
placeholderNode.allowsGroupOpacity = true
placeholderNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { [weak self] _ in
guard let strongSelf = self else {
return
}
strongSelf.placeholderNode?.removeFromSupernode()
strongSelf.placeholderNode = nil
})
}
self.listNode.forEachItemNode({ itemNode in
itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.18)
})
}
}
func setCategory(_ category: MessageReactionListCategory) {
if self.currentCategory != category {
self.currentCategory = category
for itemNode in self.categoryItemNodes {
itemNode.isSelected = category == itemNode.category
}
//self.forceHeaderTransition = .animated(duration: 0.3, curve: .spring)
if let validLayout = self.validLayout {
self.containerLayoutUpdated(layout: validLayout, transition: .animated(duration: 0.3, curve: .spring))
}
self.updateItems()
}
}
private func dequeueTransaction() {
guard let layout = self.validLayout, let transaction = self.enqueuedTransactions.first else {
return
}
self.enqueuedTransactions.remove(at: 0)
var options = ListViewDeleteAndInsertOptions()
options.insert(.Synchronous)
options.insert(.PreferSynchronousResourceLoading)
options.insert(.PreferSynchronousDrawing)
var currentCategoryItemCount = 0
if let currentState = self.currentState {
for (category, categoryState) in currentState.states {
if category == self.currentCategory {
currentCategoryItemCount = categoryState.count
break
}
}
}
var insets = UIEdgeInsets()
insets.top = topInsetForLayout(layout: layout, itemCount: currentCategoryItemCount)
insets.bottom = layout.intrinsicInsets.bottom
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: self.listNode.bounds.size, insets: insets, duration: 0.3, curve: .Default(duration: 0.3))
self.listNode.transaction(deleteIndices: transaction.deletions, insertIndicesAndItems: transaction.insertions, updateIndicesAndItems: transaction.updates, options: options, updateSizeAndInsets: updateSizeAndInsets, updateOpaqueState: nil, completion: { [weak self] _ in
self?.isReady.set(.single(true))
})
}
@objc private func dimNodeTapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
self.dismiss()
}
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
for itemNode in self.categoryItemNodes {
if let result = itemNode.hitTest(self.view.convert(point, to: itemNode.view), with: event) {
return result
}
}
if let result = self.listNode.hitTest(self.view.convert(point, to: self.listNode.view), with: event) {
return result
}
if point.y >= self.contentHeaderContainerNode.frame.minY && point.y < self.bounds.height {
return self.listNode.view
}
if point.y >= 0 && point.y < self.contentHeaderContainerNode.frame.minY {
return self.dimNode.view
}
return nil
}
}

View File

@ -1,81 +0,0 @@
import Foundation
import AsyncDisplayKit
import Display
import TelegramPresentationData
import TelegramCore
import SyncCore
final class MessageReactionListLoadingPlaceholder: ASDisplayNode {
private let theme: PresentationTheme
private let itemHeight: CGFloat
private let itemImage: UIImage?
private let backgroundNode: ASDisplayNode
private let separatorNode: ASDisplayNode
private let highlightNode: ASImageNode
private var itemNodes: [ASImageNode] = []
init(theme: PresentationTheme, itemHeight: CGFloat) {
self.theme = theme
self.itemHeight = itemHeight
self.backgroundNode = ASDisplayNode()
self.backgroundNode.backgroundColor = UIColor(white: 0.92, alpha: 1.0)
self.separatorNode = ASDisplayNode()
self.separatorNode.backgroundColor = theme.list.itemPlainSeparatorColor
self.highlightNode = ASImageNode()
self.highlightNode.displaysAsynchronously = false
self.highlightNode.displayWithoutProcessing = true
let leftInset: CGFloat = 15.0
let avatarSize: CGFloat = 40.0
let avatarSpacing: CGFloat = 11.0
let contentWidth: CGFloat = 4.0
let contentHeight: CGFloat = 14.0
let rightInset: CGFloat = 54.0
self.itemImage = generateImage(CGSize(width: leftInset + avatarSize + avatarSpacing + contentWidth + rightInset, height: itemHeight), rotatedContext: { size, context in
context.setFillColor(theme.actionSheet.opaqueItemBackgroundColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: size))
context.setFillColor(theme.list.itemPlainSeparatorColor.cgColor)
context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: UIScreenPixel)))
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.fillEllipse(in: CGRect(origin: CGPoint(x: leftInset, y: floor((itemHeight - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize)))
let contentOrigin = leftInset + avatarSize + avatarSpacing
context.fill(CGRect(origin: CGPoint(x: contentOrigin, y: floor((size.height - contentHeight) / 2.0)), size: CGSize(width: size.width - contentOrigin - rightInset, height: contentHeight)))
})?.stretchableImage(withLeftCapWidth: Int(leftInset + avatarSize + avatarSpacing + 1), topCapHeight: 0)
super.init()
self.addSubnode(self.backgroundNode)
self.addSubnode(self.highlightNode)
self.addSubnode(self.separatorNode)
}
func updateLayout(size: CGSize) {
self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size)
var verticalOffset: CGFloat = 0.0
var index = 0
while verticalOffset < size.height - 1.0 {
if self.itemNodes.count >= index {
let itemNode = ASImageNode()
itemNode.image = self.itemImage
self.itemNodes.append(itemNode)
self.addSubnode(itemNode)
}
self.itemNodes[index].frame = CGRect(origin: CGPoint(x: 0.0, y: verticalOffset), size: CGSize(width: size.width, height: self.itemHeight))
verticalOffset += self.itemHeight
index += 1
}
self.separatorNode.frame = CGRect(origin: CGPoint(x: 0.0, y: verticalOffset), size: CGSize(width: size.width, height: UIScreenPixel))
if index < self.itemNodes.count {
for i in index ..< self.itemNodes.count {
self.itemNodes[i].removeFromSupernode()
}
self.itemNodes.removeLast(self.itemNodes.count - index)
}
}
}

View File

@ -36,7 +36,7 @@ public func peerInfoProfilePhotos(context: AccountContext, peerId: PeerId) -> Si
if let firstEntry = entries.first {
return context.account.postbox.loadedPeerWithId(peerId)
|> mapToSignal { peer -> Signal<(Bool, [AvatarGalleryEntry])?, NoError>in
return fetchedAvatarGalleryEntries(account: context.account, peer: peer, firstEntry: firstEntry)
return fetchedAvatarGalleryEntries(engine: context.engine, account: context.account, peer: peer, firstEntry: firstEntry)
|> map(Optional.init)
}
} else {
@ -210,7 +210,7 @@ public func initialAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<
}
}
public func fetchedAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<[AvatarGalleryEntry], NoError> {
public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account, peer: Peer) -> Signal<[AvatarGalleryEntry], NoError> {
return initialAvatarGalleryEntries(account: account, peer: peer)
|> map { entries -> [AvatarGalleryEntry] in
return entries ?? []
@ -218,7 +218,7 @@ public func fetchedAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<
|> mapToSignal { initialEntries in
return .single(initialEntries)
|> then(
requestPeerPhotos(postbox: account.postbox, network: account.network, peerId: peer.id)
engine.peers.requestPeerPhotos(peerId: peer.id)
|> map { photos -> [AvatarGalleryEntry] in
var result: [AvatarGalleryEntry] = []
if photos.isEmpty {
@ -269,11 +269,11 @@ public func fetchedAvatarGalleryEntries(account: Account, peer: Peer) -> Signal<
}
}
public func fetchedAvatarGalleryEntries(account: Account, peer: Peer, firstEntry: AvatarGalleryEntry) -> Signal<(Bool, [AvatarGalleryEntry]), NoError> {
public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account, peer: Peer, firstEntry: AvatarGalleryEntry) -> Signal<(Bool, [AvatarGalleryEntry]), NoError> {
let initialEntries = [firstEntry]
return Signal<(Bool, [AvatarGalleryEntry]), NoError>.single((false, initialEntries))
|> then(
requestPeerPhotos(postbox: account.postbox, network: account.network, peerId: peer.id)
engine.peers.requestPeerPhotos(peerId: peer.id)
|> map { photos -> (Bool, [AvatarGalleryEntry]) in
var result: [AvatarGalleryEntry] = []
let initialEntries = [firstEntry]
@ -403,7 +403,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr
if let remoteEntries = remoteEntries {
remoteEntriesSignal = remoteEntries.get()
} else {
remoteEntriesSignal = fetchedAvatarGalleryEntries(account: context.account, peer: peer)
remoteEntriesSignal = fetchedAvatarGalleryEntries(engine: context.engine, account: context.account, peer: peer)
}
let initialSignal = initialAvatarGalleryEntries(account: context.account, peer: peer)

View File

@ -889,7 +889,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
return
}
transferOwnershipDisposable.set((checkOwnershipTranfserAvailability(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, memberId: adminId) |> deliverOnMainQueue).start(error: { error in
transferOwnershipDisposable.set((context.engine.peers.checkOwnershipTranfserAvailability(memberId: adminId) |> deliverOnMainQueue).start(error: { error in
let controller = channelOwnershipTransferController(context: context, peer: peer, member: member, initialError: error, present: { c, a in
presentControllerImpl?(c, a)
}, completion: { upgradedPeerId in

View File

@ -665,7 +665,7 @@ public func channelAdminsController(context: AccountContext, peerId initialPeerI
|> deliverOnMainQueue).start(next: { peerId in
if peerId.namespace == Namespaces.Peer.CloudChannel {
var didReportLoadCompleted = false
let membersAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?) = context.peerChannelMemberCategoriesContextsManager.admins(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) { membersState in
let membersAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId) { membersState in
if case .loading = membersState.loadingState, membersState.list.isEmpty {
adminsPromise.set(.single(nil))
} else {

View File

@ -506,7 +506,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
state.updating = true
return state
}
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: nil)
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: nil)
|> deliverOnMainQueue).start(error: { _ in
}, completed: {
@ -667,7 +667,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
guard let upgradedPeerId = upgradedPeerId else {
return .single(nil)
}
return context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: upgradedPeerId, memberId: memberId, bannedRights: cleanResolvedRights)
return context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: upgradedPeerId, memberId: memberId, bannedRights: cleanResolvedRights)
|> mapToSignal { _ -> Signal<PeerId?, NoError> in
return .complete()
}
@ -700,7 +700,7 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
}
}))
} else {
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: cleanResolvedRights)
updateRightsDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: cleanResolvedRights)
|> deliverOnMainQueue).start(error: { _ in
}, completed: {

View File

@ -324,7 +324,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let progress = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
presentControllerImpl?(progress, nil)
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> deliverOnMainQueue).start(error: { [weak progress] _ in
progress?.dismiss()
dismissController?()
@ -343,7 +343,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
return $0.withUpdatedRemovingPeerId(memberId)
}
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: nil) |> deliverOnMainQueue).start(error: { _ in
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: nil) |> deliverOnMainQueue).start(error: { _ in
updateState {
return $0.withUpdatedRemovingPeerId(nil)
}
@ -388,7 +388,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
updateState {
return $0.withUpdatedRemovingPeerId(memberId)
}
let signal = context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: nil)
let signal = context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: nil)
|> ignoreValues
|> then(
context.peerChannelMemberCategoriesContextsManager.addMember(account: context.account, peerId: peerId, memberId: memberId)
@ -418,7 +418,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
return $0.withUpdatedRemovingPeerId(memberId)
}
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: nil) |> deliverOnMainQueue).start(error: { _ in
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: nil) |> deliverOnMainQueue).start(error: { _ in
updateState {
return $0.withUpdatedRemovingPeerId(nil)
}
@ -437,7 +437,7 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
})
})
let (listDisposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.banned(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { listState in
let (listDisposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.banned(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { listState in
if case .loading(true) = listState.loadingState, listState.list.isEmpty {
blacklistPromise.set(.single(nil))
} else {

View File

@ -230,7 +230,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
let groupPeers = Promise<[Peer]?>()
groupPeers.set(.single(nil)
|> then(
availableGroupsForChannelDiscussion(postbox: context.account.postbox, network: context.account.network)
context.engine.peers.availableGroupsForChannelDiscussion()
|> map(Optional.init)
|> `catch` { _ -> Signal<[Peer]?, NoError> in
return .single(nil)
@ -260,7 +260,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
}
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
pushControllerImpl?(context.sharedContext.makeCreateGroupController(context: context, peerIds: [], initialTitle: peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + " Chat", mode: .supergroup, completion: { groupId, dismiss in
var applySignal = updateGroupDiscussionForChannel(network: context.account.network, postbox: context.account.postbox, channelId: peerId, groupId: groupId)
var applySignal = context.engine.peers.updateGroupDiscussionForChannel(channelId: peerId, groupId: groupId)
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -358,13 +358,13 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
})
}
return updateGroupDiscussionForChannel(network: context.account.network, postbox: context.account.postbox, channelId: peerId, groupId: resultPeerId)
return context.engine.peers.updateGroupDiscussionForChannel(channelId: peerId, groupId: resultPeerId)
}
|> castError(ChannelDiscussionGroupError.self)
|> switchToLatest
}
} else {
applySignal = updateGroupDiscussionForChannel(network: context.account.network, postbox: context.account.postbox, channelId: peerId, groupId: groupId)
applySignal = context.engine.peers.updateGroupDiscussionForChannel(channelId: peerId, groupId: groupId)
}
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
@ -413,7 +413,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
case .groupHistoryIsCurrentlyPrivate:
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Channel_DiscussionGroup_MakeHistoryPublic, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Channel_DiscussionGroup_MakeHistoryPublicProceed, action: {
var applySignal: Signal<Bool, ChannelDiscussionGroupError> = updateChannelHistoryAvailabilitySettingsInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: updatedPeerId ?? groupId, historyAvailableForNewMembers: true)
var applySignal: Signal<Bool, ChannelDiscussionGroupError> = context.engine.peers.updateChannelHistoryAvailabilitySettingsInteractively(peerId: updatedPeerId ?? groupId, historyAvailableForNewMembers: true)
|> mapError { _ -> ChannelDiscussionGroupError in
return .generic
}
@ -421,7 +421,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
return .complete()
}
|> then(
updateGroupDiscussionForChannel(network: context.account.network, postbox: context.account.postbox, channelId: peerId, groupId: updatedPeerId ?? groupId)
context.engine.peers.updateGroupDiscussionForChannel(channelId: peerId, groupId: updatedPeerId ?? groupId)
)
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
@ -502,7 +502,7 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
return
}
var applySignal = updateGroupDiscussionForChannel(network: context.account.network, postbox: context.account.postbox, channelId: applyPeerId, groupId: nil)
var applySignal = context.engine.peers.updateGroupDiscussionForChannel(channelId: applyPeerId, groupId: nil)
var cancelImpl: (() -> Void)?
let progressSignal = Signal<Never, NoError> { subscriber in
let presentationData = context.sharedContext.currentPresentationData.with { $0 }

View File

@ -836,11 +836,11 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
}
let controller = notificationMuteSettingsController(presentationData: presentationData, notificationSettings: globalSettings.effective.groupChats, soundSettings: soundSettings, openSoundSettings: {
let controller = notificationSoundSelectionController(context: context, isModal: true, currentSound: peerSettings.messageSound, defaultSound: globalSettings.effective.groupChats.sound, completion: { sound in
let _ = updatePeerNotificationSoundInteractive(account: context.account, peerId: peerId, sound: sound).start()
let _ = context.engine.peers.updatePeerNotificationSoundInteractive(peerId: peerId, sound: sound).start()
})
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}, updateSettings: { value in
changeMuteSettingsDisposable.set(updatePeerMuteSetting(account: context.account, peerId: peerId, muteInterval: value).start())
changeMuteSettingsDisposable.set(context.engine.peers.updatePeerMuteSetting(peerId: peerId, muteInterval: value).start())
})
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
})
@ -918,7 +918,7 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
}, aboutLinkAction: { action, itemLink in
aboutLinkActionImpl?(action, itemLink)
}, toggleSignatures: { enabled in
actionsDisposable.add(toggleShouldChannelMessagesSignatures(account: context.account, peerId: peerId, enabled: enabled).start())
actionsDisposable.add(context.engine.peers.toggleShouldChannelMessagesSignatures(peerId: peerId, enabled: enabled).start())
})
var wasEditing: Bool?

View File

@ -443,7 +443,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
return $0.withUpdatedRemovingPeerId(memberId)
}
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> deliverOnMainQueue).start(completed: {
updateState {
return $0.withUpdatedRemovingPeerId(nil)
@ -462,7 +462,7 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
let peerView = context.account.viewTracker.peerView(peerId)
let (disposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
let (disposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
peersPromise.set(.single(state.list))
})
actionsDisposable.add(disposable)

View File

@ -231,13 +231,13 @@ private func categorySignal(context: AccountContext, peerId: PeerId, category: G
}
switch category {
case .admins:
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.admins(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
case .contacts:
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
case .bots:
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.bots(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.bots(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
case .members:
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: processListState)
}
let (disposable, _) = disposableAndLoadMoreControl
@ -452,7 +452,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
}
}
return context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
return context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max))
|> afterDisposed {
Queue.mainQueue().async {
updateState { state in
@ -479,7 +479,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
}
}
return removePeerMember(account: context.account, peerId: peerId, memberId: memberId)
return context.engine.peers.removePeerMember(peerId: peerId, memberId: memberId)
|> deliverOnMainQueue
|> afterDisposed {
updateState { state in
@ -608,7 +608,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
switch mode {
case .searchMembers, .banAndPromoteActions:
foundGroupMembers = Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext(state.list)
}
@ -619,11 +619,11 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
foundMembers = .single([])
case .inviteActions:
foundGroupMembers = .single([])
foundMembers = channelMembers(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, category: .recent(.search(query)))
foundMembers = context.engine.peers.channelMembers(peerId: peerId, category: .recent(.search(query)))
|> map { $0 ?? [] }
case .searchAdmins:
foundGroupMembers = Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.admins(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext(state.list)
}
@ -633,7 +633,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
foundMembers = .single([])
case .searchBanned:
foundGroupMembers = Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.restricted(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.restricted(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext(state.list)
subscriber.putCompletion()
@ -643,7 +643,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
}
|> runOn(Queue.mainQueue())
foundMembers = Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext(state.list.filter({ participant in
return participant.peer.id != context.account.peerId
@ -655,7 +655,7 @@ public final class ChannelMembersSearchContainerNode: SearchDisplayControllerCon
|> runOn(Queue.mainQueue())
case .searchKicked:
foundGroupMembers = Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.banned(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.banned(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext(state.list)
subscriber.putCompletion()

View File

@ -419,7 +419,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
} else {
let membersState = Promise<ChannelMemberListState>()
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
membersState.set(.single(state))
})

View File

@ -455,7 +455,7 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
let signal: Signal<PeerId?, ChannelOwnershipTransferError>
if let peer = peer as? TelegramChannel {
signal = context.peerChannelMemberCategoriesContextsManager.transferOwnership(account: context.account, peerId: peer.id, memberId: member.id, password: contentNode.password) |> mapToSignal { _ in
signal = context.peerChannelMemberCategoriesContextsManager.transferOwnership(engine: context.engine, peerId: peer.id, memberId: member.id, password: contentNode.password) |> mapToSignal { _ in
return .complete()
}
|> then(.single(nil))
@ -475,7 +475,7 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
guard let upgradedPeerId = upgradedPeerId else {
return .fail(.generic)
}
return context.peerChannelMemberCategoriesContextsManager.transferOwnership(account: context.account, peerId: upgradedPeerId, memberId: member.id, password: contentNode.password) |> mapToSignal { _ in
return context.peerChannelMemberCategoriesContextsManager.transferOwnership(engine: context.engine, peerId: upgradedPeerId, memberId: member.id, password: contentNode.password) |> mapToSignal { _ in
return .complete()
}
|> then(.single(upgradedPeerId))

View File

@ -536,7 +536,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
peersPromise.set(.single((peerId, nil)))
} else {
var loadCompletedCalled = false
let disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.restricted(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
let disposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.restricted(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
if case .loading(true) = state.loadingState, !updated {
peersPromise.set(.single((peerId, nil)))
} else {
@ -594,7 +594,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
}
let state = stateValue.with { $0 }
if let modifiedRightsFlags = state.modifiedRightsFlags {
updateDefaultRightsDisposable.set((updateDefaultChannelMemberBannedRights(account: context.account, peerId: view.peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), untilDate: Int32.max))
updateDefaultRightsDisposable.set((context.engine.peers.updateDefaultChannelMemberBannedRights(peerId: view.peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), untilDate: Int32.max))
|> deliverOnMainQueue).start())
}
} else if let group = view.peers[view.peerId] as? TelegramGroup, let _ = view.cachedData as? CachedGroupData {
@ -624,7 +624,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
}
let state = stateValue.with { $0 }
if let modifiedRightsFlags = state.modifiedRightsFlags {
updateDefaultRightsDisposable.set((updateDefaultChannelMemberBannedRights(account: context.account, peerId: view.peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), untilDate: Int32.max))
updateDefaultRightsDisposable.set((context.engine.peers.updateDefaultChannelMemberBannedRights(peerId: view.peerId, rights: TelegramChatBannedRights(flags: completeRights(modifiedRightsFlags), untilDate: Int32.max))
|> deliverOnMainQueue).start())
}
}
@ -679,7 +679,7 @@ public func channelPermissionsController(context: AccountContext, peerId origina
return state
}
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: context.account, peerId: peerId, memberId: memberId, bannedRights: nil)
removePeerDisposable.set((context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: context.engine, peerId: peerId, memberId: memberId, bannedRights: nil)
|> deliverOnMainQueue).start(error: { _ in
updateState { state in
var state = state

View File

@ -1104,7 +1104,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
switch subject {
case let .create(peer, _, share, shareViaException, _):
if share, filteredPhoneNumbers.count <= 1, let peer = peer {
addContactDisposable.set((addContactInteractively(account: context.account, peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
addContactDisposable.set((context.engine.contacts.addContactInteractively(peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
|> deliverOnMainQueue).start(error: { _ in
presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}, completed: {
@ -1138,7 +1138,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
switch subject {
case let .create(peer, _, share, shareViaException, _):
if share, let peer = peer {
return addContactInteractively(account: context.account, peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
return context.engine.contacts.addContactInteractively(peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
|> mapToSignal { _ -> Signal<(DeviceContactStableId, DeviceContactExtendedData, Peer?)?, AddContactError> in
return .complete()
}
@ -1153,7 +1153,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
break
}
return importContact(account: context.account, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers[0].value)
return context.engine.contacts.importContact(firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers[0].value)
|> castError(AddContactError.self)
|> mapToSignal { peerId -> Signal<(DeviceContactStableId, DeviceContactExtendedData, Peer?)?, AddContactError> in
if let peerId = peerId {

View File

@ -163,7 +163,7 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
if peerId.namespace == Namespaces.Peer.CloudGroup {
let signal = context.engine.peers.convertGroupToSupergroup(peerId: peerId)
|> mapToSignal { upgradedPeerId -> Signal<PeerId?, ConvertGroupToSupergroupError> in
return updateChannelHistoryAvailabilitySettingsInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: upgradedPeerId, historyAvailableForNewMembers: value)
return context.engine.peers.updateChannelHistoryAvailabilitySettingsInteractively(peerId: upgradedPeerId, historyAvailableForNewMembers: value)
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
}
@ -190,7 +190,7 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
}
}))
} else {
applyDisposable.set((updateChannelHistoryAvailabilitySettingsInteractively(postbox: context.account.postbox, network: context.account.network, accountStateManager: context.account.stateManager, peerId: peerId, historyAvailableForNewMembers: value)
applyDisposable.set((context.engine.peers.updateChannelHistoryAvailabilitySettingsInteractively(peerId: peerId, historyAvailableForNewMembers: value)
|> deliverOnMainQueue).start(completed: {
dismissImpl?()
}))

View File

@ -448,7 +448,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
state.isSaving = true
return state
}
saveDisposable.set((updateGroupSpecificStickerset(postbox: context.account.postbox, network: context.account.network, peerId: peerId, info: info)
saveDisposable.set((context.engine.peers.updateGroupSpecificStickerset(peerId: peerId, info: info)
|> deliverOnMainQueue).start(error: { _ in
updateState { state in
var state = state

View File

@ -18,7 +18,7 @@ public func searchPeerMembers(context: AccountContext, peerId: PeerId, chatLocat
|> mapToSignal { cachedData -> Signal<([Peer], Bool), NoError> in
if case .peer = chatLocation, let cachedData = cachedData, let memberCount = cachedData.participantsSummary.memberCount, memberCount <= 64 {
return Signal { subscriber in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, requestUpdate: false, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, requestUpdate: false, updated: { state in
if case .ready = state.loadingState {
let normalizedQuery = query.lowercased()
subscriber.putNext((state.list.compactMap { participant -> Peer? in
@ -54,7 +54,7 @@ public func searchPeerMembers(context: AccountContext, peerId: PeerId, chatLocat
return Signal { subscriber in
switch chatLocation {
case let .peer(peerId):
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query.isEmpty ? nil : query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: query.isEmpty ? nil : query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext((state.list.compactMap { participant in
if participant.peer.isDeleted {
@ -69,7 +69,7 @@ public func searchPeerMembers(context: AccountContext, peerId: PeerId, chatLocat
disposable.dispose()
}
case let .replyThread(replyThreadMessage):
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: replyThreadMessage.messageId, searchQuery: query.isEmpty ? nil : query, updated: { state in
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: replyThreadMessage.messageId, searchQuery: query.isEmpty ? nil : query, updated: { state in
if case .ready = state.loadingState {
subscriber.putNext((state.list.compactMap { participant in
if participant.peer.isDeleted {
@ -117,6 +117,6 @@ public func searchPeerMembers(context: AccountContext, peerId: PeerId, chatLocat
}
}
} else {
return searchGroupMembers(postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, query: query)
return context.engine.peers.searchGroupMembers(peerId: peerId, query: query)
}
}

View File

@ -780,16 +780,16 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
let presentationData = context.sharedContext.currentPresentationData.modify {$0}
let updatePeerSound: (PeerId, PeerMessageSound) -> Signal<Void, NoError> = { peerId, sound in
return updatePeerNotificationSoundInteractive(account: context.account, peerId: peerId, sound: sound) |> deliverOnMainQueue
return context.engine.peers.updatePeerNotificationSoundInteractive(peerId: peerId, sound: sound) |> deliverOnMainQueue
}
let updatePeerNotificationInterval: (PeerId, Int32?) -> Signal<Void, NoError> = { peerId, muteInterval in
return updatePeerMuteSetting(account: context.account, peerId: peerId, muteInterval: muteInterval) |> deliverOnMainQueue
return context.engine.peers.updatePeerMuteSetting(peerId: peerId, muteInterval: muteInterval) |> deliverOnMainQueue
}
let updatePeerDisplayPreviews:(PeerId, PeerNotificationDisplayPreviews) -> Signal<Void, NoError> = {
peerId, displayPreviews in
return updatePeerDisplayPreviewsSetting(account: context.account, peerId: peerId, displayPreviews: displayPreviews) |> deliverOnMainQueue
return context.engine.peers.updatePeerDisplayPreviewsSetting(peerId: peerId, displayPreviews: displayPreviews) |> deliverOnMainQueue
}
self.backgroundColor = presentationData.theme.list.blocksBackgroundColor
@ -842,13 +842,11 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
updateNotificationsView({})
})
}, removePeerFromExceptions: {
let _ = (context.account.postbox.transaction { transaction -> Peer? in
updatePeerMuteSetting(transaction: transaction, peerId: peerId, muteInterval: nil)
updatePeerDisplayPreviewsSetting(transaction: transaction, peerId: peerId, displayPreviews: .default)
updatePeerNotificationSoundInteractive(transaction: transaction, peerId: peerId, sound: .default)
let _ = (context.engine.peers.removeCustomNotificationSettings(peerIds: [peerId])
|> map { _ -> Peer? in }
|> then(context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}
|> deliverOnMainQueue).start(next: { peer in
})).start(next: { peer in
guard let peer = peer else {
return
}
@ -917,11 +915,7 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
updateState { value in
return value.withUpdatedPeerMuteInterval(peer, nil).withUpdatedPeerSound(peer, .default).withUpdatedPeerDisplayPreviews(peer, .default)
}
_ = (context.account.postbox.transaction { transaction in
updatePeerNotificationSoundInteractive(transaction: transaction, peerId: peer.id, sound: .default)
updatePeerMuteSetting(transaction: transaction, peerId: peer.id, muteInterval: nil)
updatePeerDisplayPreviewsSetting(transaction: transaction, peerId: peer.id, displayPreviews: .default)
}
let _ = (context.engine.peers.removeCustomNotificationSettings(peerIds: [peer.id])
|> deliverOnMainQueue).start(completed: {
updateNotificationsView({})
})
@ -953,13 +947,7 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
}
return state
}
let _ = (context.account.postbox.transaction { transaction -> Void in
for value in values {
updatePeerNotificationSoundInteractive(transaction: transaction, peerId: value.peer.id, sound: .default)
updatePeerMuteSetting(transaction: transaction, peerId: value.peer.id, muteInterval: nil)
updatePeerDisplayPreviewsSetting(transaction: transaction, peerId: value.peer.id, displayPreviews: .default)
}
}
let _ = (context.engine.peers.removeCustomNotificationSettings(peerIds: values.map(\.peer.id))
|> deliverOnMainQueue).start(completed: {
updateNotificationsView({})
})

View File

@ -426,7 +426,7 @@ public func dataPrivacyController(context: AccountContext) -> ViewController {
})
}).start()
actionsDisposable.add((deleteAllContacts(account: context.account)
actionsDisposable.add((context.engine.contacts.deleteAllContacts()
|> deliverOnMainQueue).start(completed: {
updateState { state in
var state = state

View File

@ -506,11 +506,11 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
actionsDisposable.add(updateAutoArchiveDisposable)
let privacySettingsPromise = Promise<AccountPrivacySettings?>()
privacySettingsPromise.set(.single(initialSettings) |> then(requestAccountPrivacySettings(account: context.account) |> map(Optional.init)))
privacySettingsPromise.set(.single(initialSettings) |> then(context.engine.privacy.requestAccountPrivacySettings() |> map(Optional.init)))
let blockedPeersContext = blockedPeersContext ?? BlockedPeersContext(account: context.account)
let activeSessionsContext = activeSessionsContext ?? ActiveSessionsContext(account: context.account)
let webSessionsContext = webSessionsContext ?? WebSessionsContext(account: context.account)
let activeSessionsContext = activeSessionsContext ?? context.engine.privacy.activeSessions()
let webSessionsContext = webSessionsContext ?? context.engine.privacy.webSessions()
let blockedPeersState = Promise<BlockedPeersContextState>()
blockedPeersState.set(blockedPeersContext.state)
@ -779,7 +779,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
return .complete()
}
updateAutoArchiveDisposable.set((updateAccountAutoArchiveChats(account: context.account, value: archiveValue)
updateAutoArchiveDisposable.set((context.engine.privacy.updateAccountAutoArchiveChats(value: archiveValue)
|> mapToSignal { _ -> Signal<Void, NoError> in }
|> then(applyTimeout)
|> deliverOnMainQueue).start(completed: {
@ -817,7 +817,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting
}
return .complete()
}
updateAccountTimeoutDisposable.set((updateAccountRemovalTimeout(account: context.account, timeout: timeout)
updateAccountTimeoutDisposable.set((context.engine.privacy.updateAccountRemovalTimeout(timeout: timeout)
|> then(applyTimeout)
|> deliverOnMainQueue).start(completed: {
updateState { state in

View File

@ -1038,14 +1038,14 @@ func selectivePrivacySettingsController(context: AccountContext, kind: Selective
type = .phoneNumber
}
let updateSettingsSignal = updateSelectiveAccountPrivacySettings(account: context.account, type: type, settings: settings)
let updateSettingsSignal = context.engine.privacy.updateSelectiveAccountPrivacySettings(type: type, settings: settings)
var updateCallP2PSettingsSignal: Signal<Void, NoError> = Signal.complete()
if let callP2PSettings = callP2PSettings {
updateCallP2PSettingsSignal = updateSelectiveAccountPrivacySettings(account: context.account, type: .voiceCallsP2P, settings: callP2PSettings)
updateCallP2PSettingsSignal = context.engine.privacy.updateSelectiveAccountPrivacySettings(type: .voiceCallsP2P, settings: callP2PSettings)
}
var updatePhoneDiscoverySignal: Signal<Void, NoError> = Signal.complete()
if let phoneDiscoveryEnabled = phoneDiscoveryEnabled {
updatePhoneDiscoverySignal = updatePhoneNumberDiscovery(account: context.account, value: phoneDiscoveryEnabled)
updatePhoneDiscoverySignal = context.engine.privacy.updatePhoneNumberDiscovery(value: phoneDiscoveryEnabled)
}
let _ = (combineLatest(updateSettingsSignal, updateCallP2PSettingsSignal, updatePhoneDiscoverySignal)

View File

@ -430,7 +430,7 @@ private func privacySearchableItems(context: AccountContext, privacySettings: Ac
if let privacySettings = privacySettings {
privacySignal = .single(privacySettings)
} else {
privacySignal = requestAccountPrivacySettings(account: context.account)
privacySignal = context.engine.privacy.requestAccountPrivacySettings()
}
let callsSignal: Signal<(VoiceCallSettings, VoipConfiguration)?, NoError>
if case .voiceCalls = kind {
@ -535,10 +535,10 @@ private func privacySearchableItems(context: AccountContext, privacySettings: Ac
present(.push, twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: true, data: nil)))
}),
activeSessionsContext == nil ? nil : SettingsSearchableItem(id: .privacy(9), title: strings.Settings_Devices, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_AuthSessions) + [strings.PrivacySettings_AuthSessions], icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
present(.push, recentSessionsController(context: context, activeSessionsContext: activeSessionsContext!, webSessionsContext: webSessionsContext ?? WebSessionsContext(account: context.account), websitesOnly: false))
present(.push, recentSessionsController(context: context, activeSessionsContext: activeSessionsContext!, webSessionsContext: webSessionsContext ?? context.engine.privacy.webSessions(), websitesOnly: false))
}),
webSessionsContext == nil ? nil : SettingsSearchableItem(id: .privacy(10), title: strings.PrivacySettings_WebSessions, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_AuthSessions), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
present(.push, recentSessionsController(context: context, activeSessionsContext: activeSessionsContext ?? ActiveSessionsContext(account: context.account), webSessionsContext: webSessionsContext ?? WebSessionsContext(account: context.account), websitesOnly: true))
present(.push, recentSessionsController(context: context, activeSessionsContext: activeSessionsContext ?? context.engine.privacy.activeSessions(), webSessionsContext: webSessionsContext ?? context.engine.privacy.webSessions(), websitesOnly: true))
}),
SettingsSearchableItem(id: .privacy(11), title: strings.PrivacySettings_DeleteAccountTitle, alternate: synonyms(strings.SettingsSearch_Synonyms_Privacy_DeleteAccountIfAwayFor), icon: icon, breadcrumbs: [strings.Settings_PrivacySettings], present: { context, _, present in
presentPrivacySettings(context, present, .accountTimeout)

View File

@ -1136,7 +1136,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
let rawAdminIds: Signal<Set<PeerId>, NoError>
if peerId.namespace == Namespaces.Peer.CloudChannel {
rawAdminIds = Signal { subscriber in
let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(postbox: accountContext.account.postbox, network: accountContext.account.network, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in
let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: accountContext.engine, postbox: accountContext.account.postbox, network: accountContext.account.network, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in
var peerIds = Set<PeerId>()
for item in list.list {
if let adminInfo = item.participant.adminInfo, adminInfo.rights.rights.contains(.canManageCalls) {
@ -1425,7 +1425,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
let peerId = strongSelf.peerId
if strongSelf.peerId.namespace == Namespaces.Peer.CloudChannel {
peerAdminIds = Signal { subscriber in
let (disposable, _) = strongSelf.accountContext.peerChannelMemberCategoriesContextsManager.admins(postbox: strongSelf.accountContext.account.postbox, network: strongSelf.accountContext.account.network, accountPeerId: strongSelf.accountContext.account.peerId, peerId: peerId, updated: { list in
let (disposable, _) = strongSelf.accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: strongSelf.accountContext.engine, postbox: strongSelf.accountContext.account.postbox, network: strongSelf.accountContext.account.network, accountPeerId: strongSelf.accountContext.account.peerId, peerId: peerId, updated: { list in
var peerIds = Set<PeerId>()
for item in list.list {
if let adminInfo = item.participant.adminInfo, adminInfo.rights.rights.contains(.canManageCalls) {
@ -1670,7 +1670,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
let rawAdminIds: Signal<Set<PeerId>, NoError>
if peerId.namespace == Namespaces.Peer.CloudChannel {
rawAdminIds = Signal { subscriber in
let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(postbox: accountContext.account.postbox, network: accountContext.account.network, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in
let (disposable, _) = accountContext.peerChannelMemberCategoriesContextsManager.admins(engine: accountContext.engine, postbox: accountContext.account.postbox, network: accountContext.account.network, accountPeerId: accountContext.account.peerId, peerId: peerId, updated: { list in
var peerIds = Set<PeerId>()
for item in list.list {
if let adminInfo = item.participant.adminInfo, adminInfo.rights.rights.contains(.canManageCalls) {

View File

@ -1711,7 +1711,7 @@ public final class VoiceChatController: ViewController {
return
}
let _ = strongSelf.context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(account: strongSelf.context.account, peerId: strongSelf.call.peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)).start()
let _ = strongSelf.context.peerChannelMemberCategoriesContextsManager.updateMemberBannedRights(engine: strongSelf.context.engine, peerId: strongSelf.call.peerId, memberId: peer.id, bannedRights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: Int32.max)).start()
strongSelf.call.removedPeer(peer.id)
strongSelf.presentUndoOverlay(content: .banned(text: strongSelf.presentationData.strings.VoiceChat_RemovedPeerText(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).0), action: { _ in return false })

View File

@ -4,7 +4,7 @@ import SwiftSignalKit
import SyncCore
public func currentWebDocumentsHostDatacenterId(postbox: Postbox, isTestingEnvironment: Bool) -> Signal<Int32, NoError> {
func currentWebDocumentsHostDatacenterId(postbox: Postbox, isTestingEnvironment: Bool) -> Signal<Int32, NoError> {
return postbox.transaction { transaction -> Int32 in
if let entry = transaction.getPreferencesEntry(key: PreferencesKeys.remoteStorageConfiguration) as? RemoteStorageConfiguration {
return entry.webDocumentsHostDatacenterId

View File

@ -1,82 +0,0 @@
import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
import SyncCore
public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedChannelParticipant], NoError> {
return account.postbox.transaction { transaction -> Signal<[RenderedChannelParticipant], NoError> in
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: 0))
|> retryRequest
|> mapToSignal { result -> Signal<[RenderedChannelParticipant], NoError> in
switch result {
case let .channelParticipants(count, participants, chats, users):
var items: [RenderedChannelParticipant] = []
var peers: [PeerId: Peer] = [:]
var presences:[PeerId: PeerPresence] = [:]
for user in users {
let peer = TelegramUser(user: user)
peers[peer.id] = peer
if let presence = TelegramUserPresence(apiUser: user) {
presences[peer.id] = presence
}
}
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
if let peer = peers[participant.peerId] {
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences))
}
}
return account.postbox.transaction { transaction -> [RenderedChannelParticipant] in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
return cachedData.withUpdatedParticipantsSummary(cachedData.participantsSummary.withUpdatedAdminCount(count))
} else {
return cachedData
}
})
return items
}
case .channelParticipantsNotModified:
return .single([])
}
}
} else {
return .single([])
}
} |> switchToLatest
}
public func channelAdminIds(postbox: Postbox, network: Network, peerId: PeerId, hash: Int32) -> Signal<[PeerId], NoError> {
return postbox.transaction { transaction in
if let peer = transaction.getPeer(peerId) as? TelegramChannel, case .group = peer.info, let apiChannel = apiInputChannel(peer) {
let api = Api.functions.channels.getParticipants(channel: apiChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: hash)
return network.request(api) |> retryRequest |> mapToSignal { result in
switch result {
case let .channelParticipants(_, participants, _, users):
let users = users.filter({ user in
return participants.contains(where: { participant in
switch participant {
case let .channelParticipantAdmin(_, userId, _, _, _, _, _):
return user.peerId.id._internalGetInt32Value() == userId
case let .channelParticipantCreator(_, userId, _, _):
return user.peerId.id._internalGetInt32Value() == userId
default:
return false
}
})
})
return .single(users.map({TelegramUser(user: $0).id}))
default:
return .complete()
}
}
}
return .complete()
} |> switchToLatest
}

View File

@ -1,84 +0,0 @@
import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
import SyncCore
public struct RenderedChannelParticipant: Equatable {
public let participant: ChannelParticipant
public let peer: Peer
public let peers: [PeerId: Peer]
public let presences: [PeerId: PeerPresence]
public init(participant: ChannelParticipant, peer: Peer, peers: [PeerId: Peer] = [:], presences: [PeerId: PeerPresence] = [:]) {
self.participant = participant
self.peer = peer
self.peers = peers
self.presences = presences
}
public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool {
return lhs.participant == rhs.participant && lhs.peer.isEqual(rhs.peer)
}
}
func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
let admins = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 0, hash: 0))
let members = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsRecent, offset: 0, limit: 0, hash: 0))
let banned = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsBanned(q: ""), offset: 0, limit: 0, hash: 0))
let kicked = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 0, hash: 0))
return combineLatest(admins, members, banned, kicked)
|> mapToSignal { admins, members, banned, kicked -> Signal<Void, MTRpcError> in
return account.postbox.transaction { transaction -> Void in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
if let current = current as? CachedChannelData {
let adminCount: Int32
switch admins {
case let .channelParticipants(count, _, _, _):
adminCount = count
case .channelParticipantsNotModified:
assertionFailure()
adminCount = 0
}
let memberCount: Int32
switch members {
case let .channelParticipants(count, _, _, _):
memberCount = count
case .channelParticipantsNotModified:
assertionFailure()
memberCount = 0
}
let bannedCount: Int32
switch banned {
case let .channelParticipants(count, _, _, _):
bannedCount = count
case .channelParticipantsNotModified:
assertionFailure()
bannedCount = 0
}
let kickedCount: Int32
switch kicked {
case let .channelParticipants(count, _, _, _):
kickedCount = count
case .channelParticipantsNotModified:
assertionFailure()
kickedCount = 0
}
return current.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: adminCount, bannedCount: bannedCount, kickedCount: kickedCount))
}
return current
})
} |> mapError { _ -> MTRpcError in return MTRpcError(errorCode: 0, errorDescription: "") }
}
|> `catch` { _ -> Signal<Void, NoError> in
return .complete()
}
} else {
return .complete()
}
} |> switchToLatest
}

View File

@ -461,7 +461,7 @@ final class MediaReferenceRevalidationContext {
func peerAvatars(postbox: Postbox, network: Network, background: Bool, peer: PeerReference) -> Signal<[TelegramPeerPhoto], RevalidateMediaReferenceError> {
return self.genericItem(key: .peerAvatars(peer: peer), background: background, request: { next, error in
return (requestPeerPhotos(postbox: postbox, network: network, peerId: peer.id)
return (_internal_requestPeerPhotos(postbox: postbox, network: network, peerId: peer.id)
|> mapError { _ -> RevalidateMediaReferenceError in
return .generic
}).start(next: { value in

View File

@ -1,210 +0,0 @@
import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
import SyncCore
public enum MessageReactionListCategory: Hashable {
case all
case reaction(String)
}
public final class MessageReactionListCategoryItem: Equatable {
public let peer: Peer
public let reaction: String
init(peer: Peer, reaction: String) {
self.peer = peer
self.reaction = reaction
}
public static func ==(lhs: MessageReactionListCategoryItem, rhs: MessageReactionListCategoryItem) -> Bool {
if lhs.peer.id != rhs.peer.id {
return false
}
if lhs.reaction != rhs.reaction {
return false
}
return true
}
}
public struct MessageReactionListCategoryState: Equatable {
public var count: Int
public var completed: Bool
public var items: [MessageReactionListCategoryItem]
public var loadingMore: Bool
fileprivate var nextOffset: String?
}
private enum LoadReactionsError {
case generic
}
private final class MessageReactionCategoryContext {
private let postbox: Postbox
private let network: Network
private let messageId: MessageId
private let category: MessageReactionListCategory
private var state: MessageReactionListCategoryState
var statePromise: ValuePromise<MessageReactionListCategoryState>
private let loadingDisposable = MetaDisposable()
init(postbox: Postbox, network: Network, messageId: MessageId, category: MessageReactionListCategory, initialState: MessageReactionListCategoryState) {
self.postbox = postbox
self.network = network
self.messageId = messageId
self.category = category
self.state = initialState
self.statePromise = ValuePromise(initialState)
}
deinit {
self.loadingDisposable.dispose()
}
func loadMore() {
if self.state.completed || self.state.loadingMore {
return
}
/*self.state.loadingMore = true
self.statePromise.set(self.state)
var flags: Int32 = 0
var reaction: String?
switch self.category {
case .all:
break
case let .reaction(value):
flags |= 1 << 0
reaction = value
}
let messageId = self.messageId
let offset = self.state.nextOffset
var request = self.postbox.transaction { transaction -> Api.InputPeer? in
let inputPeer = transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
return inputPeer
}
|> castError(LoadReactionsError.self)
|> mapToSignal { inputPeer -> Signal<Api.messages.MessageReactionsList, LoadReactionsError> in
guard let inputPeer = inputPeer else {
return .fail(.generic)
}
return self.network.request(Api.functions.messages.getMessageReactionsList(flags: flags, peer: inputPeer, id: messageId.id, reaction: reaction, offset: offset, limit: 64))
|> mapError { _ -> LoadReactionsError in
return .generic
}
}
//#if DEBUG
//request = request |> delay(1.0, queue: .mainQueue())
//#endif
self.loadingDisposable.set((request
|> deliverOnMainQueue).start(next: { [weak self] result in
guard let strongSelf = self else {
return
}
let currentState = strongSelf.state
let _ = (strongSelf.postbox.transaction { transaction -> MessageReactionListCategoryState in
var mergedItems = currentState.items
var currentIds = Set(mergedItems.lazy.map { $0.peer.id })
switch result {
case let .messageReactionsList(_, count, reactions, users, nextOffset):
var peers: [Peer] = []
for user in users {
let parsedUser = TelegramUser(user: user)
peers.append(parsedUser)
}
updatePeers(transaction: transaction, peers: peers, update: { _, updated in updated })
for reaction in reactions {
switch reaction {
case let .messageUserReaction(userId, reaction):
if let peer = transaction.getPeer(PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)) {
if !currentIds.contains(peer.id) {
currentIds.insert(peer.id)
mergedItems.append(MessageReactionListCategoryItem(peer: peer, reaction: reaction))
}
}
}
}
return MessageReactionListCategoryState(count: max(mergedItems.count, Int(count)), completed: nextOffset == nil, items: mergedItems, loadingMore: false, nextOffset: nextOffset)
}
}
|> deliverOnMainQueue).start(next: { state in
guard let strongSelf = self else {
return
}
strongSelf.state = state
strongSelf.statePromise.set(state)
})
}, error: { _ in
}))*/
}
}
public struct MessageReactionListState: Equatable {
public var states: [(MessageReactionListCategory, MessageReactionListCategoryState)]
public static func ==(lhs: MessageReactionListState, rhs: MessageReactionListState) -> Bool {
if lhs.states.count != rhs.states.count {
return false
}
for i in 0 ..< lhs.states.count {
if lhs.states[i].0 != rhs.states[i].0 {
return false
}
if lhs.states[i].1 != rhs.states[i].1 {
return false
}
}
return true
}
}
public final class MessageReactionListContext {
private let postbox: Postbox
private let network: Network
private var categoryContexts: [MessageReactionListCategory: MessageReactionCategoryContext] = [:]
private let _state = Promise<MessageReactionListState>()
public var state: Signal<MessageReactionListState, NoError> {
return self._state.get()
}
public init(postbox: Postbox, network: Network, messageId: MessageId, initialReactions: [MessageReaction]) {
self.postbox = postbox
self.network = network
var allState = MessageReactionListCategoryState(count: 0, completed: false, items: [], loadingMore: false, nextOffset: nil)
var signals: [Signal<(MessageReactionListCategory, MessageReactionListCategoryState), NoError>] = []
for reaction in initialReactions {
allState.count += Int(reaction.count)
let context = MessageReactionCategoryContext(postbox: postbox, network: network, messageId: messageId, category: .reaction(reaction.value), initialState: MessageReactionListCategoryState(count: Int(reaction.count), completed: false, items: [], loadingMore: false, nextOffset: nil))
signals.append(context.statePromise.get() |> map { value -> (MessageReactionListCategory, MessageReactionListCategoryState) in
return (.reaction(reaction.value), value)
})
self.categoryContexts[.reaction(reaction.value)] = context
context.loadMore()
}
let allContext = MessageReactionCategoryContext(postbox: postbox, network: network, messageId: messageId, category: .all, initialState: allState)
signals.insert(allContext.statePromise.get() |> map { value -> (MessageReactionListCategory, MessageReactionListCategoryState) in
return (.all, value)
}, at: 0)
self.categoryContexts[.all] = allContext
self._state.set(combineLatest(queue: .mainQueue(), signals)
|> map { states in
return MessageReactionListState(states: states)
})
allContext.loadMore()
}
public func loadMore(category: MessageReactionListCategory) {
self.categoryContexts[category]?.loadMore()
}
}

View File

@ -1,40 +0,0 @@
import Foundation
import Postbox
import SwiftSignalKit
import SyncCore
private struct PeerParticipants: Equatable {
let peers: [Peer]
static func ==(lhs: PeerParticipants, rhs: PeerParticipants) -> Bool {
if lhs.peers.count != rhs.peers.count {
return false
}
for i in 0 ..< lhs.peers.count {
if !lhs.peers[i].isEqual(rhs.peers[i]) {
return false
}
}
return true
}
}
public func peerParticipants(postbox: Postbox, id: PeerId) -> Signal<[Peer], NoError> {
return postbox.peerView(id: id) |> map { view -> PeerParticipants in
if let cachedGroupData = view.cachedData as? CachedGroupData, let participants = cachedGroupData.participants {
var peers: [Peer] = []
for participant in participants.participants {
if let peer = view.peers[participant.peerId] {
peers.append(peer)
}
}
return PeerParticipants(peers: peers)
} else {
return PeerParticipants(peers: [])
}
}
|> distinctUntilChanged |> map { participants in
return participants.peers
}
}

View File

@ -65,5 +65,5 @@ public func unarchiveAutomaticallyArchivedPeer(account: Account, peerId: PeerId)
}
|> deliverOnMainQueue).start()
let _ = updatePeerMuteSetting(account: account, peerId: peerId, muteInterval: nil).start()
let _ = _internal_updatePeerMuteSetting(account: account, peerId: peerId, muteInterval: nil).start()
}

View File

@ -105,7 +105,7 @@ func syncContactsOnce(network: Network, postbox: Postbox, accountPeerId: PeerId)
return appliedUpdatedPeers
}
public func deleteContactPeerInteractively(account: Account, peerId: PeerId) -> Signal<Never, NoError> {
func _internal_deleteContactPeerInteractively(account: Account, peerId: PeerId) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Signal<Never, NoError> in
if let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) {
return account.network.request(Api.functions.contacts.deleteContacts(id: [inputUser]))
@ -133,7 +133,7 @@ public func deleteContactPeerInteractively(account: Account, peerId: PeerId) ->
|> switchToLatest
}
public func deleteAllContacts(account: Account) -> Signal<Never, NoError> {
func _internal_deleteAllContacts(account: Account) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> [Api.InputUser] in
return transaction.getContactPeerIds().compactMap(transaction.getPeer).compactMap({ apiInputUser($0) }).compactMap({ $0 })
}
@ -166,7 +166,7 @@ public func deleteAllContacts(account: Account) -> Signal<Never, NoError> {
}
}
public func resetSavedContacts(network: Network) -> Signal<Void, NoError> {
func _internal_resetSavedContacts(network: Network) -> Signal<Void, NoError> {
return network.request(Api.functions.contacts.resetSaved())
|> `catch` { _ -> Signal<Api.Bool, NoError> in
return .single(.boolFalse)

View File

@ -4,8 +4,7 @@ import SwiftSignalKit
import SyncCore
public func importContact(account: Account, firstName: String, lastName: String, phoneNumber: String) -> Signal<PeerId?, NoError> {
func _internal_importContact(account: Account, firstName: String, lastName: String, phoneNumber: String) -> Signal<PeerId?, NoError> {
let input = Api.InputContact.inputPhoneContact(clientId: 1, phone: phoneNumber, firstName: firstName, lastName: lastName)
return account.network.request(Api.functions.contacts.importContacts(contacts: [input]))
@ -42,7 +41,7 @@ public enum AddContactError {
case generic
}
public func addContactInteractively(account: Account, peerId: PeerId, firstName: String, lastName: String, phoneNumber: String, addToPrivacyExceptions: Bool) -> Signal<Never, AddContactError> {
func _internal_addContactInteractively(account: Account, peerId: PeerId, firstName: String, lastName: String, phoneNumber: String, addToPrivacyExceptions: Bool) -> Signal<Never, AddContactError> {
return account.postbox.transaction { transaction -> (Api.InputUser, String)? in
if let user = transaction.getPeer(peerId) as? TelegramUser, let inputUser = apiInputUser(user) {
return (inputUser, user.phone == nil ? phoneNumber : "")
@ -99,7 +98,7 @@ public enum AcceptAndShareContactError {
case generic
}
public func acceptAndShareContact(account: Account, peerId: PeerId) -> Signal<Never, AcceptAndShareContactError> {
func _internal_acceptAndShareContact(account: Account, peerId: PeerId) -> Signal<Never, AcceptAndShareContactError> {
return account.postbox.transaction { transaction -> Api.InputUser? in
return transaction.getPeer(peerId).flatMap(apiInputUser)
}

View File

@ -48,7 +48,7 @@ enum TelegramDeviceContactImportIdentifier: Hashable, Comparable, Equatable {
}
}
public func deviceContactsImportedByCount(postbox: Postbox, contacts: [(String, [DeviceContactNormalizedPhoneNumber])]) -> Signal<[String: Int32], NoError> {
func _internal_deviceContactsImportedByCount(postbox: Postbox, contacts: [(String, [DeviceContactNormalizedPhoneNumber])]) -> Signal<[String: Int32], NoError> {
return postbox.transaction { transaction -> [String: Int32] in
var result: [String: Int32] = [:]
for (id, numbers) in contacts {

View File

@ -0,0 +1,44 @@
import SwiftSignalKit
import Postbox
public extension TelegramEngine {
final class Contacts {
private let account: Account
init(account: Account) {
self.account = account
}
public func deleteContactPeerInteractively(peerId: PeerId) -> Signal<Never, NoError> {
return _internal_deleteContactPeerInteractively(account: self.account, peerId: peerId)
}
public func deleteAllContacts() -> Signal<Never, NoError> {
return _internal_deleteAllContacts(account: self.account)
}
public func resetSavedContacts() -> Signal<Void, NoError> {
return _internal_resetSavedContacts(network: self.account.network)
}
public func updateContactName(peerId: PeerId, firstName: String, lastName: String) -> Signal<Void, UpdateContactNameError> {
return _internal_updateContactName(account: self.account, peerId: peerId, firstName: firstName, lastName: lastName)
}
public func deviceContactsImportedByCount(contacts: [(String, [DeviceContactNormalizedPhoneNumber])]) -> Signal<[String: Int32], NoError> {
return _internal_deviceContactsImportedByCount(postbox: self.account.postbox, contacts: contacts)
}
public func importContact(firstName: String, lastName: String, phoneNumber: String) -> Signal<PeerId?, NoError> {
return _internal_importContact(account: self.account, firstName: firstName, lastName: lastName, phoneNumber: phoneNumber)
}
public func addContactInteractively(peerId: PeerId, firstName: String, lastName: String, phoneNumber: String, addToPrivacyExceptions: Bool) -> Signal<Never, AddContactError> {
return _internal_addContactInteractively(account: self.account, peerId: peerId, firstName: firstName, lastName: lastName, phoneNumber: phoneNumber, addToPrivacyExceptions: addToPrivacyExceptions)
}
public func acceptAndShareContact(peerId: PeerId) -> Signal<Never, AcceptAndShareContactError> {
return _internal_acceptAndShareContact(account: self.account, peerId: peerId)
}
}
}

View File

@ -10,7 +10,7 @@ public enum UpdateContactNameError {
case generic
}
public func updateContactName(account: Account, peerId: PeerId, firstName: String, lastName: String) -> Signal<Void, UpdateContactNameError> {
func _internal_updateContactName(account: Account, peerId: PeerId, firstName: String, lastName: String) -> Signal<Void, UpdateContactNameError> {
return account.postbox.transaction { transaction -> Signal<Void, UpdateContactNameError> in
if let peer = transaction.getPeer(peerId) as? TelegramUser, let inputUser = apiInputUser(peer) {
return account.network.request(Api.functions.contacts.addContact(flags: 0, id: inputUser, firstName: firstName, lastName: lastName, phone: ""))

View File

@ -11,7 +11,7 @@ public enum GetMessagesStrategy {
case cloud
}
public func getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Postbox, network: Network, accountPeerId: PeerId, strategy: GetMessagesStrategy = .cloud) -> Signal <[Message], NoError> {
func _internal_getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Postbox, network: Network, accountPeerId: PeerId, strategy: GetMessagesStrategy = .cloud) -> Signal <[Message], NoError> {
let postboxSignal = postbox.transaction { transaction -> ([Message], Set<MessageId>, SimpleDictionary<PeerId, Peer>) in
var ids = messageIds

View File

@ -6,7 +6,7 @@ import MtProtoKit
import SyncCore
public func markAllChatsAsRead(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
func _internal_markAllChatsAsRead(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
return network.request(Api.functions.messages.getDialogUnreadMarks())
|> map(Optional.init)
|> `catch` { _ -> Signal<[Api.DialogPeer]?, NoError> in

View File

@ -453,7 +453,7 @@ public enum FetchChannelReplyThreadMessageError {
case generic
}
public func fetchChannelReplyThreadMessage(account: Account, messageId: MessageId, atMessageId: MessageId?) -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> {
func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: MessageId, atMessageId: MessageId?) -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> {
return account.postbox.transaction { transaction -> Api.InputPeer? in
return transaction.getPeer(messageId.peerId).flatMap(apiInputPeer)
}

View File

@ -6,7 +6,7 @@ import MtProtoKit
import SyncCore
public func requestStartBot(account: Account, botPeerId: PeerId, payload: String?) -> Signal<Void, NoError> {
func _internal_requestStartBot(account: Account, botPeerId: PeerId, payload: String?) -> Signal<Void, NoError> {
if let payload = payload, !payload.isEmpty {
return account.postbox.loadedPeerWithId(botPeerId)
|> mapToSignal { botPeer -> Signal<Void, NoError> in
@ -41,7 +41,7 @@ public enum StartBotInGroupResult {
case channelParticipant(RenderedChannelParticipant)
}
public func requestStartBotInGroup(account: Account, botPeerId: PeerId, groupPeerId: PeerId, payload: String?) -> Signal<StartBotInGroupResult, RequestStartBotInGroupError> {
func _internal_requestStartBotInGroup(account: Account, botPeerId: PeerId, groupPeerId: PeerId, payload: String?) -> Signal<StartBotInGroupResult, RequestStartBotInGroupError> {
return account.postbox.transaction { transaction -> (Peer?, Peer?) in
return (transaction.getPeer(botPeerId), transaction.getPeer(groupPeerId))
}

View File

@ -94,5 +94,33 @@ public extension TelegramEngine {
public func forwardGameWithScore(messageId: MessageId, to peerId: PeerId) -> Signal<Void, NoError> {
return _internal_forwardGameWithScore(account: self.account, messageId: messageId, to: peerId)
}
public func requestUpdatePinnedMessage(peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
return _internal_requestUpdatePinnedMessage(account: self.account, peerId: peerId, update: update)
}
public func requestUnpinAllMessages(peerId: PeerId) -> Signal<Never, UpdatePinnedMessageError> {
return _internal_requestUnpinAllMessages(account: self.account, peerId: peerId)
}
public func fetchChannelReplyThreadMessage(messageId: MessageId, atMessageId: MessageId?) -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> {
return _internal_fetchChannelReplyThreadMessage(account: self.account, messageId: messageId, atMessageId: atMessageId)
}
public func requestStartBot(botPeerId: PeerId, payload: String?) -> Signal<Void, NoError> {
return _internal_requestStartBot(account: self.account, botPeerId: botPeerId, payload: payload)
}
public func requestStartBotInGroup(botPeerId: PeerId, groupPeerId: PeerId, payload: String?) -> Signal<StartBotInGroupResult, RequestStartBotInGroupError> {
return _internal_requestStartBotInGroup(account: self.account, botPeerId: botPeerId, groupPeerId: groupPeerId, payload: payload)
}
public func markAllChatsAsRead() -> Signal<Void, NoError> {
return _internal_markAllChatsAsRead(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager)
}
public func getMessagesLoadIfNecessary(_ messageIds: [MessageId], strategy: GetMessagesStrategy = .cloud) -> Signal <[Message], NoError> {
return _internal_getMessagesLoadIfNecessary(messageIds, postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId, strategy: strategy)
}
}
}

View File

@ -15,7 +15,7 @@ public enum PinnedMessageUpdate {
case clear(id: MessageId)
}
public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
func _internal_requestUpdatePinnedMessage(account: Account, peerId: PeerId, update: PinnedMessageUpdate) -> Signal<Void, UpdatePinnedMessageError> {
return account.postbox.transaction { transaction -> (Peer?, CachedPeerData?) in
return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId))
}
@ -112,7 +112,7 @@ public func requestUpdatePinnedMessage(account: Account, peerId: PeerId, update:
}
}
public func requestUnpinAllMessages(account: Account, peerId: PeerId) -> Signal<Never, UpdatePinnedMessageError> {
func _internal_requestUnpinAllMessages(account: Account, peerId: PeerId) -> Signal<Never, UpdatePinnedMessageError> {
return account.postbox.transaction { transaction -> (Peer?, CachedPeerData?) in
return (transaction.getPeer(peerId), transaction.getPeerCachedData(peerId: peerId))
}

View File

@ -4,7 +4,7 @@ import SwiftSignalKit
import SyncCore
public func togglePeerMuted(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
func _internal_togglePeerMuted(account: Account, peerId: PeerId) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
if let peer = transaction.getPeer(peerId) {
var notificationPeerId = peerId
@ -39,13 +39,13 @@ public func togglePeerMuted(account: Account, peerId: PeerId) -> Signal<Void, No
}
}
public func updatePeerMuteSetting(account: Account, peerId: PeerId, muteInterval: Int32?) -> Signal<Void, NoError> {
func _internal_updatePeerMuteSetting(account: Account, peerId: PeerId, muteInterval: Int32?) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
updatePeerMuteSetting(transaction: transaction, peerId: peerId, muteInterval: muteInterval)
}
}
public func updatePeerMuteSetting(transaction: Transaction, peerId: PeerId, muteInterval: Int32?) {
func updatePeerMuteSetting(transaction: Transaction, peerId: PeerId, muteInterval: Int32?) {
if let peer = transaction.getPeer(peerId) {
var notificationPeerId = peerId
if let associatedPeerId = peer.associatedPeerId {
@ -82,13 +82,13 @@ public func updatePeerMuteSetting(transaction: Transaction, peerId: PeerId, mute
}
}
public func updatePeerDisplayPreviewsSetting(account: Account, peerId: PeerId, displayPreviews: PeerNotificationDisplayPreviews) -> Signal<Void, NoError> {
func _internal_updatePeerDisplayPreviewsSetting(account: Account, peerId: PeerId, displayPreviews: PeerNotificationDisplayPreviews) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
updatePeerDisplayPreviewsSetting(transaction: transaction, peerId: peerId, displayPreviews: displayPreviews)
}
}
public func updatePeerDisplayPreviewsSetting(transaction: Transaction, peerId: PeerId, displayPreviews: PeerNotificationDisplayPreviews) {
func updatePeerDisplayPreviewsSetting(transaction: Transaction, peerId: PeerId, displayPreviews: PeerNotificationDisplayPreviews) {
if let peer = transaction.getPeer(peerId) {
var notificationPeerId = peerId
if let associatedPeerId = peer.associatedPeerId {
@ -108,13 +108,13 @@ public func updatePeerDisplayPreviewsSetting(transaction: Transaction, peerId: P
}
}
public func updatePeerNotificationSoundInteractive(account: Account, peerId: PeerId, sound: PeerMessageSound) -> Signal<Void, NoError> {
func _internal_updatePeerNotificationSoundInteractive(account: Account, peerId: PeerId, sound: PeerMessageSound) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Void in
updatePeerNotificationSoundInteractive(transaction: transaction, peerId: peerId, sound: sound)
}
}
public func updatePeerNotificationSoundInteractive(transaction: Transaction, peerId: PeerId, sound: PeerMessageSound) {
func updatePeerNotificationSoundInteractive(transaction: Transaction, peerId: PeerId, sound: PeerMessageSound) {
if let peer = transaction.getPeer(peerId) {
var notificationPeerId = peerId
if let associatedPeerId = peer.associatedPeerId {

View File

@ -96,7 +96,7 @@ public final class ChannelAdminEventLogContext {
private let loadMoreDisposable = MetaDisposable()
public init(postbox: Postbox, network: Network, peerId: PeerId) {
init(postbox: Postbox, network: Network, peerId: PeerId) {
self.postbox = postbox
self.network = network
self.peerId = peerId

View File

@ -114,7 +114,7 @@ private func boolFromApiValue(_ value: Api.Bool) -> Bool {
}
}
public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
return postbox.transaction { transaction -> (Peer?, [Peer]?) in
return (transaction.getPeer(peerId), admins?.compactMap { transaction.getPeer($0) })
}

View File

@ -3,138 +3,9 @@ import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
import SyncCore
private enum ChannelBlacklistFilter {
case restricted
case banned
}
private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: ChannelBlacklistFilter) -> Signal<[RenderedChannelParticipant], NoError> {
return account.postbox.transaction { transaction -> Signal<[RenderedChannelParticipant], NoError> in
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
let apiFilter: Api.ChannelParticipantsFilter
switch filter {
case .restricted:
apiFilter = .channelParticipantsBanned(q: "")
case .banned:
apiFilter = .channelParticipantsKicked(q: "")
}
return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100, hash: 0))
|> retryRequest
|> map { result -> [RenderedChannelParticipant] in
var items: [RenderedChannelParticipant] = []
switch result {
case let .channelParticipants(_, participants, chats, users):
var peers: [PeerId: Peer] = [:]
var presences: [PeerId: PeerPresence] = [:]
for user in users {
let peer = TelegramUser(user: user)
peers[peer.id] = peer
if let presence = TelegramUserPresence(apiUser: user) {
presences[peer.id] = presence
}
}
for chat in chats {
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
peers[groupOrChannel.id] = groupOrChannel
}
}
for participant in CachedChannelParticipants(apiParticipants: participants).participants {
if let peer = peers[participant.peerId] {
items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences))
}
}
case .channelParticipantsNotModified:
assertionFailure()
break
}
return items
}
} else {
return .single([])
}
} |> switchToLatest
}
public struct ChannelBlacklist {
public let banned: [RenderedChannelParticipant]
public let restricted: [RenderedChannelParticipant]
public init(banned: [RenderedChannelParticipant], restricted: [RenderedChannelParticipant]) {
self.banned = banned
self.restricted = restricted
}
public var isEmpty: Bool {
return banned.isEmpty && restricted.isEmpty
}
public func withRemovedPeerId(_ memberId:PeerId) -> ChannelBlacklist {
var updatedRestricted = restricted
var updatedBanned = banned
for i in 0 ..< updatedBanned.count {
if updatedBanned[i].peer.id == memberId {
updatedBanned.remove(at: i)
break
}
}
for i in 0 ..< updatedRestricted.count {
if updatedRestricted[i].peer.id == memberId {
updatedRestricted.remove(at: i)
break
}
}
return ChannelBlacklist(banned: updatedBanned, restricted: updatedRestricted)
}
public func withRemovedParticipant(_ participant:RenderedChannelParticipant) -> ChannelBlacklist {
let updated = self.withRemovedPeerId(participant.participant.peerId)
var updatedRestricted = updated.restricted
var updatedBanned = updated.banned
if case let .member(_, _, _, maybeBanInfo, _) = participant.participant, let banInfo = maybeBanInfo {
if banInfo.rights.flags.contains(.banReadMessages) {
updatedBanned.insert(participant, at: 0)
} else {
if !banInfo.rights.flags.isEmpty {
updatedRestricted.insert(participant, at: 0)
}
}
}
return ChannelBlacklist(banned: updatedBanned, restricted: updatedRestricted)
}
}
public func channelBlacklistParticipants(account: Account, peerId: PeerId) -> Signal<ChannelBlacklist, NoError> {
return combineLatest(fetchChannelBlacklist(account: account, peerId: peerId, filter: .restricted), fetchChannelBlacklist(account: account, peerId: peerId, filter: .banned))
|> map { restricted, banned in
var r: [RenderedChannelParticipant] = []
var b: [RenderedChannelParticipant] = []
var peerIds = Set<PeerId>()
for participant in restricted {
if !peerIds.contains(participant.peer.id) {
peerIds.insert(participant.peer.id)
r.append(participant)
}
}
for participant in banned {
if !peerIds.contains(participant.peer.id) {
peerIds.insert(participant.peer.id)
b.append(participant)
}
}
return ChannelBlacklist(banned: b, restricted: r)
}
}
public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChatBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> {
func _internal_updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChatBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> {
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> in
@ -263,7 +134,7 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
}
}
public func updateDefaultChannelMemberBannedRights(account: Account, peerId: PeerId, rights: TelegramChatBannedRights) -> Signal<Never, NoError> {
func _internal_updateDefaultChannelMemberBannedRights(account: Account, peerId: PeerId, rights: TelegramChatBannedRights) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Signal<Never, NoError> in
guard let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer), let _ = transaction.getPeer(account.peerId) else {
return .complete()

View File

@ -71,11 +71,11 @@ private func createChannel(account: Account, title: String, description: String?
|> switchToLatest
}
public func createChannel(account: Account, title: String, description: String?) -> Signal<PeerId, CreateChannelError> {
func _internal_createChannel(account: Account, title: String, description: String?) -> Signal<PeerId, CreateChannelError> {
return createChannel(account: account, title: title, description: description, isSupergroup: false)
}
public func createSupergroup(account: Account, title: String, description: String?, location: (latitude: Double, longitude: Double, address: String)? = nil, isForHistoryImport: Bool = false) -> Signal<PeerId, CreateChannelError> {
func _internal_createSupergroup(account: Account, title: String, description: String?, location: (latitude: Double, longitude: Double, address: String)? = nil, isForHistoryImport: Bool = false) -> Signal<PeerId, CreateChannelError> {
return createChannel(account: account, title: title, description: description, isSupergroup: true, location: location, isForHistoryImport: isForHistoryImport)
}
@ -83,7 +83,7 @@ public enum DeleteChannelError {
case generic
}
public func deleteChannel(account: Account, peerId: PeerId) -> Signal<Void, DeleteChannelError> {
func _internal_deleteChannel(account: Account, peerId: PeerId) -> Signal<Void, DeleteChannelError> {
return account.postbox.transaction { transaction -> Api.InputChannel? in
return transaction.getPeer(peerId).flatMap(apiInputChannel)
}

View File

@ -9,7 +9,7 @@ public enum ChannelHistoryAvailabilityError {
case hasNotPermissions
}
public func updateChannelHistoryAvailabilitySettingsInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, historyAvailableForNewMembers: Bool) -> Signal<Void, ChannelHistoryAvailabilityError> {
func _internal_updateChannelHistoryAvailabilitySettingsInteractively(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, peerId: PeerId, historyAvailableForNewMembers: Bool) -> Signal<Void, ChannelHistoryAvailabilityError> {
return postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
}

View File

@ -21,7 +21,7 @@ public enum ChannelMembersCategory {
case mentions(threadId: MessageId?, filter: ChannelMembersCategoryFilter)
}
public func channelMembers(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, category: ChannelMembersCategory = .recent(.all), offset: Int32 = 0, limit: Int32 = 64, hash: Int32 = 0) -> Signal<[RenderedChannelParticipant]?, NoError> {
func _internal_channelMembers(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, category: ChannelMembersCategory = .recent(.all), offset: Int32 = 0, limit: Int32 = 64, hash: Int32 = 0) -> Signal<[RenderedChannelParticipant]?, NoError> {
return postbox.transaction { transaction -> Signal<[RenderedChannelParticipant]?, NoError> in
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer) {
let apiFilter: Api.ChannelParticipantsFilter

View File

@ -21,7 +21,7 @@ public enum ChannelOwnershipTransferError {
case userBlocked
}
public func checkOwnershipTranfserAvailability(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, memberId: PeerId) -> Signal<Never, ChannelOwnershipTransferError> {
func _internal_checkOwnershipTranfserAvailability(postbox: Postbox, network: Network, accountStateManager: AccountStateManager, memberId: PeerId) -> Signal<Never, ChannelOwnershipTransferError> {
return postbox.transaction { transaction -> Peer? in
return transaction.getPeer(memberId)
}
@ -72,7 +72,7 @@ public func checkOwnershipTranfserAvailability(postbox: Postbox, network: Networ
}
}
public func updateChannelOwnership(account: Account, accountStateManager: AccountStateManager, channelId: PeerId, memberId: PeerId, password: String) -> Signal<[(ChannelParticipant?, RenderedChannelParticipant)], ChannelOwnershipTransferError> {
func _internal_updateChannelOwnership(account: Account, accountStateManager: AccountStateManager, channelId: PeerId, memberId: PeerId, password: String) -> Signal<[(ChannelParticipant?, RenderedChannelParticipant)], ChannelOwnershipTransferError> {
guard !password.isEmpty else {
return .fail(.invalidPassword)
}

View File

@ -0,0 +1,25 @@
import Foundation
import Postbox
import SwiftSignalKit
import TelegramApi
import MtProtoKit
import SyncCore
public struct RenderedChannelParticipant: Equatable {
public let participant: ChannelParticipant
public let peer: Peer
public let peers: [PeerId: Peer]
public let presences: [PeerId: PeerPresence]
public init(participant: ChannelParticipant, peer: Peer, peers: [PeerId: Peer] = [:], presences: [PeerId: PeerPresence] = [:]) {
self.participant = participant
self.peer = peer
self.peers = peers
self.presences = presences
}
public static func ==(lhs: RenderedChannelParticipant, rhs: RenderedChannelParticipant) -> Bool {
return lhs.participant == rhs.participant && lhs.peer.isEqual(rhs.peer)
}
}

View File

@ -12,7 +12,7 @@ public enum JoinChannelError {
case tooMuchUsers
}
public func joinChannel(account: Account, peerId: PeerId, hash: String?) -> Signal<RenderedChannelParticipant?, JoinChannelError> {
func _internal_joinChannel(account: Account, peerId: PeerId, hash: String?) -> Signal<RenderedChannelParticipant?, JoinChannelError> {
return account.postbox.loadedPeerWithId(peerId)
|> take(1)
|> castError(JoinChannelError.self)

View File

@ -9,7 +9,7 @@ public enum AvailableChannelDiscussionGroupError {
case generic
}
public func availableGroupsForChannelDiscussion(postbox: Postbox, network: Network) -> Signal<[Peer], AvailableChannelDiscussionGroupError> {
func _internal_availableGroupsForChannelDiscussion(postbox: Postbox, network: Network) -> Signal<[Peer], AvailableChannelDiscussionGroupError> {
return network.request(Api.functions.channels.getGroupsForDiscussion())
|> mapError { error in
return .generic
@ -39,7 +39,7 @@ public enum ChannelDiscussionGroupError {
case tooManyChannels
}
public func updateGroupDiscussionForChannel(network: Network, postbox: Postbox, channelId: PeerId?, groupId: PeerId?) -> Signal<Bool, ChannelDiscussionGroupError> {
func _internal_updateGroupDiscussionForChannel(network: Network, postbox: Postbox, channelId: PeerId?, groupId: PeerId?) -> Signal<Bool, ChannelDiscussionGroupError> {
return postbox.transaction { transaction -> (channel: Peer?, group: Peer?) in
return (channel: channelId.flatMap(transaction.getPeer), group: groupId.flatMap(transaction.getPeer))
}

View File

@ -26,7 +26,7 @@ public struct PeerCommands: Equatable {
}
}
public func peerCommands(account: Account, id: PeerId) -> Signal<PeerCommands, NoError> {
func _internal_peerCommands(account: Account, id: PeerId) -> Signal<PeerCommands, NoError> {
return account.postbox.peerView(id: id) |> map { view -> PeerCommands in
if let cachedUserData = view.cachedData as? CachedUserData {
if let botInfo = cachedUserData.botInfo {

View File

@ -6,9 +6,9 @@ import MtProtoKit
import SyncCore
public func removePeerMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Void, NoError> {
func _internal_removePeerMember(account: Account, peerId: PeerId, memberId: PeerId) -> Signal<Void, NoError> {
if peerId.namespace == Namespaces.Peer.CloudChannel {
return updateChannelMemberBannedRights(account: account, peerId: peerId, memberId: memberId, rights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: 0))
return _internal_updateChannelMemberBannedRights(account: account, peerId: peerId, memberId: memberId, rights: TelegramChatBannedRights(flags: [.banReadMessages], untilDate: 0))
|> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}

View File

@ -24,7 +24,7 @@ public struct TelegramPeerPhoto {
}
}
public func requestPeerPhotos(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<[TelegramPeerPhoto], NoError> {
func _internal_requestPeerPhotos(postbox: Postbox, network: Network, peerId: PeerId) -> Signal<[TelegramPeerPhoto], NoError> {
return postbox.transaction{ transaction -> Peer? in
return transaction.getPeer(peerId)
}

View File

@ -4,6 +4,41 @@ import SwiftSignalKit
import SyncCore
private struct PeerParticipants: Equatable {
let peers: [Peer]
static func ==(lhs: PeerParticipants, rhs: PeerParticipants) -> Bool {
if lhs.peers.count != rhs.peers.count {
return false
}
for i in 0 ..< lhs.peers.count {
if !lhs.peers[i].isEqual(rhs.peers[i]) {
return false
}
}
return true
}
}
private func peerParticipants(postbox: Postbox, id: PeerId) -> Signal<[Peer], NoError> {
return postbox.peerView(id: id) |> map { view -> PeerParticipants in
if let cachedGroupData = view.cachedData as? CachedGroupData, let participants = cachedGroupData.participants {
var peers: [Peer] = []
for participant in participants.participants {
if let peer = view.peers[participant.peerId] {
peers.append(peer)
}
}
return PeerParticipants(peers: peers)
} else {
return PeerParticipants(peers: [])
}
}
|> distinctUntilChanged |> map { participants in
return participants.peers
}
}
private func searchLocalGroupMembers(postbox: Postbox, peerId: PeerId, query: String) -> Signal<[Peer], NoError> {
return peerParticipants(postbox: postbox, id: peerId)
|> map { peers -> [Peer] in
@ -28,7 +63,7 @@ private func searchLocalGroupMembers(postbox: Postbox, peerId: PeerId, query: St
}
}
public func searchGroupMembers(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, query: String) -> Signal<[Peer], NoError> {
func _internal_searchGroupMembers(postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, query: String) -> Signal<[Peer], NoError> {
if peerId.namespace == Namespaces.Peer.CloudChannel && !query.isEmpty {
return searchLocalGroupMembers(postbox: postbox, peerId: peerId, query: query)
|> mapToSignal { local -> Signal<[Peer], NoError> in
@ -40,7 +75,7 @@ public func searchGroupMembers(postbox: Postbox, network: Network, accountPeerId
}
return localResult
|> then(
channelMembers(postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, category: .recent(.search(query)))
_internal_channelMembers(postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, category: .recent(.search(query)))
|> map { participants -> [Peer] in
var result: [Peer] = local
let existingIds = Set(local.map { $0.id })

View File

@ -128,5 +128,108 @@ public extension TelegramEngine {
public func reportRepliesMessage(messageId: MessageId, deleteMessage: Bool, deleteHistory: Bool, reportSpam: Bool) -> Signal<Never, NoError> {
return _internal_reportRepliesMessage(account: self.account, messageId: messageId, deleteMessage: deleteMessage, deleteHistory: deleteHistory, reportSpam: reportSpam)
}
public func togglePeerMuted(peerId: PeerId) -> Signal<Void, NoError> {
return _internal_togglePeerMuted(account: self.account, peerId: peerId)
}
public func updatePeerMuteSetting(peerId: PeerId, muteInterval: Int32?) -> Signal<Void, NoError> {
return _internal_updatePeerMuteSetting(account: self.account, peerId: peerId, muteInterval: muteInterval)
}
public func updatePeerDisplayPreviewsSetting(peerId: PeerId, displayPreviews: PeerNotificationDisplayPreviews) -> Signal<Void, NoError> {
return _internal_updatePeerDisplayPreviewsSetting(account: self.account, peerId: peerId, displayPreviews: displayPreviews)
}
public func updatePeerNotificationSoundInteractive(peerId: PeerId, sound: PeerMessageSound) -> Signal<Void, NoError> {
return _internal_updatePeerNotificationSoundInteractive(account: self.account, peerId: peerId, sound: sound)
}
public func removeCustomNotificationSettings(peerIds: [PeerId]) -> Signal<Never, NoError> {
return self.account.postbox.transaction { transaction -> Void in
for peerId in peerIds {
TelegramCore.updatePeerNotificationSoundInteractive(transaction: transaction, peerId: peerId, sound: .default)
TelegramCore.updatePeerMuteSetting(transaction: transaction, peerId: peerId, muteInterval: nil)
TelegramCore.updatePeerDisplayPreviewsSetting(transaction: transaction, peerId: peerId, displayPreviews: .default)
}
}
|> ignoreValues
}
public func channelAdminEventLog(peerId: PeerId) -> ChannelAdminEventLogContext {
return ChannelAdminEventLogContext(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
}
public func updateChannelMemberBannedRights(peerId: PeerId, memberId: PeerId, rights: TelegramChatBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant?, Bool), NoError> {
return _internal_updateChannelMemberBannedRights(account: self.account, peerId: peerId, memberId: memberId, rights: rights)
}
public func updateDefaultChannelMemberBannedRights(peerId: PeerId, rights: TelegramChatBannedRights) -> Signal<Never, NoError> {
return _internal_updateDefaultChannelMemberBannedRights(account: self.account, peerId: peerId, rights: rights)
}
public func createChannel(title: String, description: String?) -> Signal<PeerId, CreateChannelError> {
return _internal_createChannel(account: self.account, title: title, description: description)
}
public func createSupergroup(title: String, description: String?, location: (latitude: Double, longitude: Double, address: String)? = nil, isForHistoryImport: Bool = false) -> Signal<PeerId, CreateChannelError> {
return _internal_createSupergroup(account: self.account, title: title, description: description, location: location, isForHistoryImport: isForHistoryImport)
}
public func deleteChannel(peerId: PeerId) -> Signal<Void, DeleteChannelError> {
return _internal_deleteChannel(account: self.account, peerId: peerId)
}
public func updateChannelHistoryAvailabilitySettingsInteractively(peerId: PeerId, historyAvailableForNewMembers: Bool) -> Signal<Void, ChannelHistoryAvailabilityError> {
return _internal_updateChannelHistoryAvailabilitySettingsInteractively(postbox: self.account.postbox, network: self.account.network, accountStateManager: self.account.stateManager, peerId: peerId, historyAvailableForNewMembers: historyAvailableForNewMembers)
}
public func channelMembers(peerId: PeerId, category: ChannelMembersCategory = .recent(.all), offset: Int32 = 0, limit: Int32 = 64, hash: Int32 = 0) -> Signal<[RenderedChannelParticipant]?, NoError> {
return _internal_channelMembers(postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId, peerId: peerId, category: category, offset: offset, limit: limit, hash: hash)
}
public func checkOwnershipTranfserAvailability(memberId: PeerId) -> Signal<Never, ChannelOwnershipTransferError> {
return _internal_checkOwnershipTranfserAvailability(postbox: self.account.postbox, network: self.account.network, accountStateManager: self.account.stateManager, memberId: memberId)
}
public func updateChannelOwnership(channelId: PeerId, memberId: PeerId, password: String) -> Signal<[(ChannelParticipant?, RenderedChannelParticipant)], ChannelOwnershipTransferError> {
return _internal_updateChannelOwnership(account: self.account, accountStateManager: self.account.stateManager, channelId: channelId, memberId: memberId, password: password)
}
public func searchGroupMembers(peerId: PeerId, query: String) -> Signal<[Peer], NoError> {
return _internal_searchGroupMembers(postbox: self.account.postbox, network: self.account.network, accountPeerId: self.account.peerId, peerId: peerId, query: query)
}
public func toggleShouldChannelMessagesSignatures(peerId: PeerId, enabled: Bool) -> Signal<Void, NoError> {
return _internal_toggleShouldChannelMessagesSignatures(account: self.account, peerId: peerId, enabled: enabled)
}
public func requestPeerPhotos(peerId: PeerId) -> Signal<[TelegramPeerPhoto], NoError> {
return _internal_requestPeerPhotos(postbox: self.account.postbox, network: self.account.network, peerId: peerId)
}
public func updateGroupSpecificStickerset(peerId: PeerId, info: StickerPackCollectionInfo?) -> Signal<Void, UpdateGroupSpecificStickersetError> {
return _internal_updateGroupSpecificStickerset(postbox: self.account.postbox, network: self.account.network, peerId: peerId, info: info)
}
public func joinChannel(peerId: PeerId, hash: String?) -> Signal<RenderedChannelParticipant?, JoinChannelError> {
return _internal_joinChannel(account: self.account, peerId: peerId, hash: hash)
}
public func removePeerMember(peerId: PeerId, memberId: PeerId) -> Signal<Void, NoError> {
return _internal_removePeerMember(account: self.account, peerId: peerId, memberId: memberId)
}
public func availableGroupsForChannelDiscussion() -> Signal<[Peer], AvailableChannelDiscussionGroupError> {
return _internal_availableGroupsForChannelDiscussion(postbox: self.account.postbox, network: self.account.network)
}
public func updateGroupDiscussionForChannel(channelId: PeerId?, groupId: PeerId?) -> Signal<Bool, ChannelDiscussionGroupError> {
return _internal_updateGroupDiscussionForChannel(network: self.account.network, postbox: self.account.postbox, channelId: channelId, groupId: groupId)
}
public func peerCommands(id: PeerId) -> Signal<PeerCommands, NoError> {
return _internal_peerCommands(account: self.account, id: id)
}
}
}

View File

@ -6,7 +6,7 @@ import MtProtoKit
import SyncCore
public func toggleShouldChannelMessagesSignatures(account:Account, peerId:PeerId, enabled: Bool) -> Signal<Void, NoError> {
func _internal_toggleShouldChannelMessagesSignatures(account:Account, peerId:PeerId, enabled: Bool) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
if let peer = transaction.getPeer(peerId) as? TelegramChannel, let inputChannel = apiInputChannel(peer) {
return account.network.request(Api.functions.channels.toggleSignatures(channel: inputChannel, enabled: enabled ? .boolTrue : .boolFalse)) |> retryRequest |> map { updates -> Void in

View File

@ -9,7 +9,7 @@ public enum UpdateGroupSpecificStickersetError {
case generic
}
public func updateGroupSpecificStickerset(postbox: Postbox, network: Network, peerId: PeerId, info: StickerPackCollectionInfo?) -> Signal<Void, UpdateGroupSpecificStickersetError> {
func _internal_updateGroupSpecificStickerset(postbox: Postbox, network: Network, peerId: PeerId, info: StickerPackCollectionInfo?) -> Signal<Void, UpdateGroupSpecificStickersetError> {
return postbox.loadedPeerWithId(peerId)
|> castError(UpdateGroupSpecificStickersetError.self)
|> mapToSignal { peer -> Signal<Void, UpdateGroupSpecificStickersetError> in

View File

@ -136,7 +136,7 @@ public final class ActiveSessionsContext {
}
}
public init(account: Account) {
init(account: Account) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
return ActiveSessionsContextImpl(account: account)
})
@ -218,7 +218,7 @@ public final class WebSessionsContext {
private let disposable = MetaDisposable()
public init(account: Account) {
init(account: Account) {
assert(Queue.mainQueue().isCurrent())
self.account = account

View File

@ -3,7 +3,7 @@ import Postbox
import TelegramApi
import SwiftSignalKit
public func requestRecentAccountSessions(account: Account) -> Signal<[RecentAccountSession], NoError> {
func requestRecentAccountSessions(account: Account) -> Signal<[RecentAccountSession], NoError> {
return account.network.request(Api.functions.account.getAuthorizations())
|> retryRequest
|> map { result -> [RecentAccountSession] in
@ -23,7 +23,7 @@ public enum TerminateSessionError {
case freshReset
}
public func terminateAccountSession(account: Account, hash: Int64) -> Signal<Void, TerminateSessionError> {
func terminateAccountSession(account: Account, hash: Int64) -> Signal<Void, TerminateSessionError> {
return account.network.request(Api.functions.account.resetAuthorization(hash: hash))
|> mapError { error -> TerminateSessionError in
if error.errorCode == 406 {
@ -36,7 +36,7 @@ public func terminateAccountSession(account: Account, hash: Int64) -> Signal<Voi
}
}
public func terminateOtherAccountSessions(account: Account) -> Signal<Void, TerminateSessionError> {
func terminateOtherAccountSessions(account: Account) -> Signal<Void, TerminateSessionError> {
return account.network.request(Api.functions.auth.resetAuthorizations())
|> mapError { error -> TerminateSessionError in
if error.errorCode == 406 {

View File

@ -21,7 +21,7 @@ public struct WebAuthorization : Equatable {
}
}
public func webSessions(network: Network) -> Signal<([WebAuthorization], [PeerId: Peer]), NoError> {
func webSessions(network: Network) -> Signal<([WebAuthorization], [PeerId: Peer]), NoError> {
return network.request(Api.functions.account.getWebAuthorizations())
|> retryRequest
|> map { result -> ([WebAuthorization], [PeerId : Peer]) in
@ -46,7 +46,7 @@ public func webSessions(network: Network) -> Signal<([WebAuthorization], [PeerId
}
public func terminateWebSession(network: Network, hash: Int64) -> Signal<Bool, NoError> {
func terminateWebSession(network: Network, hash: Int64) -> Signal<Bool, NoError> {
return network.request(Api.functions.account.resetWebAuthorization(hash: hash))
|> retryRequest
|> map { result in
@ -61,7 +61,7 @@ public func terminateWebSession(network: Network, hash: Int64) -> Signal<Bool, N
public func terminateAllWebSessions(network: Network) -> Signal<Void, NoError> {
func terminateAllWebSessions(network: Network) -> Signal<Void, NoError> {
return network.request(Api.functions.account.resetWebAuthorizations())
|> retryRequest
|> map { _ in }

View File

@ -12,5 +12,33 @@ public extension TelegramEngine {
public func requestUpdatePeerIsBlocked(peerId: PeerId, isBlocked: Bool) -> Signal<Void, NoError> {
return _internal_requestUpdatePeerIsBlocked(account: self.account, peerId: peerId, isBlocked: isBlocked)
}
public func activeSessions() -> ActiveSessionsContext {
return ActiveSessionsContext(account: self.account)
}
public func webSessions() -> WebSessionsContext {
return WebSessionsContext(account: self.account)
}
public func requestAccountPrivacySettings() -> Signal<AccountPrivacySettings, NoError> {
return _internal_requestAccountPrivacySettings(account: self.account)
}
public func updateAccountAutoArchiveChats(value: Bool) -> Signal<Never, NoError> {
return _internal_updateAccountAutoArchiveChats(account: self.account, value: value)
}
public func updateAccountRemovalTimeout(timeout: Int32) -> Signal<Void, NoError> {
return _internal_updateAccountRemovalTimeout(account: self.account, timeout: timeout)
}
public func updatePhoneNumberDiscovery(value: Bool) -> Signal<Void, NoError> {
return _internal_updatePhoneNumberDiscovery(account: self.account, value: value)
}
public func updateSelectiveAccountPrivacySettings(type: UpdateSelectiveAccountPrivacySettingsType, settings: SelectivePrivacySettings) -> Signal<Void, NoError> {
return _internal_updateSelectiveAccountPrivacySettings(account: self.account, type: type, settings: settings)
}
}
}

View File

@ -5,7 +5,7 @@ import SwiftSignalKit
import SyncCore
public func requestAccountPrivacySettings(account: Account) -> Signal<AccountPrivacySettings, NoError> {
func _internal_requestAccountPrivacySettings(account: Account) -> Signal<AccountPrivacySettings, NoError> {
let lastSeenPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyStatusTimestamp))
let groupPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyChatInvite))
let voiceCallPrivacy = account.network.request(Api.functions.account.getPrivacy(key: .inputPrivacyKeyPhoneCall))
@ -140,8 +140,7 @@ public func requestAccountPrivacySettings(account: Account) -> Signal<AccountPri
}
}
public func updateAccountAutoArchiveChats(account: Account, value: Bool) -> Signal<Never, NoError> {
func _internal_updateAccountAutoArchiveChats(account: Account, value: Bool) -> Signal<Never, NoError> {
return account.network.request(Api.functions.account.setGlobalPrivacySettings(
settings: .globalPrivacySettings(flags: 1 << 0, archiveAndMuteNewNoncontactPeers: value ? .boolTrue : .boolFalse)
))
@ -149,7 +148,7 @@ public func updateAccountAutoArchiveChats(account: Account, value: Bool) -> Sign
|> ignoreValues
}
public func updateAccountRemovalTimeout(account: Account, timeout: Int32) -> Signal<Void, NoError> {
func _internal_updateAccountRemovalTimeout(account: Account, timeout: Int32) -> Signal<Void, NoError> {
return account.network.request(Api.functions.account.setAccountTTL(ttl: .accountDaysTTL(days: timeout / (24 * 60 * 60))))
|> retryRequest
|> mapToSignal { _ -> Signal<Void, NoError> in
@ -157,7 +156,7 @@ public func updateAccountRemovalTimeout(account: Account, timeout: Int32) -> Sig
}
}
public func updatePhoneNumberDiscovery(account: Account, value: Bool) -> Signal<Void, NoError> {
func _internal_updatePhoneNumberDiscovery(account: Account, value: Bool) -> Signal<Void, NoError> {
var rules: [Api.InputPrivacyRule] = []
if value {
rules.append(.inputPrivacyValueAllowAll)
@ -223,7 +222,7 @@ private func apiUserAndGroupIds(peerIds: [PeerId: SelectivePrivacyPeer]) -> (use
return (users, groups)
}
public func updateSelectiveAccountPrivacySettings(account: Account, type: UpdateSelectiveAccountPrivacySettingsType, settings: SelectivePrivacySettings) -> Signal<Void, NoError> {
func _internal_updateSelectiveAccountPrivacySettings(account: Account, type: UpdateSelectiveAccountPrivacySettingsType, settings: SelectivePrivacySettings) -> Signal<Void, NoError> {
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
var rules: [Api.InputPrivacyRule] = []
switch settings {

View File

@ -59,6 +59,10 @@ public final class TelegramEngine {
public lazy var historyImport: HistoryImport = {
return HistoryImport(account: self.account)
}()
public lazy var contacts: Contacts = {
return Contacts(account: self.account)
}()
}
public final class TelegramEngineUnauthorized {

Some files were not shown because too many files have changed in this diff Show More