mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
no message
This commit is contained in:
parent
4a58158d99
commit
50c0158683
@ -151,7 +151,6 @@
|
||||
D033FEB61E61F3F900644997 /* BlockedPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEB51E61F3F900644997 /* BlockedPeers.swift */; };
|
||||
D033FEB71E61F3F900644997 /* BlockedPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033FEB51E61F3F900644997 /* BlockedPeers.swift */; };
|
||||
D03B0CB91D62233400955575 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CB81D62233400955575 /* Either.swift */; };
|
||||
D03B0CBB1D62233C00955575 /* MergeLists.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBA1D62233C00955575 /* MergeLists.swift */; };
|
||||
D03B0CBD1D62234300955575 /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBC1D62234300955575 /* Regex.swift */; };
|
||||
D03B0CBF1D62234A00955575 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBE1D62234A00955575 /* Log.swift */; };
|
||||
D03B0CC11D62235000955575 /* StringFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CC01D62235000955575 /* StringFormat.swift */; };
|
||||
@ -454,7 +453,6 @@
|
||||
D0B8440D1DAB91CD005F29E1 /* ImageRepresentationsUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DF0C901D81A857008AEB01 /* ImageRepresentationsUtils.swift */; };
|
||||
D0B8440E1DAB91CD005F29E1 /* MessageUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0DF0C921D81AD09008AEB01 /* MessageUtils.swift */; };
|
||||
D0B8440F1DAB91CD005F29E1 /* Either.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CB81D62233400955575 /* Either.swift */; };
|
||||
D0B844101DAB91CD005F29E1 /* MergeLists.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBA1D62233C00955575 /* MergeLists.swift */; };
|
||||
D0B844111DAB91CD005F29E1 /* Regex.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBC1D62234300955575 /* Regex.swift */; };
|
||||
D0B844121DAB91CD005F29E1 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CBE1D62234A00955575 /* Log.swift */; };
|
||||
D0B844131DAB91CD005F29E1 /* StringFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CC01D62235000955575 /* StringFormat.swift */; };
|
||||
@ -556,6 +554,8 @@
|
||||
D0E35A151DE4C6A200BC6096 /* OutgoingMessageWithChatContextResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E35A0F1DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift */; };
|
||||
D0E6521F1E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */; };
|
||||
D0E652201E3A364A004EEA91 /* UpdateAccountPeerName.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */; };
|
||||
D0E817492010E7E300B82BBB /* ChannelAdminEventLogContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E817482010E7E300B82BBB /* ChannelAdminEventLogContext.swift */; };
|
||||
D0E8174A2010E7E300B82BBB /* ChannelAdminEventLogContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E817482010E7E300B82BBB /* ChannelAdminEventLogContext.swift */; };
|
||||
D0F02CE51E9926C40065DEE2 /* ManagedConfigurationUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F02CE41E9926C40065DEE2 /* ManagedConfigurationUpdates.swift */; };
|
||||
D0F02CE61E9926C50065DEE2 /* ManagedConfigurationUpdates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F02CE41E9926C40065DEE2 /* ManagedConfigurationUpdates.swift */; };
|
||||
D0F3A89F1E82C65400B4C64C /* SynchronizeChatInputStateOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F3A89E1E82C65400B4C64C /* SynchronizeChatInputStateOperation.swift */; };
|
||||
@ -694,7 +694,6 @@
|
||||
D033FEB21E61F3C000644997 /* ReportPeer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReportPeer.swift; sourceTree = "<group>"; };
|
||||
D033FEB51E61F3F900644997 /* BlockedPeers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BlockedPeers.swift; sourceTree = "<group>"; };
|
||||
D03B0CB81D62233400955575 /* Either.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Either.swift; sourceTree = "<group>"; };
|
||||
D03B0CBA1D62233C00955575 /* MergeLists.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MergeLists.swift; sourceTree = "<group>"; };
|
||||
D03B0CBC1D62234300955575 /* Regex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regex.swift; sourceTree = "<group>"; };
|
||||
D03B0CBE1D62234A00955575 /* Log.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Log.swift; sourceTree = "<group>"; };
|
||||
D03B0CC01D62235000955575 /* StringFormat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringFormat.swift; sourceTree = "<group>"; };
|
||||
@ -930,6 +929,7 @@
|
||||
D0E35A0F1DE49E1C00BC6096 /* OutgoingMessageWithChatContextResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingMessageWithChatContextResult.swift; sourceTree = "<group>"; };
|
||||
D0E35A111DE4A25E00BC6096 /* OutgoingChatContextResultMessageAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OutgoingChatContextResultMessageAttribute.swift; sourceTree = "<group>"; };
|
||||
D0E6521E1E3A364A004EEA91 /* UpdateAccountPeerName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateAccountPeerName.swift; sourceTree = "<group>"; };
|
||||
D0E817482010E7E300B82BBB /* ChannelAdminEventLogContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelAdminEventLogContext.swift; sourceTree = "<group>"; };
|
||||
D0F02CE41E9926C40065DEE2 /* ManagedConfigurationUpdates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedConfigurationUpdates.swift; sourceTree = "<group>"; };
|
||||
D0F3A89E1E82C65400B4C64C /* SynchronizeChatInputStateOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizeChatInputStateOperation.swift; sourceTree = "<group>"; };
|
||||
D0F3A8A11E82C65E00B4C64C /* ManagedSynchronizeChatInputStateOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeChatInputStateOperations.swift; sourceTree = "<group>"; };
|
||||
@ -1090,7 +1090,6 @@
|
||||
D0DF0C901D81A857008AEB01 /* ImageRepresentationsUtils.swift */,
|
||||
D0DF0C921D81AD09008AEB01 /* MessageUtils.swift */,
|
||||
D03B0CB81D62233400955575 /* Either.swift */,
|
||||
D03B0CBA1D62233C00955575 /* MergeLists.swift */,
|
||||
D03B0CBC1D62234300955575 /* Regex.swift */,
|
||||
D03B0CBE1D62234A00955575 /* Log.swift */,
|
||||
D03B0CC01D62235000955575 /* StringFormat.swift */,
|
||||
@ -1575,6 +1574,7 @@
|
||||
C23BC3861E9BE3CA00D79F92 /* ImportContact.swift */,
|
||||
C205FEA71EB3B75900455808 /* ExportMessageLink.swift */,
|
||||
C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */,
|
||||
D0E817482010E7E300B82BBB /* ChannelAdminEventLogContext.swift */,
|
||||
D0A472B51F4CBE8B00E0EEDA /* LoadedPeer.swift */,
|
||||
D0DA1D311F7043D50034E892 /* ManagedPendingPeerNotificationSettings.swift */,
|
||||
D02395D51F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift */,
|
||||
@ -1950,6 +1950,7 @@
|
||||
D0561DE31E5737FC00E6B9E9 /* UpdatePeerInfo.swift in Sources */,
|
||||
D0DF0C8A1D819C7E008AEB01 /* JoinChannel.swift in Sources */,
|
||||
D04CAA5A1E83310D0047E51F /* MD5.swift in Sources */,
|
||||
D0E817492010E7E300B82BBB /* ChannelAdminEventLogContext.swift in Sources */,
|
||||
D05452071E7B5093006EEF19 /* LoadedStickerPack.swift in Sources */,
|
||||
D01C7F041EFC1C49008305F1 /* DeviceContact.swift in Sources */,
|
||||
D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */,
|
||||
@ -2040,7 +2041,6 @@
|
||||
D0528E651E65C82400E2FEF5 /* UpdateContactName.swift in Sources */,
|
||||
D03121021DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift in Sources */,
|
||||
D0C48F391E8138DF0075317D /* ArchivedStickerPacksInfo.swift in Sources */,
|
||||
D03B0CBB1D62233C00955575 /* MergeLists.swift in Sources */,
|
||||
C239BE971E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift in Sources */,
|
||||
D03B0CC11D62235000955575 /* StringFormat.swift in Sources */,
|
||||
D0B85AC51F6B2B9400B8B5CE /* RecentlyUsedHashtags.swift in Sources */,
|
||||
@ -2289,6 +2289,7 @@
|
||||
D050F2621E4A5AE700988324 /* GlobalNotificationSettings.swift in Sources */,
|
||||
D0DFD5E01FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */,
|
||||
D0B418991D7E0580004562A4 /* TelegramMediaMap.swift in Sources */,
|
||||
D0E8174A2010E7E300B82BBB /* ChannelAdminEventLogContext.swift in Sources */,
|
||||
D0561DEB1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */,
|
||||
D0AD02E41FFFA14800C1DCFF /* PeerLiveLocationsContext.swift in Sources */,
|
||||
D0613FCB1E60440600202CDB /* InvitationLinks.swift in Sources */,
|
||||
@ -2324,7 +2325,6 @@
|
||||
D033FEB41E61F3C000644997 /* ReportPeer.swift in Sources */,
|
||||
D0FA8BAE1E1FD6E2001E855B /* MemoryBufferExtensions.swift in Sources */,
|
||||
D0FA8BB41E201B02001E855B /* ProcessSecretChatIncomingEncryptedOperations.swift in Sources */,
|
||||
D0B844101DAB91CD005F29E1 /* MergeLists.swift in Sources */,
|
||||
D0F3A8A31E82C65E00B4C64C /* ManagedSynchronizeChatInputStateOperations.swift in Sources */,
|
||||
D0448CA61E29215A005A61A7 /* MediaResourceApiUtils.swift in Sources */,
|
||||
D001F3F11E128A1C007A8C60 /* SynchronizePeerReadState.swift in Sources */,
|
||||
|
||||
124
TelegramCore/ChannelAdminEventLogContext.swift
Normal file
124
TelegramCore/ChannelAdminEventLogContext.swift
Normal file
@ -0,0 +1,124 @@
|
||||
#if os(macOS)
|
||||
import PostboxMac
|
||||
import SwiftSignalKitMac
|
||||
#else
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
public struct ChannelAdminEventLogEntry: Comparable {
|
||||
public let event: AdminLogEvent
|
||||
public let peers: [PeerId: Peer]
|
||||
|
||||
public static func ==(lhs: ChannelAdminEventLogEntry, rhs: ChannelAdminEventLogEntry) -> Bool {
|
||||
return lhs.event == rhs.event
|
||||
}
|
||||
|
||||
public static func <(lhs: ChannelAdminEventLogEntry, rhs: ChannelAdminEventLogEntry) -> Bool {
|
||||
return lhs.event < rhs.event
|
||||
}
|
||||
}
|
||||
|
||||
public enum ChannelAdminEventLogUpdateType {
|
||||
case initial
|
||||
case generic
|
||||
case load
|
||||
}
|
||||
|
||||
public final class ChannelAdminEventLogContext {
|
||||
private let queue: Queue = Queue.mainQueue()
|
||||
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let peerId: PeerId
|
||||
|
||||
private var entries: [ChannelAdminEventLogEntry] = []
|
||||
private var hasEarlier: Bool = true
|
||||
private var loadingMoreEarlier: Bool = false
|
||||
|
||||
private var subscribers = Bag<([ChannelAdminEventLogEntry], Bool, ChannelAdminEventLogUpdateType) -> Void>()
|
||||
|
||||
private let loadMoreDisposable = MetaDisposable()
|
||||
|
||||
public init(postbox: Postbox, network: Network, peerId: PeerId) {
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.peerId = peerId
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.loadMoreDisposable.dispose()
|
||||
}
|
||||
|
||||
public func get() -> Signal<([ChannelAdminEventLogEntry], Bool, ChannelAdminEventLogUpdateType), NoError> {
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
if let strongSelf = self {
|
||||
subscriber.putNext((strongSelf.entries, strongSelf.hasEarlier, .initial))
|
||||
|
||||
let index = strongSelf.subscribers.add({ entries, hasEarlier, type in
|
||||
subscriber.putNext((strongSelf.entries, strongSelf.hasEarlier, type))
|
||||
})
|
||||
|
||||
return ActionDisposable {
|
||||
queue.async {
|
||||
if let strongSelf = self {
|
||||
strongSelf.subscribers.remove(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return EmptyDisposable
|
||||
}
|
||||
} |> runOn(queue)
|
||||
}
|
||||
|
||||
public func loadMoreEntries() {
|
||||
assert(self.queue.isCurrent())
|
||||
|
||||
if self.loadingMoreEarlier {
|
||||
return
|
||||
}
|
||||
|
||||
let maxId: AdminLogEventId
|
||||
if let last = self.entries.last {
|
||||
maxId = last.event.id
|
||||
} else {
|
||||
maxId = AdminLogEventId.max
|
||||
}
|
||||
|
||||
self.loadingMoreEarlier = true
|
||||
self.loadMoreDisposable.set((channelAdminLogEvents(postbox: self.postbox, network: self.network, peerId: self.peerId, maxId: maxId, minId: AdminLogEventId.min, limit: 10, query: nil, filter: nil, admins: nil)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||
if let strongSelf = self {
|
||||
var events = result.events.sorted()
|
||||
if let first = strongSelf.entries.first {
|
||||
var clipIndex = events.count
|
||||
for i in (0 ..< events.count).reversed() {
|
||||
if events[i] >= first.event {
|
||||
clipIndex = i - 1
|
||||
}
|
||||
}
|
||||
if clipIndex < events.count {
|
||||
events.removeSubrange(clipIndex ..< events.count)
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.hasEarlier = !events.isEmpty
|
||||
|
||||
var entries: [ChannelAdminEventLogEntry] = events.map { event in
|
||||
return ChannelAdminEventLogEntry(event: event, peers: result.peers)
|
||||
|
||||
}
|
||||
entries.append(contentsOf: strongSelf.entries)
|
||||
strongSelf.entries = entries
|
||||
|
||||
strongSelf.loadingMoreEarlier = false
|
||||
|
||||
for subscriber in strongSelf.subscribers.copyItems() {
|
||||
subscriber(strongSelf.entries, strongSelf.hasEarlier, .load)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
@ -8,11 +8,23 @@
|
||||
|
||||
public typealias AdminLogEventId = Int64
|
||||
|
||||
public struct AdminLogEvent {
|
||||
public struct AdminLogEvent: Comparable {
|
||||
public let id: AdminLogEventId
|
||||
public let peerId: PeerId
|
||||
public let date: Int32
|
||||
public let action: AdminLogEventAction
|
||||
|
||||
public static func ==(lhs: AdminLogEvent, rhs: AdminLogEvent) -> Bool {
|
||||
return lhs.id == rhs.id
|
||||
}
|
||||
|
||||
public static func <(lhs: AdminLogEvent, rhs: AdminLogEvent) -> Bool {
|
||||
if lhs.date != rhs.date {
|
||||
return lhs.date < rhs.date
|
||||
} else {
|
||||
return lhs.id < rhs.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct AdminLogEventsResult {
|
||||
@ -86,112 +98,112 @@ private func boolFromApiValue(_ value: Api.Bool) -> Bool {
|
||||
}
|
||||
}
|
||||
|
||||
public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
|
||||
|
||||
return account.postbox.modify { modifier -> (Peer?, [Peer]?) in
|
||||
return (modifier.getPeer(peerId), admins?.flatMap {modifier.getPeer($0)})
|
||||
} |> mapError {return .generic} |> mapToSignal { (peer, admins) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> in
|
||||
public func channelAdminLogEvents(postbox: Postbox, network: Network, peerId: PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> {
|
||||
return postbox.modify { modifier -> (Peer?, [Peer]?) in
|
||||
return (modifier.getPeer(peerId), admins?.flatMap { modifier.getPeer($0) })
|
||||
}
|
||||
|> mapError { return .generic }
|
||||
|> mapToSignal { (peer, admins) -> Signal<AdminLogEventsResult, ChannelAdminLogEventError> in
|
||||
if let peer = peer, let inputChannel = apiInputChannel(peer) {
|
||||
let inputAdmins = admins?.flatMap {apiInputUser($0)}
|
||||
|
||||
if let peer = peer, let inputChannel = apiInputChannel(peer) {
|
||||
let inputAdmins = admins?.flatMap {apiInputUser($0)}
|
||||
|
||||
var flags:Int32 = 0
|
||||
var eventsFilter:Api.ChannelAdminLogEventsFilter? = nil
|
||||
if let filter = filter {
|
||||
flags += Int32(1 << 0)
|
||||
eventsFilter = Api.ChannelAdminLogEventsFilter.channelAdminLogEventsFilter(flags: Int32(filter.rawValue))
|
||||
}
|
||||
if let _ = inputAdmins {
|
||||
flags += Int32(1 << 1)
|
||||
}
|
||||
return account.network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query ?? "", eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit)) |> map { result in
|
||||
|
||||
switch result {
|
||||
case let .adminLogResults(apiEvents, apiChats, apiUsers):
|
||||
let peers = (apiChats.flatMap {parseTelegramGroupOrChannel(chat: $0)} + apiUsers.flatMap { TelegramUser(user: $0) } + Array(arrayLiteral: peer)).reduce([:], { current, peer -> [PeerId : Peer] in
|
||||
var current = current
|
||||
current[peer.id] = peer
|
||||
return current
|
||||
})
|
||||
|
||||
var events: [AdminLogEvent] = []
|
||||
|
||||
for event in apiEvents {
|
||||
switch event {
|
||||
case let .channelAdminLogEvent(id, date, userId, apiAction):
|
||||
var action: AdminLogEventAction?
|
||||
switch apiAction {
|
||||
case let .channelAdminLogEventActionChangeTitle(prev, new):
|
||||
action = .changeTitle(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeAbout(prev, new):
|
||||
action = .changeAbout(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeUsername(prev, new):
|
||||
action = .changeUsername(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangePhoto(prev, new):
|
||||
action = .changePhoto(prev: imageRepresentationsForApiChatPhoto(prev), new: imageRepresentationsForApiChatPhoto(new))
|
||||
case let .channelAdminLogEventActionToggleInvites(new):
|
||||
action = .toggleInvites(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionToggleSignatures(new):
|
||||
action = .toggleSignatures(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionUpdatePinned(new):
|
||||
switch new {
|
||||
case .messageEmpty:
|
||||
action = .updatePinned(nil)
|
||||
default:
|
||||
if let message = StoreMessage(apiMessage: new), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .updatePinned(rendered)
|
||||
}
|
||||
}
|
||||
|
||||
case let .channelAdminLogEventActionEditMessage(prev, new):
|
||||
if let prev = StoreMessage(apiMessage: prev), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new), let newRendered = locallyRenderedMessage(message: new, peers: peers) {
|
||||
action = .editMessage(prev: prevRendered, new: newRendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionDeleteMessage(message):
|
||||
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .deleteMessage(rendered)
|
||||
}
|
||||
case .channelAdminLogEventActionParticipantJoin:
|
||||
action = .participantJoin
|
||||
case .channelAdminLogEventActionParticipantLeave:
|
||||
action = .participantLeave
|
||||
case let .channelAdminLogEventActionParticipantInvite(participant):
|
||||
let participant = ChannelParticipant(apiParticipant: participant)
|
||||
|
||||
if let peer = peers[participant.peerId] {
|
||||
action = .participantInvite(RenderedChannelParticipant(participant: participant, peer: peer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleBan(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleBan(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleAdmin(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleAdmin(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeStickerSet(prevStickerset, newStickerset):
|
||||
action = .changeStickerPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset))
|
||||
case let .channelAdminLogEventActionTogglePreHistoryHidden(value):
|
||||
action = .togglePreHistoryHidden(value == .boolTrue)
|
||||
}
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
if let action = action {
|
||||
events.append(AdminLogEvent(id: id, peerId: peerId, date: date, action: action))
|
||||
}
|
||||
}
|
||||
}
|
||||
return AdminLogEventsResult(peerId: peerId, peers: peers, events: events)
|
||||
}
|
||||
|
||||
} |> mapError {_ in return .generic}
|
||||
var flags: Int32 = 0
|
||||
var eventsFilter: Api.ChannelAdminLogEventsFilter? = nil
|
||||
if let filter = filter {
|
||||
flags += Int32(1 << 0)
|
||||
eventsFilter = Api.ChannelAdminLogEventsFilter.channelAdminLogEventsFilter(flags: Int32(filter.rawValue))
|
||||
}
|
||||
|
||||
return .complete()
|
||||
if let _ = inputAdmins {
|
||||
flags += Int32(1 << 1)
|
||||
}
|
||||
return network.request(Api.functions.channels.getAdminLog(flags: flags, channel: inputChannel, q: query ?? "", eventsFilter: eventsFilter, admins: inputAdmins, maxId: maxId, minId: minId, limit: limit)) |> map { result in
|
||||
|
||||
switch result {
|
||||
case let .adminLogResults(apiEvents, apiChats, apiUsers):
|
||||
let peers = (apiChats.flatMap {parseTelegramGroupOrChannel(chat: $0)} + apiUsers.flatMap { TelegramUser(user: $0) } + Array(arrayLiteral: peer)).reduce([:], { current, peer -> [PeerId : Peer] in
|
||||
var current = current
|
||||
current[peer.id] = peer
|
||||
return current
|
||||
})
|
||||
|
||||
var events: [AdminLogEvent] = []
|
||||
|
||||
for event in apiEvents {
|
||||
switch event {
|
||||
case let .channelAdminLogEvent(id, date, userId, apiAction):
|
||||
var action: AdminLogEventAction?
|
||||
switch apiAction {
|
||||
case let .channelAdminLogEventActionChangeTitle(prev, new):
|
||||
action = .changeTitle(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeAbout(prev, new):
|
||||
action = .changeAbout(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangeUsername(prev, new):
|
||||
action = .changeUsername(prev: prev, new: new)
|
||||
case let .channelAdminLogEventActionChangePhoto(prev, new):
|
||||
action = .changePhoto(prev: imageRepresentationsForApiChatPhoto(prev), new: imageRepresentationsForApiChatPhoto(new))
|
||||
case let .channelAdminLogEventActionToggleInvites(new):
|
||||
action = .toggleInvites(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionToggleSignatures(new):
|
||||
action = .toggleSignatures(boolFromApiValue(new))
|
||||
case let .channelAdminLogEventActionUpdatePinned(new):
|
||||
switch new {
|
||||
case .messageEmpty:
|
||||
action = .updatePinned(nil)
|
||||
default:
|
||||
if let message = StoreMessage(apiMessage: new), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .updatePinned(rendered)
|
||||
}
|
||||
}
|
||||
|
||||
case let .channelAdminLogEventActionEditMessage(prev, new):
|
||||
if let prev = StoreMessage(apiMessage: prev), let prevRendered = locallyRenderedMessage(message: prev, peers: peers), let new = StoreMessage(apiMessage: new), let newRendered = locallyRenderedMessage(message: new, peers: peers) {
|
||||
action = .editMessage(prev: prevRendered, new: newRendered)
|
||||
}
|
||||
case let .channelAdminLogEventActionDeleteMessage(message):
|
||||
if let message = StoreMessage(apiMessage: message), let rendered = locallyRenderedMessage(message: message, peers: peers) {
|
||||
action = .deleteMessage(rendered)
|
||||
}
|
||||
case .channelAdminLogEventActionParticipantJoin:
|
||||
action = .participantJoin
|
||||
case .channelAdminLogEventActionParticipantLeave:
|
||||
action = .participantLeave
|
||||
case let .channelAdminLogEventActionParticipantInvite(participant):
|
||||
let participant = ChannelParticipant(apiParticipant: participant)
|
||||
|
||||
if let peer = peers[participant.peerId] {
|
||||
action = .participantInvite(RenderedChannelParticipant(participant: participant, peer: peer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleBan(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleBan(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionParticipantToggleAdmin(prev, new):
|
||||
let prevParticipant = ChannelParticipant(apiParticipant: prev)
|
||||
let newParticipant = ChannelParticipant(apiParticipant: new)
|
||||
|
||||
if let prevPeer = peers[prevParticipant.peerId], let newPeer = peers[newParticipant.peerId] {
|
||||
action = .participantToggleAdmin(prev: RenderedChannelParticipant(participant: prevParticipant, peer: prevPeer), new: RenderedChannelParticipant(participant: newParticipant, peer: newPeer))
|
||||
}
|
||||
case let .channelAdminLogEventActionChangeStickerSet(prevStickerset, newStickerset):
|
||||
action = .changeStickerPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset))
|
||||
case let .channelAdminLogEventActionTogglePreHistoryHidden(value):
|
||||
action = .togglePreHistoryHidden(value == .boolTrue)
|
||||
}
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||
if let action = action {
|
||||
events.append(AdminLogEvent(id: id, peerId: peerId, date: date, action: action))
|
||||
}
|
||||
}
|
||||
}
|
||||
return AdminLogEventsResult(peerId: peerId, peers: peers, events: events)
|
||||
}
|
||||
|
||||
} |> mapError {_ in return .generic}
|
||||
}
|
||||
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,413 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
public protocol Identifiable {
|
||||
associatedtype T: Hashable
|
||||
var stableId: T { get }
|
||||
}
|
||||
|
||||
public func mergeListsStable<T>(leftList: [T], rightList: [T]) -> ([Int], [(Int, T, Int?)]) where T: Comparable, T: Identifiable {
|
||||
var removeIndices: [Int] = []
|
||||
var insertItems: [(Int, T, Int?)] = []
|
||||
|
||||
var currentList = leftList
|
||||
|
||||
var i = 0
|
||||
var j = 0
|
||||
while true {
|
||||
let left: T? = i < currentList.count ? currentList[i] : nil
|
||||
let right: T? = j < rightList.count ? rightList[j] : nil
|
||||
|
||||
if let left = left, let right = right {
|
||||
if left == right {
|
||||
i += 1
|
||||
j += 1
|
||||
} else if left < right {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else {
|
||||
j += 1
|
||||
}
|
||||
} else if let _ = left {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else if let _ = right {
|
||||
j += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for index in removeIndices.reversed() {
|
||||
currentList.remove(at: index)
|
||||
}
|
||||
|
||||
var previousIndices: [T.T: Int] = [:]
|
||||
i = 0
|
||||
for left in leftList {
|
||||
previousIndices[left.stableId] = i
|
||||
i += 1
|
||||
}
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
while true {
|
||||
let left: T? = i < currentList.count ? currentList[i] : nil
|
||||
let right: T? = j < rightList.count ? rightList[j] : nil
|
||||
|
||||
if let left = left, let right = right {
|
||||
if left == right {
|
||||
i += 1
|
||||
j += 1
|
||||
} else if left > right {
|
||||
let previousIndex = previousIndices[right.stableId]
|
||||
insertItems.append((i, right, previousIndex))
|
||||
currentList.insert(right, at: i)
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
i += 1
|
||||
}
|
||||
} else if let _ = left {
|
||||
i += 1
|
||||
} else if let right = right {
|
||||
let previousIndex = previousIndices[right.stableId]
|
||||
insertItems.append((i, right, previousIndex))
|
||||
currentList.insert(right, at: i)
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert(currentList == rightList, "currentList == rightList")
|
||||
|
||||
return (removeIndices, insertItems)
|
||||
}
|
||||
|
||||
public func mergeListsStableWithUpdates<T>(leftList: [T], rightList: [T]) -> ([Int], [(Int, T, Int?)], [(Int, T, Int)]) where T: Comparable, T: Identifiable {
|
||||
var removeIndices: [Int] = []
|
||||
var insertItems: [(Int, T, Int?)] = []
|
||||
var updatedIndices: [(Int, T, Int)] = []
|
||||
|
||||
#if (arch(i386) || arch(x86_64)) && os(iOS)
|
||||
var existingStableIds: [T.T: T] = [:]
|
||||
for item in leftList {
|
||||
if let _ = existingStableIds[item.stableId] {
|
||||
assertionFailure()
|
||||
} else {
|
||||
existingStableIds[item.stableId] = item
|
||||
}
|
||||
}
|
||||
existingStableIds.removeAll()
|
||||
for item in rightList {
|
||||
if let other = existingStableIds[item.stableId] {
|
||||
print("\(other) has the same stableId as \(item): \(item.stableId)")
|
||||
assertionFailure()
|
||||
} else {
|
||||
existingStableIds[item.stableId] = item
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var currentList = leftList
|
||||
|
||||
var i = 0
|
||||
var previousIndices: [T.T: Int] = [:]
|
||||
for left in leftList {
|
||||
previousIndices[left.stableId] = i
|
||||
i += 1
|
||||
}
|
||||
|
||||
i = 0
|
||||
var j = 0
|
||||
while true {
|
||||
let left: T? = i < currentList.count ? currentList[i] : nil
|
||||
let right: T? = j < rightList.count ? rightList[j] : nil
|
||||
|
||||
if let left = left, let right = right {
|
||||
if left.stableId == right.stableId && left != right {
|
||||
updatedIndices.append((i, right, previousIndices[left.stableId]!))
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
if left == right {
|
||||
i += 1
|
||||
j += 1
|
||||
} else if left < right {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else if !(left > right) {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else {
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
} else if let _ = left {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else if let _ = right {
|
||||
j += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//print("remove:\n\(removeIndices)")
|
||||
|
||||
for index in removeIndices.reversed() {
|
||||
currentList.remove(at: index)
|
||||
for i in 0 ..< updatedIndices.count {
|
||||
if updatedIndices[i].0 >= index {
|
||||
updatedIndices[i].0 -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*print("\n current after removes:\n")
|
||||
m = 0
|
||||
for right in currentList {
|
||||
print("\(m): \(right.stableId)")
|
||||
m += 1
|
||||
}
|
||||
|
||||
print("update:\n\(updatedIndices.map({ "\($0.0), \($0.1.stableId) (was \($0.2)))" }))")*/
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
var k = 0
|
||||
while true {
|
||||
let left: T?
|
||||
|
||||
//print("i=\(i), j=\(j), k=\(k)")
|
||||
|
||||
if k < updatedIndices.count && updatedIndices[k].0 < i {
|
||||
//print("updated[k=\(k)]=\(updatedIndices[k].0)<i=\(i), k++")
|
||||
k += 1
|
||||
}
|
||||
|
||||
if k < updatedIndices.count {
|
||||
if updatedIndices[k].0 == i {
|
||||
left = updatedIndices[k].1
|
||||
//print("override left = \(updatedIndices[k].1.stableId)")
|
||||
} else {
|
||||
left = i < currentList.count ? currentList[i] : nil
|
||||
}
|
||||
} else {
|
||||
left = i < currentList.count ? currentList[i] : nil
|
||||
}
|
||||
|
||||
let right: T? = j < rightList.count ? rightList[j] : nil
|
||||
|
||||
if let left = left, let right = right {
|
||||
if left == right {
|
||||
//print("\(left.stableId)==\(right.stableId)")
|
||||
//print("i++, j++")
|
||||
i += 1
|
||||
j += 1
|
||||
} else if left > right {
|
||||
//print("\(left.stableId)>\(right.stableId)")
|
||||
//print("insert \(right.stableId) at \(i)")
|
||||
//print("i++, j++")
|
||||
let previousIndex = previousIndices[right.stableId]
|
||||
insertItems.append((i, right, previousIndex))
|
||||
currentList.insert(right, at: i)
|
||||
if k < updatedIndices.count {
|
||||
for l in k ..< updatedIndices.count {
|
||||
updatedIndices[l] = (updatedIndices[l].0 + 1, updatedIndices[l].1, updatedIndices[l].2)
|
||||
}
|
||||
}
|
||||
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
//print("\(left.stableId)<\(right.stableId)")
|
||||
//print("i++")
|
||||
i += 1
|
||||
}
|
||||
} else if let _ = left {
|
||||
//print("\(left!.stableId)>nil")
|
||||
//print("i++")
|
||||
i += 1
|
||||
} else if let right = right {
|
||||
//print("nil<\(right.stableId)")
|
||||
//print("insert \(right.stableId) at \(i)")
|
||||
//print("i++")
|
||||
//print("j++")
|
||||
let previousIndex = previousIndices[right.stableId]
|
||||
insertItems.append((i, right, previousIndex))
|
||||
currentList.insert(right, at: i)
|
||||
|
||||
if k < updatedIndices.count {
|
||||
for l in k ..< updatedIndices.count {
|
||||
updatedIndices[l] = (updatedIndices[l].0 + 1, updatedIndices[l].1, updatedIndices[l].2)
|
||||
}
|
||||
}
|
||||
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (index, item, _) in updatedIndices {
|
||||
currentList[index] = item
|
||||
}
|
||||
|
||||
assert(currentList == rightList, "currentList == rightList")
|
||||
|
||||
return (removeIndices, insertItems, updatedIndices)
|
||||
}
|
||||
|
||||
public func mergeListsStableWithUpdatesReversed<T>(leftList: [T], rightList: [T]) -> ([Int], [(Int, T, Int?)], [(Int, T, Int)]) where T: Comparable, T: Identifiable {
|
||||
var removeIndices: [Int] = []
|
||||
var insertItems: [(Int, T, Int?)] = []
|
||||
var updatedIndices: [(Int, T, Int)] = []
|
||||
|
||||
#if (arch(i386) || arch(x86_64)) && os(iOS)
|
||||
var existingStableIds: [T.T: T] = [:]
|
||||
for item in leftList {
|
||||
if let _ = existingStableIds[item.stableId] {
|
||||
assertionFailure()
|
||||
} else {
|
||||
existingStableIds[item.stableId] = item
|
||||
}
|
||||
}
|
||||
existingStableIds.removeAll()
|
||||
for item in rightList {
|
||||
if let other = existingStableIds[item.stableId] {
|
||||
print("\(other) has the same stableId as \(item): \(item.stableId)")
|
||||
assertionFailure()
|
||||
} else {
|
||||
existingStableIds[item.stableId] = item
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var currentList = leftList
|
||||
|
||||
var i = 0
|
||||
var previousIndices: [T.T: Int] = [:]
|
||||
for left in leftList {
|
||||
previousIndices[left.stableId] = i
|
||||
i += 1
|
||||
}
|
||||
|
||||
i = 0
|
||||
var j = 0
|
||||
while true {
|
||||
let left: T? = i < currentList.count ? currentList[i] : nil
|
||||
let right: T? = j < rightList.count ? rightList[j] : nil
|
||||
|
||||
if let left = left, let right = right {
|
||||
if left.stableId == right.stableId && left != right {
|
||||
updatedIndices.append((i, right, previousIndices[left.stableId]!))
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
if left == right {
|
||||
i += 1
|
||||
j += 1
|
||||
} else if left > right {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else if !(left < right) {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else {
|
||||
j += 1
|
||||
}
|
||||
}
|
||||
} else if let _ = left {
|
||||
removeIndices.append(i)
|
||||
i += 1
|
||||
} else if let _ = right {
|
||||
j += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//print("remove:\n\(removeIndices)")
|
||||
|
||||
for index in removeIndices.reversed() {
|
||||
currentList.remove(at: index)
|
||||
for i in 0 ..< updatedIndices.count {
|
||||
if updatedIndices[i].0 >= index {
|
||||
updatedIndices[i].0 -= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i = 0
|
||||
j = 0
|
||||
var k = 0
|
||||
while true {
|
||||
let left: T?
|
||||
|
||||
if k < updatedIndices.count && updatedIndices[k].0 < i {
|
||||
k += 1
|
||||
}
|
||||
|
||||
if k < updatedIndices.count {
|
||||
if updatedIndices[k].0 == i {
|
||||
left = updatedIndices[k].1
|
||||
} else {
|
||||
left = i < currentList.count ? currentList[i] : nil
|
||||
}
|
||||
} else {
|
||||
left = i < currentList.count ? currentList[i] : nil
|
||||
}
|
||||
|
||||
let right: T? = j < rightList.count ? rightList[j] : nil
|
||||
|
||||
if let left = left, let right = right {
|
||||
if left == right {
|
||||
i += 1
|
||||
j += 1
|
||||
} else if left < right {
|
||||
let previousIndex = previousIndices[right.stableId]
|
||||
insertItems.append((i, right, previousIndex))
|
||||
currentList.insert(right, at: i)
|
||||
if k < updatedIndices.count {
|
||||
for l in k ..< updatedIndices.count {
|
||||
updatedIndices[l] = (updatedIndices[l].0 + 1, updatedIndices[l].1, updatedIndices[l].2)
|
||||
}
|
||||
}
|
||||
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
i += 1
|
||||
}
|
||||
} else if let _ = left {
|
||||
i += 1
|
||||
} else if let right = right {
|
||||
let previousIndex = previousIndices[right.stableId]
|
||||
insertItems.append((i, right, previousIndex))
|
||||
currentList.insert(right, at: i)
|
||||
|
||||
if k < updatedIndices.count {
|
||||
for l in k ..< updatedIndices.count {
|
||||
updatedIndices[l] = (updatedIndices[l].0 + 1, updatedIndices[l].1, updatedIndices[l].2)
|
||||
}
|
||||
}
|
||||
|
||||
i += 1
|
||||
j += 1
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for (index, item, _) in updatedIndices {
|
||||
currentList[index] = item
|
||||
}
|
||||
|
||||
assert(currentList == rightList, "currentList == rightList")
|
||||
|
||||
return (removeIndices, insertItems, updatedIndices)
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 75
|
||||
return 76
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user