From 0cf92bb440728e89fd99786d1e96068551dde954 Mon Sep 17 00:00:00 2001 From: overtake Date: Thu, 11 Nov 2021 21:30:43 +0400 Subject: [PATCH] spm macos initial commit --- submodules/Crc32/Package.swift | 32 + submodules/CryptoUtils/Package.swift | 32 + submodules/EncryptionProvider/Package.swift | 32 + .../Sources/EncryptionProvider.mm | 1 + submodules/FFMpegBinding/Package.swift | 33 + submodules/GraphCore/Info.plist | 22 - submodules/GraphCore/Package.swift | 27 + submodules/GraphCore/Sources/GraphCore.h | 19 - submodules/MtProtoKit/Package.swift | 33 + submodules/MurMurHash32/Package.swift | 32 + .../PublicHeaders/MurMurHash32/MurMurHash32.h | 2 - .../MurMurHash32/Sources/MurMurHash32.m | 17 - submodules/NetworkLogging/Package.swift | 33 + submodules/OpusBinding/Package.swift | 35 + submodules/Postbox/Package.swift | 36 + .../Sources/ChatListViewState.swift.bak | 1429 ----------------- .../LegacyReachability/Package.swift | 32 + .../LegacyReachability/LegacyReachability.h | 14 +- submodules/Reachability/Package.swift | 30 + submodules/SSignalKit/Package.swift | 27 + .../StringTransliteration/Package.swift | 32 + submodules/TelegramApi/Package.swift | 27 + submodules/TelegramCore/Package.swift | 42 + .../Sources/MacOS/MacInternalUpdater.swift | 1 + submodules/TelegramVoip/Package.swift | 42 + .../macOS/OngoingCallVideoCapturer.swift | 140 ++ .../Sources/OngoingCallThreadLocalContext.mm | 5 +- submodules/libphonenumber/Package.swift | 32 + .../libphonenumber/libphonenumber.h | 5 +- submodules/sqlcipher/Package.swift | 44 + submodules/sqlcipher/Sources/sqlite3.c | 34 +- third-party/rnnoise/Package.swift | 65 + 32 files changed, 867 insertions(+), 1520 deletions(-) create mode 100644 submodules/Crc32/Package.swift create mode 100644 submodules/CryptoUtils/Package.swift create mode 100644 submodules/EncryptionProvider/Package.swift create mode 100644 submodules/EncryptionProvider/Sources/EncryptionProvider.mm create mode 100644 submodules/FFMpegBinding/Package.swift delete mode 100644 submodules/GraphCore/Info.plist create mode 100644 submodules/GraphCore/Package.swift delete mode 100644 submodules/GraphCore/Sources/GraphCore.h create mode 100644 submodules/MtProtoKit/Package.swift create mode 100644 submodules/MurMurHash32/Package.swift create mode 100644 submodules/NetworkLogging/Package.swift create mode 100644 submodules/OpusBinding/Package.swift create mode 100644 submodules/Postbox/Package.swift delete mode 100644 submodules/Postbox/Sources/ChatListViewState.swift.bak create mode 100644 submodules/Reachability/LegacyReachability/Package.swift create mode 100644 submodules/Reachability/Package.swift create mode 100644 submodules/SSignalKit/Package.swift create mode 100644 submodules/StringTransliteration/Package.swift create mode 100644 submodules/TelegramApi/Package.swift create mode 100644 submodules/TelegramCore/Package.swift create mode 100644 submodules/TelegramVoip/Package.swift create mode 100644 submodules/TelegramVoip/Sources/macOS/OngoingCallVideoCapturer.swift create mode 100644 submodules/libphonenumber/Package.swift create mode 100644 submodules/sqlcipher/Package.swift create mode 100644 third-party/rnnoise/Package.swift diff --git a/submodules/Crc32/Package.swift b/submodules/Crc32/Package.swift new file mode 100644 index 0000000000..12f92ab411 --- /dev/null +++ b/submodules/Crc32/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Crc32", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "Crc32", + targets: ["Crc32"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "Crc32", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/CryptoUtils/Package.swift b/submodules/CryptoUtils/Package.swift new file mode 100644 index 0000000000..33cf2c2b95 --- /dev/null +++ b/submodules/CryptoUtils/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "CryptoUtils", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "CryptoUtils", + targets: ["CryptoUtils"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "CryptoUtils", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/EncryptionProvider/Package.swift b/submodules/EncryptionProvider/Package.swift new file mode 100644 index 0000000000..59cfa24549 --- /dev/null +++ b/submodules/EncryptionProvider/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "EncryptionProvider", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "EncryptionProvider", + targets: ["EncryptionProvider"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "EncryptionProvider", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders"), + ]), + ] +) diff --git a/submodules/EncryptionProvider/Sources/EncryptionProvider.mm b/submodules/EncryptionProvider/Sources/EncryptionProvider.mm new file mode 100644 index 0000000000..6bd0d5fde3 --- /dev/null +++ b/submodules/EncryptionProvider/Sources/EncryptionProvider.mm @@ -0,0 +1 @@ +#import diff --git a/submodules/FFMpegBinding/Package.swift b/submodules/FFMpegBinding/Package.swift new file mode 100644 index 0000000000..558731a0ee --- /dev/null +++ b/submodules/FFMpegBinding/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "FFMpegBinding", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "FFMpegBinding", + targets: ["FFMpegBinding"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "FFMpegBinding", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "Public", + cSettings: [ + .headerSearchPath("Public"), + .unsafeFlags(["-I../../../../core-xprojects/ffmpeg/build/ffmpeg/include"]) + ]), + ] +) diff --git a/submodules/GraphCore/Info.plist b/submodules/GraphCore/Info.plist deleted file mode 100644 index e1fe4cfb7b..0000000000 --- a/submodules/GraphCore/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleVersion - $(CURRENT_PROJECT_VERSION) - - diff --git a/submodules/GraphCore/Package.swift b/submodules/GraphCore/Package.swift new file mode 100644 index 0000000000..9f749726ea --- /dev/null +++ b/submodules/GraphCore/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "GraphCore", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "GraphCore", + targets: ["GraphCore"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "GraphCore", + dependencies: [], + path: "Sources"), + ] +) diff --git a/submodules/GraphCore/Sources/GraphCore.h b/submodules/GraphCore/Sources/GraphCore.h deleted file mode 100644 index 32c43f37d3..0000000000 --- a/submodules/GraphCore/Sources/GraphCore.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// GraphCore.h -// GraphCore -// -// Created by Mikhail Filimonov on 03.02.2020. -// Copyright © 2020 Telegram. All rights reserved. -// - -#import - -//! Project version number for GraphCore. -FOUNDATION_EXPORT double GraphCoreVersionNumber; - -//! Project version string for GraphCore. -FOUNDATION_EXPORT const unsigned char GraphCoreVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - - diff --git a/submodules/MtProtoKit/Package.swift b/submodules/MtProtoKit/Package.swift new file mode 100644 index 0000000000..2d6b0da79d --- /dev/null +++ b/submodules/MtProtoKit/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MtProtoKit", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "MtProtoKit", + targets: ["MtProtoKit"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "EncryptionProvider", path: "../EncryptionProvider") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "MtProtoKit", + dependencies: [.product(name: "EncryptionProvider", package: "EncryptionProvider", condition: nil)], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders"), + ]), + ] +) diff --git a/submodules/MurMurHash32/Package.swift b/submodules/MurMurHash32/Package.swift new file mode 100644 index 0000000000..0766924842 --- /dev/null +++ b/submodules/MurMurHash32/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MurMurHash32", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "MurMurHash32", + targets: ["MurMurHash32"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "MurMurHash32", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/MurMurHash32/PublicHeaders/MurMurHash32/MurMurHash32.h b/submodules/MurMurHash32/PublicHeaders/MurMurHash32/MurMurHash32.h index fe2840c17b..69eeb1e99a 100644 --- a/submodules/MurMurHash32/PublicHeaders/MurMurHash32/MurMurHash32.h +++ b/submodules/MurMurHash32/PublicHeaders/MurMurHash32/MurMurHash32.h @@ -8,6 +8,4 @@ int32_t murMurHash32(void *bytes, int length); int32_t murMurHash32Data(NSData *data); int32_t murMurHashString32(const char *s); -NSString *postboxTransformedString(CFStringRef string, bool replaceWithTransliteratedVersion, bool appendTransliteratedVersion); - #endif diff --git a/submodules/MurMurHash32/Sources/MurMurHash32.m b/submodules/MurMurHash32/Sources/MurMurHash32.m index afbf1d2f83..5db59099a3 100644 --- a/submodules/MurMurHash32/Sources/MurMurHash32.m +++ b/submodules/MurMurHash32/Sources/MurMurHash32.m @@ -101,20 +101,3 @@ int32_t murMurHashString32(const char *s) return result; } -NSString *postboxTransformedString(CFStringRef string, bool replaceWithTransliteratedVersion, bool appendTransliteratedVersion) { - NSMutableString *mutableString = [[NSMutableString alloc] initWithString:(__bridge NSString * _Nonnull)(string)]; - CFStringTransform((CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, false); - - if (replaceWithTransliteratedVersion || appendTransliteratedVersion) { - NSMutableString *transliteratedString = [[NSMutableString alloc] initWithString:mutableString]; - CFStringTransform((CFMutableStringRef)transliteratedString, NULL, kCFStringTransformToLatin, false); - if (replaceWithTransliteratedVersion) { - return transliteratedString; - } else { - [mutableString appendString:@" "]; - [mutableString appendString:transliteratedString]; - } - } - - return mutableString; -} diff --git a/submodules/NetworkLogging/Package.swift b/submodules/NetworkLogging/Package.swift new file mode 100644 index 0000000000..2abba6c2ce --- /dev/null +++ b/submodules/NetworkLogging/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "NetworkLogging", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "NetworkLogging", + targets: ["NetworkLogging"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "MtProtoKit", path: "../MtProtoKit") + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "NetworkLogging", + dependencies: [.product(name: "MtProtoKit", package: "MtProtoKit", condition: nil)], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/OpusBinding/Package.swift b/submodules/OpusBinding/Package.swift new file mode 100644 index 0000000000..9b3abc3e84 --- /dev/null +++ b/submodules/OpusBinding/Package.swift @@ -0,0 +1,35 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "OpusBinding", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "OpusBinding", + targets: ["OpusBinding"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "OpusBinding", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders"), + .headerSearchPath("PublicHeaders/OpusBinding"), + .headerSearchPath("Sources"), + .unsafeFlags(["-I../../../../core-xprojects/libopus/build/libopus/include"]) + ]), + ] +) diff --git a/submodules/Postbox/Package.swift b/submodules/Postbox/Package.swift new file mode 100644 index 0000000000..cc6ef02c84 --- /dev/null +++ b/submodules/Postbox/Package.swift @@ -0,0 +1,36 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Postbox", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "Postbox", + targets: ["Postbox"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "MurMurHash32", path: "../MurMurHash32"), + .package(name: "Crc32", path: "../Crc32"), + .package(name: "sqlcipher", path: "../sqlcipher"), + .package(name: "StringTransliteration", path: "../StringTransliteration"), + .package(name: "SSignalKit", path: "../SSignalKit"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "Postbox", + dependencies: [.product(name: "MurMurHash32", package: "MurMurHash32", condition: nil), + .product(name: "SwiftSignalKit", package: "SSignalKit", condition: nil), + .product(name: "sqlcipher", package: "sqlcipher", condition: nil), + .product(name: "StringTransliteration", package: "StringTransliteration", condition: nil), + .product(name: "Crc32", package: "Crc32", condition: nil)], + path: "Sources"), + ] +) diff --git a/submodules/Postbox/Sources/ChatListViewState.swift.bak b/submodules/Postbox/Sources/ChatListViewState.swift.bak deleted file mode 100644 index 917cfb560e..0000000000 --- a/submodules/Postbox/Sources/ChatListViewState.swift.bak +++ /dev/null @@ -1,1429 +0,0 @@ - -enum ChatListViewSpacePinned { - case notPinned - case includePinned - case includePinnedAsUnpinned - - var include: Bool { - switch self { - case .notPinned: - return false - case .includePinned, .includePinnedAsUnpinned: - return true - } - } -} - -enum ChatListViewSpace: Hashable { - case group(groupId: PeerGroupId, pinned: ChatListViewSpacePinned, predicate: ChatListFilterPredicate?) - case peers(peerIds: [PeerId], asPinned: Bool) - - static func ==(lhs: ChatListViewSpace, rhs: ChatListViewSpace) -> Bool { - switch lhs { - case let .group(groupId, pinned, _): - if case let .group(rhsGroupId, rhsPinned, _) = rhs { - if groupId != rhsGroupId { - return false - } - if pinned != rhsPinned { - return false - } - return true - } else { - return false - } - case let .peers(peerIds, asPinned): - if case .peers(peerIds, asPinned) = rhs { - return true - } else { - return false - } - } - } - - func hash(into hasher: inout Hasher) { - switch self { - case let .group(groupId, pinned, _): - hasher.combine(groupId) - hasher.combine(pinned) - case let .peers(peerIds, asPinned): - hasher.combine(peerIds) - hasher.combine(asPinned) - } - } -} - -private func mappedChatListFilterPredicate(postbox: Postbox, groupId: PeerGroupId, predicate: ChatListFilterPredicate) -> (ChatListIntermediateEntry) -> Bool { - let globalNotificationSettings = postbox.getGlobalNotificationSettings() - return { entry in - switch entry { - case let .message(index, _): - if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) { - let isUnread = postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId)?.isUnread ?? false - let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - let isContact = postbox.contactsTable.isContact(peerId: notificationsPeerId) - let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId)) - let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, calculation: predicate.messageTagSummary) - - if predicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: messageTagSummaryResult) { - return true - } else { - return false - } - } else { - return false - } - case .hole: - return true - } - } -} - -private func updateMessagePeers(_ message: Message, updatedPeers: [PeerId: Peer]) -> Message? { - var updated = false - for (peerId, currentPeer) in message.peers { - if let updatedPeer = updatedPeers[peerId], !arePeersEqual(currentPeer, updatedPeer) { - updated = true - break - } - } - if updated { - var peers = SimpleDictionary() - for (peerId, currentPeer) in message.peers { - if let updatedPeer = updatedPeers[peerId] { - peers[peerId] = updatedPeer - } else { - peers[peerId] = currentPeer - } - } - return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds) - } - return nil -} - -private func updatedRenderedPeer(_ renderedPeer: RenderedPeer, updatedPeers: [PeerId: Peer]) -> RenderedPeer? { - var updated = false - for (peerId, currentPeer) in renderedPeer.peers { - if let updatedPeer = updatedPeers[peerId], !arePeersEqual(currentPeer, updatedPeer) { - updated = true - break - } - } - if updated { - var peers = SimpleDictionary() - for (peerId, currentPeer) in renderedPeer.peers { - if let updatedPeer = updatedPeers[peerId] { - peers[peerId] = updatedPeer - } else { - peers[peerId] = currentPeer - } - } - return RenderedPeer(peerId: renderedPeer.peerId, peers: peers) - } - return nil -} - -private final class ChatListViewSpaceState { - private let space: ChatListViewSpace - private let anchorIndex: MutableChatListEntryIndex - private let summaryComponents: ChatListEntrySummaryComponents - private let halfLimit: Int - - var orderedEntries: OrderedChatListViewEntries - - init(postbox: Postbox, space: ChatListViewSpace, anchorIndex: MutableChatListEntryIndex, summaryComponents: ChatListEntrySummaryComponents, halfLimit: Int) { - self.space = space - self.anchorIndex = anchorIndex - self.summaryComponents = summaryComponents - self.halfLimit = halfLimit - self.orderedEntries = OrderedChatListViewEntries(anchorIndex: anchorIndex.index, lowerOrAtAnchor: [], higherThanAnchor: []) - self.fillSpace(postbox: postbox) - - self.checkEntries(postbox: postbox) - } - - private func fillSpace(postbox: Postbox) { - switch self.space { - case let .group(groupId, pinned, filterPredicate): - let lowerBound: MutableChatListEntryIndex - let upperBound: MutableChatListEntryIndex - if pinned.include { - upperBound = .absoluteUpperBound - lowerBound = MutableChatListEntryIndex(index: ChatListIndex.pinnedLowerBound, isMessage: true) - } else { - upperBound = MutableChatListEntryIndex(index: ChatListIndex.pinnedLowerBound.predecessor, isMessage: true) - lowerBound = .absoluteLowerBound - } - let resolvedAnchorIndex = min(upperBound, max(self.anchorIndex, lowerBound)) - - var lowerOrAtAnchorMessages: [MutableChatListEntry] = self.orderedEntries.lowerOrAtAnchor.reversed() - var higherThanAnchorMessages: [MutableChatListEntry] = self.orderedEntries.higherThanAnchor - - func mapEntry(_ entry: ChatListIntermediateEntry) -> MutableChatListEntry { - switch entry { - case let .message(index, messageIndex): - var updatedIndex = index - if case .includePinnedAsUnpinned = pinned { - updatedIndex = ChatListIndex(pinningIndex: nil, messageIndex: index.messageIndex) - } - return .IntermediateMessageEntry(index: updatedIndex, messageIndex: messageIndex) - case let .hole(hole): - return .HoleEntry(hole) - } - } - - if case .includePinnedAsUnpinned = pinned { - let unpinnedLowerBound: MutableChatListEntryIndex - let unpinnedUpperBound: MutableChatListEntryIndex - unpinnedUpperBound = .absoluteUpperBound - unpinnedLowerBound = MutableChatListEntryIndex(index: ChatListIndex.absoluteLowerBound, isMessage: true) - let resolvedUnpinnedAnchorIndex = min(unpinnedUpperBound, max(self.anchorIndex, unpinnedLowerBound)) - - if lowerOrAtAnchorMessages.count < self.halfLimit || higherThanAnchorMessages.count < self.halfLimit { - let loadedMessages = postbox.chatListTable.entries(groupId: groupId, from: (ChatListIndex.pinnedLowerBound, true), to: (ChatListIndex.absoluteUpperBound, true), peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable, count: self.halfLimit * 2, predicate: filterPredicate.flatMap { mappedChatListFilterPredicate(postbox: postbox, groupId: groupId, predicate: $0) }).map(mapEntry).sorted(by: { $0.entryIndex < $1.entryIndex }) - - if lowerOrAtAnchorMessages.count < self.halfLimit { - var nextLowerIndex: MutableChatListEntryIndex - if let lastMessage = lowerOrAtAnchorMessages.min(by: { $0.entryIndex < $1.entryIndex }) { - nextLowerIndex = lastMessage.entryIndex.predecessor - } else { - nextLowerIndex = min(resolvedUnpinnedAnchorIndex, self.anchorIndex) - } - var loadedLowerMessages = Array(loadedMessages.filter({ $0.entryIndex <= nextLowerIndex }).reversed()) - let lowerLimit = self.halfLimit - lowerOrAtAnchorMessages.count - if loadedLowerMessages.count > lowerLimit { - loadedLowerMessages.removeLast(loadedLowerMessages.count - lowerLimit) - } - lowerOrAtAnchorMessages.append(contentsOf: loadedLowerMessages) - } - if higherThanAnchorMessages.count < self.halfLimit { - var nextHigherIndex: MutableChatListEntryIndex - if let lastMessage = higherThanAnchorMessages.max(by: { $0.entryIndex < $1.entryIndex }) { - nextHigherIndex = lastMessage.entryIndex.successor - } else { - nextHigherIndex = max(resolvedUnpinnedAnchorIndex, self.anchorIndex.successor) - } - var loadedHigherMessages = loadedMessages.filter({ $0.entryIndex > nextHigherIndex }) - let higherLimit = self.halfLimit - higherThanAnchorMessages.count - if loadedHigherMessages.count > higherLimit { - loadedHigherMessages.removeLast(loadedHigherMessages.count - higherLimit) - } - higherThanAnchorMessages.append(contentsOf: loadedHigherMessages) - } - } - } else { - if lowerOrAtAnchorMessages.count < self.halfLimit { - var nextLowerIndex: MutableChatListEntryIndex - if let lastMessage = lowerOrAtAnchorMessages.min(by: { $0.entryIndex < $1.entryIndex }) { - nextLowerIndex = lastMessage.entryIndex - } else { - nextLowerIndex = resolvedAnchorIndex.successor - } - let loadedLowerMessages = postbox.chatListTable.entries(groupId: groupId, from: (nextLowerIndex.index, nextLowerIndex.isMessage), to: (lowerBound.index, lowerBound.isMessage), peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable, count: self.halfLimit - lowerOrAtAnchorMessages.count, predicate: filterPredicate.flatMap { mappedChatListFilterPredicate(postbox: postbox, groupId: groupId, predicate: $0) }).map(mapEntry) - lowerOrAtAnchorMessages.append(contentsOf: loadedLowerMessages) - } - if higherThanAnchorMessages.count < self.halfLimit { - var nextHigherIndex: MutableChatListEntryIndex - if let lastMessage = higherThanAnchorMessages.max(by: { $0.entryIndex < $1.entryIndex }) { - nextHigherIndex = lastMessage.entryIndex - } else { - nextHigherIndex = resolvedAnchorIndex - } - let loadedHigherMessages = postbox.chatListTable.entries(groupId: groupId, from: (nextHigherIndex.index, nextHigherIndex.isMessage), to: (upperBound.index, upperBound.isMessage), peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable, count: self.halfLimit - higherThanAnchorMessages.count, predicate: filterPredicate.flatMap { mappedChatListFilterPredicate(postbox: postbox, groupId: groupId, predicate: $0) }).map(mapEntry) - higherThanAnchorMessages.append(contentsOf: loadedHigherMessages) - } - } - - lowerOrAtAnchorMessages.reverse() - - assert(lowerOrAtAnchorMessages.count <= self.halfLimit) - assert(higherThanAnchorMessages.count <= self.halfLimit) - - let allIndices = (lowerOrAtAnchorMessages + higherThanAnchorMessages).map { $0.entryIndex } - if Set(allIndices).count != allIndices.count { - var existingIndices = Set() - for i in (0 ..< lowerOrAtAnchorMessages.count).reversed() { - if !existingIndices.contains(lowerOrAtAnchorMessages[i].entryIndex) { - existingIndices.insert(lowerOrAtAnchorMessages[i].entryIndex) - } else { - lowerOrAtAnchorMessages.remove(at: i) - } - } - for i in (0 ..< higherThanAnchorMessages.count).reversed() { - if !existingIndices.contains(higherThanAnchorMessages[i].entryIndex) { - existingIndices.insert(higherThanAnchorMessages[i].entryIndex) - } else { - higherThanAnchorMessages.remove(at: i) - } - } - assert(false) - } - - assert(allIndices.sorted() == allIndices) - - let entries = OrderedChatListViewEntries(anchorIndex: self.anchorIndex.index, lowerOrAtAnchor: lowerOrAtAnchorMessages, higherThanAnchor: higherThanAnchorMessages) - self.orderedEntries = entries - case let .peers(peerIds, asPinned): - var lowerOrAtAnchorMessages: [MutableChatListEntry] = self.orderedEntries.lowerOrAtAnchor.reversed() - var higherThanAnchorMessages: [MutableChatListEntry] = self.orderedEntries.higherThanAnchor - - let unpinnedLowerBound: MutableChatListEntryIndex - let unpinnedUpperBound: MutableChatListEntryIndex - unpinnedUpperBound = .absoluteUpperBound - unpinnedLowerBound = MutableChatListEntryIndex(index: ChatListIndex.absoluteLowerBound, isMessage: true) - let resolvedUnpinnedAnchorIndex = min(unpinnedUpperBound, max(self.anchorIndex, unpinnedLowerBound)) - - if lowerOrAtAnchorMessages.count < self.halfLimit || higherThanAnchorMessages.count < self.halfLimit { - func mapEntry(_ entry: ChatListIntermediateEntry, pinningIndex: UInt16?) -> MutableChatListEntry { - switch entry { - case let .message(index, messageIndex): - var updatedIndex = index - updatedIndex = ChatListIndex(pinningIndex: pinningIndex, messageIndex: index.messageIndex) - return .IntermediateMessageEntry(index: updatedIndex, messageIndex: messageIndex) - case let .hole(hole): - return .HoleEntry(hole) - } - } - - var loadedMessages: [MutableChatListEntry] = [] - for i in 0 ..< peerIds.count { - let peerId = peerIds[i] - if let entry = postbox.chatListTable.getEntry(peerId: peerId, messageHistoryTable: postbox.messageHistoryTable, peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable) { - loadedMessages.append(mapEntry(entry, pinningIndex: asPinned ? UInt16(i) : nil)) - } - } - loadedMessages.sort(by: { $0.entryIndex < $1.entryIndex }) - - if lowerOrAtAnchorMessages.count < self.halfLimit { - var nextLowerIndex: MutableChatListEntryIndex - if let lastMessage = lowerOrAtAnchorMessages.min(by: { $0.entryIndex < $1.entryIndex }) { - nextLowerIndex = lastMessage.entryIndex.predecessor - } else { - nextLowerIndex = min(resolvedUnpinnedAnchorIndex, self.anchorIndex) - } - var loadedLowerMessages = Array(loadedMessages.filter({ $0.entryIndex <= nextLowerIndex }).reversed()) - let lowerLimit = self.halfLimit - lowerOrAtAnchorMessages.count - if loadedLowerMessages.count > lowerLimit { - loadedLowerMessages.removeLast(loadedLowerMessages.count - lowerLimit) - } - lowerOrAtAnchorMessages.append(contentsOf: loadedLowerMessages) - } - if higherThanAnchorMessages.count < self.halfLimit { - var nextHigherIndex: MutableChatListEntryIndex - if let lastMessage = higherThanAnchorMessages.max(by: { $0.entryIndex < $1.entryIndex }) { - nextHigherIndex = lastMessage.entryIndex.successor - } else { - nextHigherIndex = max(resolvedUnpinnedAnchorIndex, self.anchorIndex.successor) - } - var loadedHigherMessages = loadedMessages.filter({ $0.entryIndex > nextHigherIndex }) - let higherLimit = self.halfLimit - higherThanAnchorMessages.count - if loadedHigherMessages.count > higherLimit { - loadedHigherMessages.removeLast(loadedHigherMessages.count - higherLimit) - } - higherThanAnchorMessages.append(contentsOf: loadedHigherMessages) - } - - lowerOrAtAnchorMessages.reverse() - - assert(lowerOrAtAnchorMessages.count <= self.halfLimit) - assert(higherThanAnchorMessages.count <= self.halfLimit) - - let allIndices = (lowerOrAtAnchorMessages + higherThanAnchorMessages).map { $0.entryIndex } - assert(Set(allIndices).count == allIndices.count) - assert(allIndices.sorted() == allIndices) - - let entries = OrderedChatListViewEntries(anchorIndex: self.anchorIndex.index, lowerOrAtAnchor: lowerOrAtAnchorMessages, higherThanAnchor: higherThanAnchorMessages) - self.orderedEntries = entries - } - } - } - - func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool { - var hasUpdates = false - var hadRemovals = false - var globalNotificationSettings: PostboxGlobalNotificationSettings? - for (groupId, operations) in transaction.chatListOperations { - inner: for operation in operations { - switch operation { - case let .InsertEntry(index, messageIndex): - switch self.space { - case let .group(spaceGroupId, pinned, filterPredicate): - let matchesGroup = groupId == spaceGroupId && (index.pinningIndex != nil) == pinned.include - if !matchesGroup { - continue inner - } - - var updatedIndex = index - if case .includePinnedAsUnpinned = pinned { - updatedIndex = ChatListIndex(pinningIndex: nil, messageIndex: index.messageIndex) - } - if let filterPredicate = filterPredicate { - if let peer = postbox.peerTable.get(updatedIndex.messageIndex.id.peerId) { - let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - let globalNotificationSettingsValue: PostboxGlobalNotificationSettings - if let current = globalNotificationSettings { - globalNotificationSettingsValue = current - } else { - globalNotificationSettingsValue = postbox.getGlobalNotificationSettings() - globalNotificationSettings = globalNotificationSettingsValue - } - - let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: peer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId)) - - let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, calculation: filterPredicate.messageTagSummary) - - if !filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: postbox.readStateTable.getCombinedState(peer.id)?.isUnread ?? false, isContact: postbox.contactsTable.isContact(peerId: notificationsPeerId), messageTagSummaryResult: messageTagSummaryResult) { - continue inner - } - } else { - continue inner - } - } - if self.add(entry: .IntermediateMessageEntry(index: updatedIndex, messageIndex: messageIndex)) { - hasUpdates = true - } else { - hasUpdates = true - hadRemovals = true - } - case let .peers(peerIds, asPinned): - if let peerIndex = peerIds.firstIndex(of: index.messageIndex.id.peerId) { - var updatedIndex = index - if asPinned { - updatedIndex = ChatListIndex(pinningIndex: UInt16(peerIndex), messageIndex: index.messageIndex) - } - if self.add(entry: .IntermediateMessageEntry(index: updatedIndex, messageIndex: messageIndex)) { - hasUpdates = true - } else { - hasUpdates = true - hadRemovals = true - } - } else { - continue inner - } - } - case let .InsertHole(hole): - switch self.space { - case let .group(spaceGroupId, pinned, _): - if spaceGroupId == groupId && !pinned.include { - if self.add(entry: .HoleEntry(hole)) { - hasUpdates = true - } else { - hasUpdates = true - hadRemovals = true - } - } - case .peers: - break - } - case let .RemoveEntry(indices): - switch self.space { - case let .group(spaceGroupId, pinned, _): - if spaceGroupId == groupId { - for index in indices { - var updatedIndex = index - if case .includePinnedAsUnpinned = pinned { - updatedIndex = ChatListIndex(pinningIndex: nil, messageIndex: index.messageIndex) - } - - if self.orderedEntries.remove(index: MutableChatListEntryIndex(index: updatedIndex, isMessage: true)) { - hasUpdates = true - hadRemovals = true - } - } - } - case let .peers(peerIds, asPinned): - for index in indices { - if let peerIndex = peerIds.firstIndex(of: index.messageIndex.id.peerId) { - var updatedIndex = index - if asPinned { - updatedIndex = ChatListIndex(pinningIndex: UInt16(peerIndex), messageIndex: index.messageIndex) - } - - if self.orderedEntries.remove(index: MutableChatListEntryIndex(index: updatedIndex, isMessage: true)) { - hasUpdates = true - hadRemovals = true - } - } - } - } - case let .RemoveHoles(indices): - switch self.space { - case let .group(spaceGroupId, pinned, _): - if spaceGroupId == groupId && !pinned.include { - for index in indices { - if self.orderedEntries.remove(index: MutableChatListEntryIndex(index: index, isMessage: false)) { - hasUpdates = true - hadRemovals = true - } - } - } - case .peers: - break - } - } - } - } - - if !transaction.currentUpdatedPeerNotificationSettings.isEmpty, case let .group(groupId, pinned, maybeFilterPredicate) = self.space, let filterPredicate = maybeFilterPredicate { - var removeEntryIndices: [MutableChatListEntryIndex] = [] - let _ = self.orderedEntries.mutableScan { entry in - let entryPeer: Peer - let entryNotificationsPeerId: PeerId - switch entry { - case let .MessageEntry(messageEntry): - if let peer = messageEntry.renderedPeer.peer { - entryPeer = peer - entryNotificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - } else { - return nil - } - case let .IntermediateMessageEntry(intermediateMessageEntry): - if let peer = postbox.peerTable.get(intermediateMessageEntry.index.messageIndex.id.peerId) { - entryPeer = peer - entryNotificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - } else { - return nil - } - case .HoleEntry: - return nil - } - if let settingsChange = transaction.currentUpdatedPeerNotificationSettings[entryNotificationsPeerId] { - let isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false - - let globalNotificationSettingsValue: PostboxGlobalNotificationSettings - if let current = globalNotificationSettings { - globalNotificationSettingsValue = current - } else { - globalNotificationSettingsValue = postbox.getGlobalNotificationSettings() - globalNotificationSettings = globalNotificationSettingsValue - } - - let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: entryPeer, peerSettings: settingsChange.1) - - let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: entryPeer.id, calculation: filterPredicate.messageTagSummary) - - let isIncluded = filterPredicate.includes(peer: entryPeer, groupId: groupId, isRemovedFromTotalUnreadCount: nowRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: entryNotificationsPeerId), messageTagSummaryResult: messageTagSummaryResult) - if !isIncluded { - removeEntryIndices.append(entry.entryIndex) - } - } - return nil - } - if !removeEntryIndices.isEmpty { - hasUpdates = true - hadRemovals = true - for index in removeEntryIndices { - let _ = self.orderedEntries.remove(index: index) - } - } - for (peerId, settingsChange) in transaction.currentUpdatedPeerNotificationSettings { - if let mainPeer = postbox.peerTable.get(peerId) { - var peers: [Peer] = [mainPeer] - for associatedId in postbox.reverseAssociatedPeerTable.get(peerId: mainPeer.id) { - if let associatedPeer = postbox.peerTable.get(associatedId) { - peers.append(associatedPeer) - } - } - assert(Set(peers.map { $0.id }).count == peers.count) - - let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false - - let globalNotificationSettingsValue: PostboxGlobalNotificationSettings - if let current = globalNotificationSettings { - globalNotificationSettingsValue = current - } else { - globalNotificationSettingsValue = postbox.getGlobalNotificationSettings() - globalNotificationSettings = globalNotificationSettingsValue - } - - let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: mainPeer, peerSettings: settingsChange.1) - - let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peerId, calculation: filterPredicate.messageTagSummary) - - let isIncluded = filterPredicate.includes(peer: mainPeer, groupId: groupId, isRemovedFromTotalUnreadCount: nowRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: peerId), messageTagSummaryResult: messageTagSummaryResult) - if isIncluded && self.orderedEntries.indicesForPeerId(mainPeer.id) == nil { - for peer in peers { - let tableEntry = postbox.chatListTable.getEntry(groupId: groupId, peerId: peer.id, messageHistoryTable: postbox.messageHistoryTable, peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable) - if let entry = tableEntry { - if pinned.include == (entry.index.pinningIndex != nil) { - if self.orderedEntries.indicesForPeerId(peer.id) == nil { - switch entry { - case let .message(index, messageIndex): - if self.add(entry: .IntermediateMessageEntry(index: index, messageIndex: messageIndex)) { - hasUpdates = true - } else { - hasUpdates = true - hadRemovals = true - } - default: - break - } - } - } - } - } - } - } - } - } - - if !transaction.currentUpdatedPeerNotificationSettings.isEmpty { - let globalNotificationSettings = postbox.getGlobalNotificationSettings() - - if self.orderedEntries.mutableScan({ entry in - switch entry { - case let .MessageEntry(messageEntry): - if let peer = messageEntry.renderedPeer.peer { - let notificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - if let (_, updated) = transaction.currentUpdatedPeerNotificationSettings[notificationsPeerId] { - let isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettings, peer: peer, peerSettings: updated) - - return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: updated, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact) - } else { - return nil - } - } else { - return nil - } - default: - return nil - } - }) { - hasUpdates = true - } - } - - if !transaction.updatedFailedMessagePeerIds.isEmpty { - if self.orderedEntries.mutableScan({ entry in - switch entry { - case let .MessageEntry(messageEntry): - if transaction.updatedFailedMessagePeerIds.contains(messageEntry.index.messageIndex.id.peerId) { - return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: postbox.messageHistoryFailedTable.contains(peerId: messageEntry.index.messageIndex.id.peerId), isContact: messageEntry.isContact) - } else { - return nil - } - default: - return nil - } - }) { - hasUpdates = true - } - } - - if !transaction.currentUpdatedPeers.isEmpty { - if self.orderedEntries.mutableScan({ entry in - switch entry { - case let .MessageEntry(messageEntry): - var updatedMessage: Message? - if let message = messageEntry.message { - updatedMessage = updateMessagePeers(message, updatedPeers: transaction.currentUpdatedPeers) - } - let renderedPeer = updatedRenderedPeer(messageEntry.renderedPeer, updatedPeers: transaction.currentUpdatedPeers) - - if updatedMessage != nil || renderedPeer != nil { - return .MessageEntry(index: messageEntry.index, message: updatedMessage ?? messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: renderedPeer ?? messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact) - } else { - return nil - } - default: - return nil - } - }) { - hasUpdates = true - } - } - - if !transaction.currentUpdatedPeerPresences.isEmpty { - if self.orderedEntries.mutableScan({ entry in - switch entry { - case let .MessageEntry(messageEntry): - var presencePeerId = messageEntry.renderedPeer.peerId - if let peer = messageEntry.renderedPeer.peers[messageEntry.renderedPeer.peerId], let associatedPeerId = peer.associatedPeerId { - presencePeerId = associatedPeerId - } - if let presence = transaction.currentUpdatedPeerPresences[presencePeerId] { - return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: presence, tagSummaryInfo: messageEntry.tagSummaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact) - } else { - return nil - } - default: - return nil - } - }) { - hasUpdates = true - } - } - - if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty, case let .group(groupId, pinned, maybeFilterPredicate) = self.space, let filterPredicate = maybeFilterPredicate, let filterMessageTagSummary = filterPredicate.messageTagSummary { - var removeEntryIndices: [MutableChatListEntryIndex] = [] - let _ = self.orderedEntries.mutableScan { entry in - let entryPeer: Peer - let entryNotificationsPeerId: PeerId - switch entry { - case let .MessageEntry(messageEntry): - if let peer = messageEntry.renderedPeer.peer { - entryPeer = peer - entryNotificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - } else { - return nil - } - case let .IntermediateMessageEntry(intermediateMessageEntry): - if let peer = postbox.peerTable.get(intermediateMessageEntry.index.messageIndex.id.peerId) { - entryPeer = peer - entryNotificationsPeerId = peer.notificationSettingsPeerId ?? peer.id - } else { - return nil - } - case .HoleEntry: - return nil - } - - let updatedMessageSummary = transaction.currentUpdatedMessageTagSummaries[MessageHistoryTagsSummaryKey(tag: filterMessageTagSummary.addCount.tag, peerId: entryPeer.id, namespace: filterMessageTagSummary.addCount.namespace)] - let updatedActionsSummary = transaction.currentUpdatedMessageActionsSummaries[PendingMessageActionsSummaryKey(type: filterMessageTagSummary.subtractCount.type, peerId: entryPeer.id, namespace: filterMessageTagSummary.subtractCount.namespace)] - - if updatedMessageSummary != nil || updatedActionsSummary != nil { - let isUnread = postbox.readStateTable.getCombinedState(entryPeer.id)?.isUnread ?? false - - let globalNotificationSettingsValue: PostboxGlobalNotificationSettings - if let current = globalNotificationSettings { - globalNotificationSettingsValue = current - } else { - globalNotificationSettingsValue = postbox.getGlobalNotificationSettings() - globalNotificationSettings = globalNotificationSettingsValue - } - - let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: entryPeer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(entryPeer.id)) - - let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: entryPeer.id, calculation: filterPredicate.messageTagSummary) - - let isIncluded = filterPredicate.includes(peer: entryPeer, groupId: groupId, isRemovedFromTotalUnreadCount: nowRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: entryNotificationsPeerId), messageTagSummaryResult: messageTagSummaryResult) - if !isIncluded { - removeEntryIndices.append(entry.entryIndex) - } - } - return nil - } - if !removeEntryIndices.isEmpty { - hasUpdates = true - hadRemovals = true - for index in removeEntryIndices { - let _ = self.orderedEntries.remove(index: index) - } - } - var changedPeerIds = Set() - for key in transaction.currentUpdatedMessageTagSummaries.keys { - changedPeerIds.insert(key.peerId) - } - for key in transaction.currentUpdatedMessageTagSummaries.keys { - changedPeerIds.insert(key.peerId) - } - for peerId in changedPeerIds { - if let mainPeer = postbox.peerTable.get(peerId) { - var peers: [Peer] = [mainPeer] - for associatedId in postbox.reverseAssociatedPeerTable.get(peerId: mainPeer.id) { - if let associatedPeer = postbox.peerTable.get(associatedId) { - peers.append(associatedPeer) - } - } - assert(Set(peers.map { $0.id }).count == peers.count) - - let isUnread = postbox.readStateTable.getCombinedState(peerId)?.isUnread ?? false - - let globalNotificationSettingsValue: PostboxGlobalNotificationSettings - if let current = globalNotificationSettings { - globalNotificationSettingsValue = current - } else { - globalNotificationSettingsValue = postbox.getGlobalNotificationSettings() - globalNotificationSettings = globalNotificationSettingsValue - } - - let nowRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: globalNotificationSettingsValue, peer: mainPeer, peerSettings: postbox.peerNotificationSettingsTable.getEffective(mainPeer.id)) - - let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peerId, calculation: filterPredicate.messageTagSummary) - - let isIncluded = filterPredicate.includes(peer: mainPeer, groupId: groupId, isRemovedFromTotalUnreadCount: nowRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: postbox.contactsTable.isContact(peerId: peerId), messageTagSummaryResult: messageTagSummaryResult) - if isIncluded && self.orderedEntries.indicesForPeerId(mainPeer.id) == nil { - for peer in peers { - let tableEntry = postbox.chatListTable.getEntry(groupId: groupId, peerId: peer.id, messageHistoryTable: postbox.messageHistoryTable, peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable) - if let entry = tableEntry { - if pinned.include == (entry.index.pinningIndex != nil) { - if self.orderedEntries.indicesForPeerId(peer.id) == nil { - switch entry { - case let .message(index, messageIndex): - if self.add(entry: .IntermediateMessageEntry(index: index, messageIndex: messageIndex)) { - hasUpdates = true - } else { - hasUpdates = true - hadRemovals = true - } - default: - break - } - } - } - } - } - } - } - } - } - - if !transaction.currentUpdatedMessageTagSummaries.isEmpty || !transaction.currentUpdatedMessageActionsSummaries.isEmpty { - if self.orderedEntries.mutableScan({ entry in - switch entry { - case let .MessageEntry(messageEntry): - var updatedTagSummaryCount: Int32? - var updatedActionsSummaryCount: Int32? - - if let tagSummary = self.summaryComponents.tagSummary { - let key = MessageHistoryTagsSummaryKey(tag: tagSummary.tag, peerId: messageEntry.index.messageIndex.id.peerId, namespace: tagSummary.namespace) - if let summary = transaction.currentUpdatedMessageTagSummaries[key] { - updatedTagSummaryCount = summary.count - } - } - - if let actionsSummary = self.summaryComponents.actionsSummary { - let key = PendingMessageActionsSummaryKey(type: actionsSummary.type, peerId: messageEntry.index.messageIndex.id.peerId, namespace: actionsSummary.namespace) - if let count = transaction.currentUpdatedMessageActionsSummaries[key] { - updatedActionsSummaryCount = count - } - } - - if updatedTagSummaryCount != nil || updatedActionsSummaryCount != nil { - let summaryInfo = ChatListMessageTagSummaryInfo(tagSummaryCount: updatedTagSummaryCount ?? messageEntry.tagSummaryInfo.tagSummaryCount, actionsSummaryCount: updatedActionsSummaryCount ?? messageEntry.tagSummaryInfo.actionsSummaryCount) - - return .MessageEntry(index: messageEntry.index, message: messageEntry.message, readState: messageEntry.readState, notificationSettings: messageEntry.notificationSettings, isRemovedFromTotalUnreadCount: messageEntry.isRemovedFromTotalUnreadCount, embeddedInterfaceState: messageEntry.embeddedInterfaceState, renderedPeer: messageEntry.renderedPeer, presence: messageEntry.presence, tagSummaryInfo: summaryInfo, hasFailedMessages: messageEntry.hasFailedMessages, isContact: messageEntry.isContact) - } else { - return nil - } - default: - return nil - } - }) { - hasUpdates = true - } - } - - self.fillSpace(postbox: postbox) - - self.checkEntries(postbox: postbox) - self.checkReplayEntries(postbox: postbox) - - return hasUpdates - } - - private func checkEntries(postbox: Postbox) { - #if DEBUG - if case .group(.root, .notPinned, nil) = self.space { - let allEntries = self.orderedEntries.lowerOrAtAnchor + self.orderedEntries.higherThanAnchor - if !allEntries.isEmpty { - assert(allEntries.sorted(by: { $0.index < $1.index }) == allEntries) - - func mapEntry(_ entry: ChatListIntermediateEntry) -> MutableChatListEntry { - switch entry { - case let .message(index, messageIndex): - return .IntermediateMessageEntry(index: index, messageIndex: messageIndex) - case let .hole(hole): - return .HoleEntry(hole) - } - } - - let loadedEntries = postbox.chatListTable.entries(groupId: .root, from: (allEntries[0].index.predecessor, true), to: (allEntries[allEntries.count - 1].index.successor, true), peerChatInterfaceStateTable: postbox.peerChatInterfaceStateTable, count: 1000, predicate: nil).map(mapEntry) - - assert(loadedEntries.map({ $0.index }) == allEntries.map({ $0.index })) - } - } - #endif - } - - private func checkReplayEntries(postbox: Postbox) { - #if DEBUG - let cleanState = ChatListViewSpaceState(postbox: postbox, space: self.space, anchorIndex: self.anchorIndex, summaryComponents: self.summaryComponents, halfLimit: self.halfLimit) - assert(self.orderedEntries.lowerOrAtAnchor.map { $0.index } == cleanState.orderedEntries.lowerOrAtAnchor.map { $0.index }) - assert(self.orderedEntries.higherThanAnchor.map { $0.index } == cleanState.orderedEntries.higherThanAnchor.map { $0.index }) - #endif - } - - private func add(entry: MutableChatListEntry) -> Bool { - if self.anchorIndex >= entry.entryIndex { - let insertionIndex = binaryInsertionIndex(self.orderedEntries.lowerOrAtAnchor, extract: { $0.entryIndex }, searchItem: entry.entryIndex) - - if insertionIndex < self.orderedEntries.lowerOrAtAnchor.count { - if self.orderedEntries.lowerOrAtAnchor[insertionIndex].entryIndex == entry.entryIndex { - assertionFailure("Inserting an existing index is not allowed") - self.orderedEntries.setLowerOrAtAnchorAtArrayIndex(insertionIndex, to: entry) - return true - } - } - - if insertionIndex == 0 { - return false - } - self.orderedEntries.insertLowerOrAtAnchorAtArrayIndex(insertionIndex, value: entry) - if self.orderedEntries.lowerOrAtAnchor.count > self.halfLimit { - self.orderedEntries.removeLowerOrAtAnchorAtArrayIndex(0) - } - return true - } else { - let insertionIndex = binaryInsertionIndex(orderedEntries.higherThanAnchor, extract: { $0.entryIndex }, searchItem: entry.entryIndex) - - if insertionIndex < self.orderedEntries.higherThanAnchor.count { - if self.orderedEntries.higherThanAnchor[insertionIndex].entryIndex == entry.entryIndex { - assertionFailure("Inserting an existing index is not allowed") - self.orderedEntries.setHigherThanAnchorAtArrayIndex(insertionIndex, to: entry) - return true - } - } - - if insertionIndex == self.orderedEntries.higherThanAnchor.count { - return false - } - self.orderedEntries.insertHigherThanAnchorAtArrayIndex(insertionIndex, value: entry) - if self.orderedEntries.higherThanAnchor.count > self.halfLimit { - self.orderedEntries.removeHigherThanAnchorAtArrayIndex(self.orderedEntries.higherThanAnchor.count - 1) - } - return true - } - } -} - -private struct MutableChatListEntryIndex: Hashable, Comparable { - var index: ChatListIndex - var isMessage: Bool - - var predecessor: MutableChatListEntryIndex { - return MutableChatListEntryIndex(index: self.index.predecessor, isMessage: self.isMessage) - } - - var successor: MutableChatListEntryIndex { - return MutableChatListEntryIndex(index: self.index.successor, isMessage: self.isMessage) - } - - static let absoluteLowerBound = MutableChatListEntryIndex(index: .absoluteLowerBound, isMessage: true) - static let absoluteUpperBound = MutableChatListEntryIndex(index: .absoluteUpperBound, isMessage: true) - - static func <(lhs: MutableChatListEntryIndex, rhs: MutableChatListEntryIndex) -> Bool { - if lhs.index != rhs.index { - return lhs.index < rhs.index - } else if lhs.isMessage != rhs.isMessage { - return lhs.isMessage - } else { - return false - } - } -} - -private extension MutableChatListEntry { - var messagePeerId: PeerId? { - switch self { - case let .IntermediateMessageEntry(intermediateMessageEntry): - return intermediateMessageEntry.0.messageIndex.id.peerId - case let .MessageEntry(messageEntry): - return messageEntry.0.messageIndex.id.peerId - case .HoleEntry: - return nil - } - } - - var entryIndex: MutableChatListEntryIndex { - switch self { - case let .IntermediateMessageEntry(intermediateMessageEntry): - return MutableChatListEntryIndex(index: intermediateMessageEntry.index, isMessage: true) - case let .MessageEntry(messageEntry): - return MutableChatListEntryIndex(index: messageEntry.index, isMessage: true) - case let .HoleEntry(hole): - return MutableChatListEntryIndex(index: ChatListIndex(pinningIndex: nil, messageIndex: hole.index), isMessage: false) - } - } -} - -private struct OrderedChatListViewEntries { - private let anchorIndex: ChatListIndex - - private(set) var lowerOrAtAnchor: [MutableChatListEntry] - private(set) var higherThanAnchor: [MutableChatListEntry] - - private(set) var reverseIndices: [PeerId: [MutableChatListEntryIndex]] = [:] - - fileprivate init(anchorIndex: ChatListIndex, lowerOrAtAnchor: [MutableChatListEntry], higherThanAnchor: [MutableChatListEntry]) { - self.anchorIndex = anchorIndex - assert(!lowerOrAtAnchor.contains(where: { $0.index > anchorIndex })) - assert(!higherThanAnchor.contains(where: { $0.index <= anchorIndex })) - - self.lowerOrAtAnchor = lowerOrAtAnchor - self.higherThanAnchor = higherThanAnchor - - for entry in lowerOrAtAnchor { - if let peerId = entry.messagePeerId { - if self.reverseIndices[peerId] == nil { - self.reverseIndices[peerId] = [entry.entryIndex] - } else { - self.reverseIndices[peerId]!.append(entry.entryIndex) - } - } - } - for entry in higherThanAnchor { - if let peerId = entry.messagePeerId { - if self.reverseIndices[peerId] == nil { - self.reverseIndices[peerId] = [entry.entryIndex] - } else { - self.reverseIndices[peerId]!.append(entry.entryIndex) - } - } - } - } - - mutating func setLowerOrAtAnchorAtArrayIndex(_ index: Int, to value: MutableChatListEntry) { - assert(value.index <= self.anchorIndex) - - let previousIndex = self.lowerOrAtAnchor[index].entryIndex - let updatedIndex = value.entryIndex - let previousPeerId = self.lowerOrAtAnchor[index].messagePeerId - let updatedPeerId = value.messagePeerId - - self.lowerOrAtAnchor[index] = value - - if previousPeerId != updatedPeerId { - if let previousPeerId = previousPeerId { - self.reverseIndices[previousPeerId]?.removeAll(where: { $0 == previousIndex }) - if let isEmpty = self.reverseIndices[previousPeerId]?.isEmpty, isEmpty { - self.reverseIndices.removeValue(forKey: previousPeerId) - } - } - if let updatedPeerId = updatedPeerId { - if self.reverseIndices[updatedPeerId] == nil { - self.reverseIndices[updatedPeerId] = [updatedIndex] - } else { - self.reverseIndices[updatedPeerId]!.append(updatedIndex) - } - } - } - } - - mutating func setHigherThanAnchorAtArrayIndex(_ index: Int, to value: MutableChatListEntry) { - assert(value.index > self.anchorIndex) - - let previousIndex = self.higherThanAnchor[index].entryIndex - let updatedIndex = value.entryIndex - let previousPeerId = self.higherThanAnchor[index].messagePeerId - let updatedPeerId = value.messagePeerId - - self.higherThanAnchor[index] = value - - if previousPeerId != updatedPeerId { - if let previousPeerId = previousPeerId { - self.reverseIndices[previousPeerId]?.removeAll(where: { $0 == previousIndex }) - if let isEmpty = self.reverseIndices[previousPeerId]?.isEmpty, isEmpty { - self.reverseIndices.removeValue(forKey: previousPeerId) - } - } - if let updatedPeerId = updatedPeerId { - if self.reverseIndices[updatedPeerId] == nil { - self.reverseIndices[updatedPeerId] = [updatedIndex] - } else { - self.reverseIndices[updatedPeerId]!.append(updatedIndex) - } - } - } - } - - mutating func insertLowerOrAtAnchorAtArrayIndex(_ index: Int, value: MutableChatListEntry) { - assert(value.index <= self.anchorIndex) - self.lowerOrAtAnchor.insert(value, at: index) - - if let peerId = value.messagePeerId { - if self.reverseIndices[peerId] == nil { - self.reverseIndices[peerId] = [value.entryIndex] - } else { - self.reverseIndices[peerId]!.append(value.entryIndex) - } - } - } - - mutating func insertHigherThanAnchorAtArrayIndex(_ index: Int, value: MutableChatListEntry) { - assert(value.index > self.anchorIndex) - self.higherThanAnchor.insert(value, at: index) - - if let peerId = value.messagePeerId { - if self.reverseIndices[peerId] == nil { - self.reverseIndices[peerId] = [value.entryIndex] - } else { - self.reverseIndices[peerId]!.append(value.entryIndex) - } - } - } - - mutating func removeLowerOrAtAnchorAtArrayIndex(_ index: Int) { - let previousIndex = self.lowerOrAtAnchor[index].entryIndex - if let peerId = self.lowerOrAtAnchor[index].messagePeerId { - self.reverseIndices[peerId]?.removeAll(where: { $0 == previousIndex }) - if let isEmpty = self.reverseIndices[peerId]?.isEmpty, isEmpty { - self.reverseIndices.removeValue(forKey: peerId) - } - } - - self.lowerOrAtAnchor.remove(at: index) - } - - mutating func removeHigherThanAnchorAtArrayIndex(_ index: Int) { - let previousIndex = self.higherThanAnchor[index].entryIndex - if let peerId = self.higherThanAnchor[index].messagePeerId { - self.reverseIndices[peerId]?.removeAll(where: { $0 == previousIndex }) - if let isEmpty = self.reverseIndices[peerId]?.isEmpty, isEmpty { - self.reverseIndices.removeValue(forKey: peerId) - } - } - - self.higherThanAnchor.remove(at: index) - } - - func find(index: MutableChatListEntryIndex) -> MutableChatListEntry? { - if let entryIndex = binarySearch(self.lowerOrAtAnchor, extract: { $0.entryIndex }, searchItem: index) { - return self.lowerOrAtAnchor[entryIndex] - } else if let entryIndex = binarySearch(self.higherThanAnchor, extract: { $0.entryIndex }, searchItem: index) { - return self.higherThanAnchor[entryIndex] - } else { - return nil - } - } - - func indicesForPeerId(_ peerId: PeerId) -> [MutableChatListEntryIndex]? { - return self.reverseIndices[peerId] - } - - var first: MutableChatListEntry? { - return self.lowerOrAtAnchor.first ?? self.higherThanAnchor.first - } - - mutating func mutableScan(_ f: (MutableChatListEntry) -> MutableChatListEntry?) -> Bool { - var anyUpdated = false - for i in 0 ..< self.lowerOrAtAnchor.count { - if let updated = f(self.lowerOrAtAnchor[i]) { - self.setLowerOrAtAnchorAtArrayIndex(i, to: updated) - anyUpdated = true - } - } - for i in 0 ..< self.higherThanAnchor.count { - if let updated = f(self.higherThanAnchor[i]) { - self.setHigherThanAnchorAtArrayIndex(i, to: updated) - anyUpdated = true - } - } - return anyUpdated - } - - mutating func update(index: MutableChatListEntryIndex, _ f: (MutableChatListEntry) -> MutableChatListEntry?) -> Bool { - if let entryIndex = binarySearch(self.lowerOrAtAnchor, extract: { $0.entryIndex }, searchItem: index) { - if let updated = f(self.lowerOrAtAnchor[entryIndex]) { - assert(updated.index == self.lowerOrAtAnchor[entryIndex].index) - self.setLowerOrAtAnchorAtArrayIndex(entryIndex, to: updated) - return true - } - } else if let entryIndex = binarySearch(self.higherThanAnchor, extract: { $0.entryIndex }, searchItem: index) { - if let updated = f(self.higherThanAnchor[entryIndex]) { - assert(updated.index == self.lowerOrAtAnchor[entryIndex].index) - self.setHigherThanAnchorAtArrayIndex(entryIndex, to: updated) - return true - } - } - return false - } - - mutating func remove(index: MutableChatListEntryIndex) -> Bool { - if let entryIndex = binarySearch(self.lowerOrAtAnchor, extract: { $0.entryIndex }, searchItem: index) { - self.removeLowerOrAtAnchorAtArrayIndex(entryIndex) - return true - } else if let entryIndex = binarySearch(self.higherThanAnchor, extract: { $0.entryIndex }, searchItem: index) { - self.removeHigherThanAnchorAtArrayIndex(entryIndex) - return true - } else { - return false - } - } -} - -final class ChatListViewSample { - let entries: [MutableChatListEntry] - let lower: MutableChatListEntry? - let upper: MutableChatListEntry? - let anchorIndex: ChatListIndex - let hole: (PeerGroupId, ChatListHole)? - - fileprivate init(entries: [MutableChatListEntry], lower: MutableChatListEntry?, upper: MutableChatListEntry?, anchorIndex: ChatListIndex, hole: (PeerGroupId, ChatListHole)?) { - self.entries = entries - self.lower = lower - self.upper = upper - self.anchorIndex = anchorIndex - self.hole = hole - } -} - -struct ChatListViewState { - private let anchorIndex: MutableChatListEntryIndex - private let summaryComponents: ChatListEntrySummaryComponents - private let halfLimit: Int - private var stateBySpace: [ChatListViewSpace: ChatListViewSpaceState] = [:] - - init(postbox: Postbox, spaces: [ChatListViewSpace], anchorIndex: ChatListIndex, summaryComponents: ChatListEntrySummaryComponents, halfLimit: Int) { - self.anchorIndex = MutableChatListEntryIndex(index: anchorIndex, isMessage: true) - self.summaryComponents = summaryComponents - self.halfLimit = halfLimit - - for space in spaces { - self.stateBySpace[space] = ChatListViewSpaceState(postbox: postbox, space: space, anchorIndex: self.anchorIndex, summaryComponents: summaryComponents, halfLimit: halfLimit) - } - } - - func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool { - var updated = false - for (_, state) in self.stateBySpace { - if state.replay(postbox: postbox, transaction: transaction) { - updated = true - } - } - return updated - } - - private func sampleIndices() -> (lowerOrAtAnchor: [(ChatListViewSpace, Int)], higherThanAnchor: [(ChatListViewSpace, Int)]) { - var previousAnchorIndices: [ChatListViewSpace: Int] = [:] - var nextAnchorIndices: [ChatListViewSpace: Int] = [:] - for (space, state) in self.stateBySpace { - previousAnchorIndices[space] = state.orderedEntries.lowerOrAtAnchor.count - 1 - nextAnchorIndices[space] = 0 - } - - var backwardsResult: [(ChatListViewSpace, Int)] = [] - var backwardsResultIndices: [ChatListIndex] = [] - var result: [(ChatListViewSpace, Int)] = [] - var resultIndices: [ChatListIndex] = [] - - while true { - var minSpace: ChatListViewSpace? - for (space, value) in previousAnchorIndices { - if value != -1 { - if let minSpaceValue = minSpace { - if self.stateBySpace[space]!.orderedEntries.lowerOrAtAnchor[value].entryIndex > self.stateBySpace[minSpaceValue]!.orderedEntries.lowerOrAtAnchor[previousAnchorIndices[minSpaceValue]!].entryIndex { - minSpace = space - } - } else { - minSpace = space - } - } - } - if let minSpace = minSpace { - backwardsResult.append((minSpace, previousAnchorIndices[minSpace]!)) - backwardsResultIndices.append(self.stateBySpace[minSpace]!.orderedEntries.lowerOrAtAnchor[previousAnchorIndices[minSpace]!].index) - previousAnchorIndices[minSpace]! -= 1 - if backwardsResult.count == self.halfLimit { - break - } - } - - if minSpace == nil { - break - } - } - - while true { - var maxSpace: ChatListViewSpace? - for (space, value) in nextAnchorIndices { - if value != self.stateBySpace[space]!.orderedEntries.higherThanAnchor.count { - if let maxSpaceValue = maxSpace { - if self.stateBySpace[space]!.orderedEntries.higherThanAnchor[value].entryIndex < self.stateBySpace[maxSpaceValue]!.orderedEntries.higherThanAnchor[nextAnchorIndices[maxSpaceValue]!].entryIndex { - maxSpace = space - } - } else { - maxSpace = space - } - } - } - if let maxSpace = maxSpace { - result.append((maxSpace, nextAnchorIndices[maxSpace]!)) - resultIndices.append(self.stateBySpace[maxSpace]!.orderedEntries.higherThanAnchor[nextAnchorIndices[maxSpace]!].index) - nextAnchorIndices[maxSpace]! += 1 - if result.count == self.halfLimit { - break - } - } - - if maxSpace == nil { - break - } - } - - backwardsResultIndices.reverse() - assert(backwardsResultIndices.sorted() == backwardsResultIndices) - assert(resultIndices.sorted() == resultIndices) - let combinedIndices = (backwardsResultIndices + resultIndices) - assert(combinedIndices.sorted() == combinedIndices) - - return (backwardsResult.reversed(), result) - } - - func sample(postbox: Postbox) -> ChatListViewSample { - let combinedSpacesAndIndicesByDirection = self.sampleIndices() - - var result: [(ChatListViewSpace, MutableChatListEntry)] = [] - - var sampledHoleIndices: [Int] = [] - var sampledAnchorBoundaryIndex: Int? - - var sampledHoleChatListIndices = Set() - - let directions = [combinedSpacesAndIndicesByDirection.lowerOrAtAnchor, combinedSpacesAndIndicesByDirection.higherThanAnchor] - for directionIndex in 0 ..< directions.count { - outer: for i in 0 ..< directions[directionIndex].count { - let (space, listIndex) = directions[directionIndex][i] - - let entry: MutableChatListEntry - if directionIndex == 0 { - entry = self.stateBySpace[space]!.orderedEntries.lowerOrAtAnchor[listIndex] - } else { - entry = self.stateBySpace[space]!.orderedEntries.higherThanAnchor[listIndex] - } - - if entry.entryIndex >= self.anchorIndex { - sampledAnchorBoundaryIndex = result.count - } - - switch entry { - case let .IntermediateMessageEntry(index, messageIndex): - var peers = SimpleDictionary() - var notificationsPeerId = index.messageIndex.id.peerId - if let peer = postbox.peerTable.get(index.messageIndex.id.peerId) { - peers[peer.id] = peer - if let notificationSettingsPeerId = peer.notificationSettingsPeerId { - notificationsPeerId = notificationSettingsPeerId - } - if let associatedPeerId = peer.associatedPeerId { - if let associatedPeer = postbox.peerTable.get(associatedPeerId) { - peers[associatedPeer.id] = associatedPeer - } - } - } - let renderedPeer = RenderedPeer(peerId: index.messageIndex.id.peerId, peers: peers) - - var tagSummaryCount: Int32? - var actionsSummaryCount: Int32? - - if let tagSummary = self.summaryComponents.tagSummary { - let key = MessageHistoryTagsSummaryKey(tag: tagSummary.tag, peerId: index.messageIndex.id.peerId, namespace: tagSummary.namespace) - if let summary = postbox.messageHistoryTagsSummaryTable.get(key) { - tagSummaryCount = summary.count - } - } - - if let actionsSummary = self.summaryComponents.actionsSummary { - let key = PendingMessageActionsSummaryKey(type: actionsSummary.type, peerId: index.messageIndex.id.peerId, namespace: actionsSummary.namespace) - actionsSummaryCount = postbox.pendingMessageActionsMetadataTable.getCount(.peerNamespaceAction(key.peerId, key.namespace, key.type)) - } - - let tagSummaryInfo = ChatListMessageTagSummaryInfo(tagSummaryCount: tagSummaryCount, actionsSummaryCount: actionsSummaryCount) - - let notificationSettings = postbox.peerNotificationSettingsTable.getEffective(notificationsPeerId) - - let isRemovedFromTotalUnreadCount: Bool - if let peer = renderedPeer.peers[notificationsPeerId] { - isRemovedFromTotalUnreadCount = resolvedIsRemovedFromTotalUnreadCount(globalSettings: postbox.getGlobalNotificationSettings(), peer: peer, peerSettings: notificationSettings) - } else { - isRemovedFromTotalUnreadCount = false - } - - let updatedEntry: MutableChatListEntry = .MessageEntry(index: index, message: messageIndex.flatMap(postbox.messageHistoryTable.getMessage).flatMap(postbox.renderIntermediateMessage), readState: postbox.readStateTable.getCombinedState(index.messageIndex.id.peerId), notificationSettings: notificationSettings, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: postbox.peerChatInterfaceStateTable.get(index.messageIndex.id.peerId)?.chatListEmbeddedState, renderedPeer: renderedPeer, presence: postbox.peerPresenceTable.get(index.messageIndex.id.peerId), tagSummaryInfo: tagSummaryInfo, hasFailedMessages: false, isContact: postbox.contactsTable.isContact(peerId: index.messageIndex.id.peerId)) - if directionIndex == 0 { - self.stateBySpace[space]!.orderedEntries.setLowerOrAtAnchorAtArrayIndex(listIndex, to: updatedEntry) - } else { - self.stateBySpace[space]!.orderedEntries.setHigherThanAnchorAtArrayIndex(listIndex, to: updatedEntry) - } - result.append((space, updatedEntry)) - case .MessageEntry: - result.append((space, entry)) - case .HoleEntry: - if !sampledHoleChatListIndices.contains(entry.index) { - sampledHoleChatListIndices.insert(entry.index) - sampledHoleIndices.append(result.count) - - result.append((space, entry)) - } - } - } - } - - let allIndices = result.map { $0.1.entryIndex } - let allIndicesSorted = allIndices.sorted() - for i in 0 ..< allIndicesSorted.count { - assert(allIndicesSorted[i] == allIndices[i]) - } - - if Set(allIndices).count != allIndices.count { - var seenIndices = Set() - var updatedResult: [(ChatListViewSpace, MutableChatListEntry)] = [] - for item in result { - if !seenIndices.contains(item.1.entryIndex) { - seenIndices.insert(item.1.entryIndex) - updatedResult.append(item) - } - } - result = updatedResult - - let allIndices = result.map { $0.1.entryIndex } - let allIndicesSorted = allIndices.sorted() - for i in 0 ..< allIndicesSorted.count { - assert(allIndicesSorted[i] == allIndices[i]) - } - assert(Set(allIndices).count == allIndices.count) - - assert(false) - } - - var sampledHoleIndex: Int? - if !sampledHoleIndices.isEmpty { - if let sampledAnchorBoundaryIndex = sampledAnchorBoundaryIndex { - var found = false - for i in 0 ..< sampledHoleIndices.count { - if i >= sampledAnchorBoundaryIndex { - sampledHoleIndex = sampledHoleIndices[i] - found = true - break - } - } - if !found { - sampledHoleIndex = sampledHoleIndices.first - } - } else if let index = sampledHoleIndices.first { - sampledHoleIndex = index - } - } - - var sampledHole: (ChatListViewSpace, ChatListHole)? - if let index = sampledHoleIndex { - let (space, entry) = result[index] - if case let .HoleEntry(hole) = entry { - sampledHole = (space, hole) - } else { - assertionFailure() - } - } - - var lower: MutableChatListEntry? - if combinedSpacesAndIndicesByDirection.lowerOrAtAnchor.count >= self.halfLimit { - lower = result[0].1 - result.removeFirst() - } - - var upper: MutableChatListEntry? - if combinedSpacesAndIndicesByDirection.higherThanAnchor.count >= self.halfLimit { - upper = result.last?.1 - result.removeLast() - } - - return ChatListViewSample(entries: result.map { $0.1 }, lower: lower, upper: upper, anchorIndex: self.anchorIndex.index, hole: sampledHole.flatMap { space, hole in - switch space { - case let .group(groupId, _, _): - return (groupId, hole) - case .peers: - return nil - } - }) - } -} diff --git a/submodules/Reachability/LegacyReachability/Package.swift b/submodules/Reachability/LegacyReachability/Package.swift new file mode 100644 index 0000000000..7c9c1d198d --- /dev/null +++ b/submodules/Reachability/LegacyReachability/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "LegacyReachability", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "LegacyReachability", + targets: ["LegacyReachability"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "LegacyReachability", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/Reachability/LegacyReachability/PublicHeaders/LegacyReachability/LegacyReachability.h b/submodules/Reachability/LegacyReachability/PublicHeaders/LegacyReachability/LegacyReachability.h index f03b45f207..37b95d1b63 100644 --- a/submodules/Reachability/LegacyReachability/PublicHeaders/LegacyReachability/LegacyReachability.h +++ b/submodules/Reachability/LegacyReachability/PublicHeaders/LegacyReachability/LegacyReachability.h @@ -1,10 +1,5 @@ -/* - Copyright (C) 2016 Apple Inc. All Rights Reserved. - See LICENSE.txt for this sample’s licensing information - - Abstract: - Basic demonstration of how to use the SystemConfiguration Reachablity APIs. - */ +#ifndef LegacyReachability_h +#define LegacyReachability_h #import #import @@ -17,10 +12,6 @@ typedef enum : NSInteger { ReachableViaWWAN } NetworkStatus; -#pragma mark IPv6 Support -//Reachability fully support IPv6. For full details, see ReadMe.md. - - extern NSString *kReachabilityChangedNotification; @@ -64,3 +55,4 @@ extern NSString *kReachabilityChangedNotification; @end +#endif diff --git a/submodules/Reachability/Package.swift b/submodules/Reachability/Package.swift new file mode 100644 index 0000000000..14badfab96 --- /dev/null +++ b/submodules/Reachability/Package.swift @@ -0,0 +1,30 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "Reachability", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "Reachability", + targets: ["Reachability"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "LegacyReachability", path: "LegacyReachability"), + .package(name: "SSignalKit", path: "../SSignalKit"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "Reachability", + dependencies: [.product(name: "LegacyReachability", package: "LegacyReachability", condition: nil), + .product(name: "SwiftSignalKit", package: "SSignalKit", condition: nil)], + path: "Sources"), + ] +) diff --git a/submodules/SSignalKit/Package.swift b/submodules/SSignalKit/Package.swift new file mode 100644 index 0000000000..4304b4a21c --- /dev/null +++ b/submodules/SSignalKit/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SSignalKit", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "SwiftSignalKit", + targets: ["SwiftSignalKit"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "SwiftSignalKit", + dependencies: [], + path: "SwiftSignalKit/Source"), + ] +) diff --git a/submodules/StringTransliteration/Package.swift b/submodules/StringTransliteration/Package.swift new file mode 100644 index 0000000000..6cda06df0e --- /dev/null +++ b/submodules/StringTransliteration/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "StringTransliteration", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "StringTransliteration", + targets: ["StringTransliteration"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "StringTransliteration", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/TelegramApi/Package.swift b/submodules/TelegramApi/Package.swift new file mode 100644 index 0000000000..3d82e48f12 --- /dev/null +++ b/submodules/TelegramApi/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "TelegramApi", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "TelegramApi", + targets: ["TelegramApi"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "TelegramApi", + dependencies: [], + path: "Sources"), + ] +) diff --git a/submodules/TelegramCore/Package.swift b/submodules/TelegramCore/Package.swift new file mode 100644 index 0000000000..027eff2198 --- /dev/null +++ b/submodules/TelegramCore/Package.swift @@ -0,0 +1,42 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "TelegramCore", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "TelegramCore", + targets: ["TelegramCore"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "Postbox", path: "../Postbox"), + .package(name: "SSignalKit", path: "../SSignalKit"), + .package(name: "MtProtoKit", path: "../MtProtoKit"), + .package(name: "TelegramApi", path: "../TelegramApi"), + .package(name: "CryptoUtils", path: "../CryptoUtils"), + .package(name: "NetworkLogging", path: "../NetworkLogging"), + .package(name: "Reachability", path: "../Reachability"), + .package(name: "EncryptionProvider", path: "../EncryptionProvider"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "TelegramCore", + dependencies: [.product(name: "Postbox", package: "Postbox", condition: nil), + .product(name: "SwiftSignalKit", package: "SSignalKit", condition: nil), + .product(name: "MtProtoKit", package: "MtProtoKit", condition: nil), + .product(name: "TelegramApi", package: "TelegramApi", condition: nil), + .product(name: "CryptoUtils", package: "CryptoUtils", condition: nil), + .product(name: "NetworkLogging", package: "NetworkLogging", condition: nil), + .product(name: "Reachability", package: "Reachability", condition: nil), + .product(name: "EncryptionProvider", package: "EncryptionProvider", condition: nil)], + path: "Sources"), + ] +) diff --git a/submodules/TelegramCore/Sources/MacOS/MacInternalUpdater.swift b/submodules/TelegramCore/Sources/MacOS/MacInternalUpdater.swift index 2863c172f1..ba9d1ff642 100644 --- a/submodules/TelegramCore/Sources/MacOS/MacInternalUpdater.swift +++ b/submodules/TelegramCore/Sources/MacOS/MacInternalUpdater.swift @@ -3,6 +3,7 @@ import TelegramApi import SwiftSignalKit import Postbox +import Foundation public enum InternalUpdaterError { case generic diff --git a/submodules/TelegramVoip/Package.swift b/submodules/TelegramVoip/Package.swift new file mode 100644 index 0000000000..79ba16a38c --- /dev/null +++ b/submodules/TelegramVoip/Package.swift @@ -0,0 +1,42 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "TelegramVoip", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "TelegramVoip", + targets: ["TelegramVoip"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + .package(name: "TgVoipWebrtc", path: "../../../tgcalls"), + .package(name: "SSignalKit", path: "../SSignalKit"), + .package(name: "TelegramCore", path: "../TelegramCore") + + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "TelegramVoip", + dependencies: [ + .productItem(name: "TgVoipWebrtc", package: "TgVoipWebrtc", condition: nil), + .productItem(name: "SwiftSignalKit", package: "SSignalKit", condition: nil), + .productItem(name: "TelegramCore", package: "TelegramCore", condition: nil), + ], + path: "Sources", + exclude: [ + "IpcGroupCallContext.swift", + "OngoingCallContext.swift", + ], + cxxSettings: [ + .define("WEBRTC_MAC", to: "1", nil), + ]), + ] +) diff --git a/submodules/TelegramVoip/Sources/macOS/OngoingCallVideoCapturer.swift b/submodules/TelegramVoip/Sources/macOS/OngoingCallVideoCapturer.swift new file mode 100644 index 0000000000..2bf532a9db --- /dev/null +++ b/submodules/TelegramVoip/Sources/macOS/OngoingCallVideoCapturer.swift @@ -0,0 +1,140 @@ +// +// OngoingCallVideoCapturer.swift +// TelegramVoip +// +// Created by Mikhail Filimonov on 07.01.2021. +// + +import Foundation +import Cocoa +import TgVoipWebrtc + + + +public enum OngoingCallVideoOrientation { + case rotation0 + case rotation90 + case rotation180 + case rotation270 +} + +public extension OngoingCallVideoOrientation { + init(_ orientation: OngoingCallVideoOrientationWebrtc) { + switch orientation { + case .orientation0: + self = .rotation0 + case .orientation90: + self = .rotation90 + case .orientation180: + self = .rotation180 + case .orientation270: + self = .rotation270 + @unknown default: + self = .rotation0 + } + } +} + + + +public final class OngoingCallContextPresentationCallVideoView { + public let view: NSView + public let setOnFirstFrameReceived: (((Float) -> Void)?) -> Void + public let getOrientation: () -> OngoingCallVideoOrientation + public let getAspect: () -> CGFloat + public let setOnOrientationUpdated: (((OngoingCallVideoOrientation, CGFloat) -> Void)?) -> Void + public let setVideoContentMode: (CALayerContentsGravity) -> Void + public let setOnIsMirroredUpdated: (((Bool) -> Void)?) -> Void + public let setIsPaused: (Bool) -> Void + public let renderToSize:(NSSize, Bool)->Void + public init( + view: NSView, + setOnFirstFrameReceived: @escaping (((Float) -> Void)?) -> Void, + getOrientation: @escaping () -> OngoingCallVideoOrientation, + getAspect: @escaping () -> CGFloat, + setOnOrientationUpdated: @escaping (((OngoingCallVideoOrientation, CGFloat) -> Void)?) -> Void, + setVideoContentMode: @escaping(CALayerContentsGravity) -> Void, + setOnIsMirroredUpdated: @escaping (((Bool) -> Void)?) -> Void, + setIsPaused: @escaping(Bool) -> Void, + renderToSize: @escaping(NSSize, Bool) -> Void + ) { + self.view = view + self.setOnFirstFrameReceived = setOnFirstFrameReceived + self.getOrientation = getOrientation + self.getAspect = getAspect + self.setOnOrientationUpdated = setOnOrientationUpdated + self.setVideoContentMode = setVideoContentMode + self.setOnIsMirroredUpdated = setOnIsMirroredUpdated + self.setIsPaused = setIsPaused + self.renderToSize = renderToSize + } +} + + + +public final class OngoingCallVideoCapturer { + public let impl: OngoingCallThreadLocalContextVideoCapturer + + public init(_ deviceId: String = "", keepLandscape: Bool = true) { + self.impl = OngoingCallThreadLocalContextVideoCapturer(deviceId: deviceId, keepLandscape: keepLandscape) + } + + public func makeOutgoingVideoView(completion: @escaping (OngoingCallContextPresentationCallVideoView?) -> Void) { + self.impl.makeOutgoingVideoView(false, completion: { view, _ in + if let view = view { + completion(OngoingCallContextPresentationCallVideoView( + view: view, setOnFirstFrameReceived: { [weak view] f in + view?.setOnFirstFrameReceived(f) + }, getOrientation: { + return .rotation90 + }, + getAspect: { [weak view] in + if let view = view { + return view.aspect + } else { + return 0.0 + } + }, + setOnOrientationUpdated: { [weak view] f in + + }, + setVideoContentMode: { [weak view] mode in + view?.setVideoContentMode(mode) + }, setOnIsMirroredUpdated: { [weak view] f in + view?.setOnIsMirroredUpdated { value in + f?(value) + } + }, setIsPaused: { [weak view] paused in + view?.setIsPaused(paused) + }, + renderToSize: { [weak view] size, animated in + view?.render(to: size, animated: animated) + } + )) + } else { + completion(nil) + } + }) + } + + public func setIsVideoEnabled(_ value: Bool) { + self.impl.setIsVideoEnabled(value) + } + + public func setOnFatalError(_ onError: @escaping()->Void) { + self.impl.setOnFatalError({ + DispatchQueue.main.async(execute: onError) + }) + } + public func setOnPause(_ onPause: @escaping(Bool)->Void) { + self.impl.setOnPause({ pause in + DispatchQueue.main.async(execute: { + onPause(pause) + }) + }) + } + + public func switchVideoInput(_ deviceId: String) { + self.impl.switchVideoInput(deviceId) + } +} diff --git a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm index cb2af58c81..b64909447a 100644 --- a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm +++ b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm @@ -1,8 +1,5 @@ -#ifndef WEBRTC_IOS -#import "OngoingCallThreadLocalContext.h" -#else #import -#endif + #import "Instance.h" #import "InstanceImpl.h" diff --git a/submodules/libphonenumber/Package.swift b/submodules/libphonenumber/Package.swift new file mode 100644 index 0000000000..ae6be2b0f3 --- /dev/null +++ b/submodules/libphonenumber/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "libphonenumber", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "libphonenumber", + targets: ["libphonenumber"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "libphonenumber", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders") + ]), + ] +) diff --git a/submodules/libphonenumber/PublicHeaders/libphonenumber/libphonenumber.h b/submodules/libphonenumber/PublicHeaders/libphonenumber/libphonenumber.h index da51c6395c..70f9af02f7 100644 --- a/submodules/libphonenumber/PublicHeaders/libphonenumber/libphonenumber.h +++ b/submodules/libphonenumber/PublicHeaders/libphonenumber/libphonenumber.h @@ -1,5 +1,8 @@ +#if TARGET_OS_IOS #import - +#else +#import +#endif //! Project version number for libphonenumber_iOS. FOUNDATION_EXPORT double libphonenumber_iOSVersionNumber; diff --git a/submodules/sqlcipher/Package.swift b/submodules/sqlcipher/Package.swift new file mode 100644 index 0000000000..d29108aaca --- /dev/null +++ b/submodules/sqlcipher/Package.swift @@ -0,0 +1,44 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "sqlcipher", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "sqlcipher", + targets: ["sqlcipher"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "sqlcipher", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders"), + .define("SQLITE_HAS_CODEC", to: "1"), + .define("SQLCIPHER_CRYPTO_CC", to: "1"), + .define("SQLITE_TEMP_STORE", to: "2"), + .define("SQLITE_ENABLE_FTS5", to: "1"), + .define("HAVE_USLEEP", to: "1"), + .define("SQLITE_DEFAULT_MEMSTATUS", to: "0"), + .define("SQLITE_OMIT_LOAD_EXTENSION", to: "1"), + .define("SQLITE_OMIT_DECLTYPE", to: "1"), + .define("SSQLITE_OMIT_PROGRESS_CALLBACK", to: "1"), + .define("SQLITE_OMIT_DEPRECATED", to: "1"), + .define("NDEBUG", to: "1"), + .define("SQLITE_MAX_MMAP_SIZE", to: "0"), + ]), + ] +) diff --git a/submodules/sqlcipher/Sources/sqlite3.c b/submodules/sqlcipher/Sources/sqlite3.c index bf01836b37..9de6ff1201 100644 --- a/submodules/sqlcipher/Sources/sqlite3.c +++ b/submodules/sqlcipher/Sources/sqlite3.c @@ -14312,11 +14312,11 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); ** Macros to compute minimum and maximum of two numbers. */ #ifndef MIN -# define MIN(A,B) ((A)<(B)?(A):(B)) -#endif +#define MIN(a, b) (((a)<(b))?(a):(b)) +#endif /* MIN */ #ifndef MAX -# define MAX(A,B) ((A)>(B)?(A):(B)) -#endif +#define MAX(a, b) (((a)>(b))?(a):(b)) +#endif /* MAX */ /* ** Swap two objects of type TYPE. @@ -171497,11 +171497,11 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi #ifndef MIN -# define MIN(x,y) ((x)<(y)?(x):(y)) -#endif +#define MIN(a, b) (((a)<(b))?(a):(b)) +#endif /* MIN */ #ifndef MAX -# define MAX(x,y) ((x)>(y)?(x):(y)) -#endif +#define MAX(a, b) (((a)>(b))?(a):(b)) +#endif /* MAX */ /* ** Maximum length of a varint encoded integer. The varint format is different @@ -193354,12 +193354,12 @@ struct RtreeMatchArg { RtreeDValue aParam[1]; /* Values for parameters to the SQL function */ }; -#ifndef MAX -# define MAX(x,y) ((x) < (y) ? (y) : (x)) -#endif #ifndef MIN -# define MIN(x,y) ((x) > (y) ? (y) : (x)) -#endif +#define MIN(a, b) (((a)<(b))?(a):(b)) +#endif /* MIN */ +#ifndef MAX +#define MAX(a, b) (((a)>(b))?(a):(b)) +#endif /* MAX */ /* What version of GCC is being used. 0 means GCC is not being used . ** Note that the GCC_VERSION macro will also be set correctly when using @@ -213443,8 +213443,12 @@ typedef sqlite3_uint64 u64; #define ALWAYS(x) 1 #define NEVER(x) 0 -#define MIN(x,y) (((x) < (y)) ? (x) : (y)) -#define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#ifndef MIN +#define MIN(a, b) (((a)<(b))?(a):(b)) +#endif /* MIN */ +#ifndef MAX +#define MAX(a, b) (((a)>(b))?(a):(b)) +#endif /* MAX */ /* ** Constants for the largest and smallest possible 64-bit signed integers. diff --git a/third-party/rnnoise/Package.swift b/third-party/rnnoise/Package.swift new file mode 100644 index 0000000000..8d4b24ff1b --- /dev/null +++ b/third-party/rnnoise/Package.swift @@ -0,0 +1,65 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +func replaceSymbols() -> [String] { + let symbols = [ "_celt_autocorr", + "celt_fir", + "celt_iir", + "_celt_lpc", + "celt_pitch_xcorr", + "compute_band_corr", + "compute_band_energy", + "compute_dense", + "compute_gru", + "compute_rnn", + "interp_band_gain", + "opus_fft_alloc", + "opus_fft_alloc_arch_c", + "opus_fft_alloc_twiddles", + "opus_fft_c", + "opus_fft_free", + "opus_fft_free_arch_c", + "opus_fft_impl", + "opus_ifft_c", + "pitch_downsample", + "pitch_filter", + "pitch_search", + "remove_doubling" + ] + + return symbols.map { + return "-D\($0)=rnnoise_\($0)" + } +} + +let package = Package( + name: "rnoise", + platforms: [.macOS(.v10_11)], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .library( + name: "rnoise", + targets: ["rnoise"]), + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + // .package(url: /* package url */, from: "1.0.0"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "rnoise", + dependencies: [], + path: ".", + exclude: ["BUILD", + "Sources/compile.sh"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders"), + .unsafeFlags(replaceSymbols()) + ]), + ] +)