From 6d8b82d4e46bc77447429c3e97e18f648d530ede Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 15 Jun 2019 05:20:28 +0200 Subject: [PATCH] Fixed peers nearby updates --- Telegram-iOS/Info.plist | 94 +++++++++++++--- .../TelegramCore/PeersNearby.swift | 100 +++++++++++++++--- .../TelegramUI/ChannelAdminController.swift | 4 +- .../TelegramUI/ChannelAdminsController.swift | 2 +- .../ChannelOwnershipTransferController.swift | 4 + .../ChatMessageInteractiveFileNode.swift | 5 +- .../PeerPresenceStatusManager.swift | 4 +- .../TelegramUI/PeersNearbyController.swift | 41 ++++--- 8 files changed, 204 insertions(+), 50 deletions(-) diff --git a/Telegram-iOS/Info.plist b/Telegram-iOS/Info.plist index 8cfd6f1f19..4cd5288838 100644 --- a/Telegram-iOS/Info.plist +++ b/Telegram-iOS/Info.plist @@ -19,8 +19,6 @@ CFBundleIconFiles BlackIcon - BlackIconIpad - BlackIconLargeIpad UIPrerenderedIcon @@ -30,8 +28,6 @@ CFBundleIconFiles BlackClassicIcon - BlackClassicIconIpad - BlackClassicIconLargeIpad UIPrerenderedIcon @@ -41,8 +37,6 @@ CFBundleIconFiles BlackFilledIcon - BlackFilledIconIpad - BlackFilledIconLargeIpad UIPrerenderedIcon @@ -52,8 +46,6 @@ CFBundleIconFiles BlueIcon - BlueIconIpad - BlueIconLargeIpad UIPrerenderedIcon @@ -63,8 +55,6 @@ CFBundleIconFiles BlueClassicIcon - BlueClassicIconIpad - BlueClassicIconLargeIpad UIPrerenderedIcon @@ -74,8 +64,6 @@ CFBundleIconFiles BlueFilledIcon - BlueFilledIconIpad - BlueFilledIconLargeIpad UIPrerenderedIcon @@ -98,6 +86,88 @@ + CFBundleIcons~ipad + + CFBundleAlternateIcons + + Black + + CFBundleIconFiles + + BlackIconIpad + BlackIconLargeIpad + + UIPrerenderedIcon + + + BlackClassic + + CFBundleIconFiles + + BlackClassicIconIpad + BlackClassicIconLargeIpad + + UIPrerenderedIcon + + + BlackFilled + + CFBundleIconFiles + + BlackFilledIconIpad + BlackFilledIconLargeIpad + + UIPrerenderedIcon + + + Blue + + CFBundleIconFiles + + BlueIconIpad + BlueIconLargeIpad + + UIPrerenderedIcon + + + BlueClassic + + CFBundleIconFiles + + BlueClassicIconIpad + BlueClassicIconLargeIpad + + UIPrerenderedIcon + + + BlueFilled + + CFBundleIconFiles + + BlueFilledIconIpad + BlueFilledIconLargeIpad + + UIPrerenderedIcon + + + WhiteFilled + + CFBundleIconFiles + + WhiteFilledIcon + + UIPrerenderedIcon + + + + CFBundlePrimaryIcon + + CFBundleIconName + AppIconLLC + UIPrerenderedIcon + + + CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion diff --git a/submodules/TelegramCore/TelegramCore/PeersNearby.swift b/submodules/TelegramCore/TelegramCore/PeersNearby.swift index b8f191a921..b6906588c1 100644 --- a/submodules/TelegramCore/TelegramCore/PeersNearby.swift +++ b/submodules/TelegramCore/TelegramCore/PeersNearby.swift @@ -13,18 +13,24 @@ public struct PeerNearby { public let distance: Int32 } -public func peersNearby(network: Network, accountStateManager: AccountStateManager, coordinate: (latitude: Double, longitude: Double)) -> Signal<[PeerNearby], NoError> { - let inputGeoPoint = Api.InputGeoPoint.inputGeoPoint(lat: coordinate.latitude, long: coordinate.longitude) +public final class PeersNearbyContext { + private let queue: Queue = Queue.mainQueue() + private var subscribers = Bag<([PeerNearby]) -> Void>() + private let disposable = MetaDisposable() + private var timer: SwiftSignalKit.Timer? - return network.request(Api.functions.contacts.getLocated(geoPoint: inputGeoPoint)) - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(nil) - } - |> mapToSignal { updates in - var peersNearby: [PeerNearby] = [] - if let updates = updates { - switch updates { + private var entries: [PeerNearby] = [] + + public init(network: Network, accountStateManager: AccountStateManager, coordinate: (latitude: Double, longitude: Double)) { + self.disposable.set((network.request(Api.functions.contacts.getLocated(geoPoint: .inputGeoPoint(lat: coordinate.latitude, long: coordinate.longitude))) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { updates -> Signal<[PeerNearby], NoError> in + var peersNearby: [PeerNearby] = [] + if let updates = updates { + switch updates { case let .updates(updates, _, _, _, _): for update in updates { if case let .updatePeerLocated(peers) = update { @@ -35,13 +41,77 @@ public func peersNearby(network: Network, accountStateManager: AccountStateManag } default: break + } + accountStateManager.addUpdates(updates) + } + return .single(peersNearby) + |> then(accountStateManager.updatedPeersNearby()) + }).start(next: { [weak self] updatedEntries in + guard let strongSelf = self else { + return } - accountStateManager.addUpdates(updates) - } + let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + var entries = strongSelf.entries.filter { Double($0.expires) > timestamp } + let updatedEntries = updatedEntries.filter { Double($0.expires) > timestamp } + + var existingPeerIds: [PeerId: Int] = [:] + for i in 0 ..< entries.count { + existingPeerIds[entries[i].id] = i + } + + for entry in updatedEntries { + if let index = existingPeerIds[entry.id] { + entries[index] = entry + } else { + entries.append(entry) + } + } + + strongSelf.entries = entries + + for subscriber in strongSelf.subscribers.copyItems() { + subscriber(strongSelf.entries) + } + })) - return .single(peersNearby) - |> then(accountStateManager.updatedPeersNearby()) + self.timer = SwiftSignalKit.Timer(timeout: 5.0, repeat: true, completion: { [weak self] in + guard let strongSelf = self else { + return + } + + let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 + strongSelf.entries = strongSelf.entries.filter { Double($0.expires) > timestamp } + }, queue: self.queue) + self.timer?.start() + } + + deinit { + self.disposable.dispose() + self.timer?.invalidate() + } + + public func get() -> Signal<[PeerNearby], NoError> { + let queue = self.queue + return Signal { [weak self] subscriber in + if let strongSelf = self { + subscriber.putNext(strongSelf.entries) + + let index = strongSelf.subscribers.add({ entries in + subscriber.putNext(entries) + }) + + return ActionDisposable { + queue.async { + if let strongSelf = self { + strongSelf.subscribers.remove(index) + } + } + } + } else { + return EmptyDisposable + } + } |> runOn(queue) } } diff --git a/submodules/TelegramUI/TelegramUI/ChannelAdminController.swift b/submodules/TelegramUI/TelegramUI/ChannelAdminController.swift index 6de64dd841..d1f139e38c 100644 --- a/submodules/TelegramUI/TelegramUI/ChannelAdminController.swift +++ b/submodules/TelegramUI/TelegramUI/ChannelAdminController.swift @@ -468,7 +468,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s entries.append(.transfer(presentationData.theme, isGroup ? presentationData.strings.Group_EditAdmin_TransferOwnership : presentationData.strings.Channel_EditAdmin_TransferOwnership)) } - if let initialParticipant = initialParticipant, case let .member(participant) = initialParticipant, let adminInfo = participant.adminInfo, !adminInfo.rights.flags.isEmpty { + if let initialParticipant = initialParticipant, case let .member(participant) = initialParticipant, let adminInfo = participant.adminInfo, !adminInfo.rights.flags.isEmpty && admin.id != accountPeerId { var canDismiss = false if channel.flags.contains(.isCreator) { canDismiss = true @@ -538,7 +538,7 @@ private func channelAdminControllerEntries(presentationData: PresentationData, s entries.append(.transfer(presentationData.theme, presentationData.strings.Group_EditAdmin_TransferOwnership)) } - if let initialParticipant = initialParticipant, case let .member(participant) = initialParticipant, let adminInfo = participant.adminInfo, !adminInfo.rights.flags.isEmpty { + if let initialParticipant = initialParticipant, case let .member(participant) = initialParticipant, let adminInfo = participant.adminInfo, !adminInfo.rights.flags.isEmpty && admin.id != accountPeerId { entries.append(.dismiss(presentationData.theme, presentationData.strings.Channel_Moderator_AccessLevelRevoke)) } } diff --git a/submodules/TelegramUI/TelegramUI/ChannelAdminsController.swift b/submodules/TelegramUI/TelegramUI/ChannelAdminsController.swift index ccc3c04a8c..e81633587e 100644 --- a/submodules/TelegramUI/TelegramUI/ChannelAdminsController.swift +++ b/submodules/TelegramUI/TelegramUI/ChannelAdminsController.swift @@ -503,7 +503,7 @@ public func channelAdminsController(context: AccountContext, peerId: PeerId, loa guard let peer = peer, let user = user else { return } - presentControllerImpl?(UndoOverlayController(context: context, content: .succeed(text: presentationData.strings.Channel_OwnershipTransfer_TransferCompleted(peer.displayTitle, user.displayTitle).0), elevatedLayout: false, action: { _ in }), nil) + presentControllerImpl?(UndoOverlayController(context: context, content: .succeed(text: presentationData.strings.Channel_OwnershipTransfer_TransferCompleted(user.displayTitle, peer.displayTitle).0), elevatedLayout: false, action: { _ in }), nil) }) } diff --git a/submodules/TelegramUI/TelegramUI/ChannelOwnershipTransferController.swift b/submodules/TelegramUI/TelegramUI/ChannelOwnershipTransferController.swift index c8a263ccf5..cc1d941f3b 100644 --- a/submodules/TelegramUI/TelegramUI/ChannelOwnershipTransferController.swift +++ b/submodules/TelegramUI/TelegramUI/ChannelOwnershipTransferController.swift @@ -410,6 +410,10 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p proceedImpl?() })]) + contentNode.complete = { + proceedImpl?() + } + let controller = AlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), contentNode: contentNode) let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in controller?.theme = AlertControllerTheme(presentationTheme: presentationData.theme) diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift index 045a09b24a..64bc8d4d1e 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInteractiveFileNode.swift @@ -105,7 +105,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { self.consumableContentNode = ASImageNode() super.init() - + self.backgroundColor = UIColor.red.withAlphaComponent(0.5) self.addSubnode(self.titleNode) self.addSubnode(self.descriptionNode) self.addSubnode(self.fetchingTextNode) @@ -489,6 +489,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { if hasStreamingProgress { fittedLayoutSize.width += streamingProgressDiameter + 6.0 } + fittedLayoutSize.width = max(fittedLayoutSize.width, boundingWidth + 2.0) } else { streamingCacheStatusFrame = CGRect() } @@ -633,8 +634,6 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { } private func updateStatus(animated: Bool) { - - guard let resourceStatus = self.resourceStatus else { return } diff --git a/submodules/TelegramUI/TelegramUI/PeerPresenceStatusManager.swift b/submodules/TelegramUI/TelegramUI/PeerPresenceStatusManager.swift index 4f388c911f..ef58217189 100644 --- a/submodules/TelegramUI/TelegramUI/PeerPresenceStatusManager.swift +++ b/submodules/TelegramUI/TelegramUI/PeerPresenceStatusManager.swift @@ -15,8 +15,8 @@ final class PeerPresenceStatusManager { } func reset(presence: TelegramUserPresence) { - timer?.invalidate() - timer = nil + self.timer?.invalidate() + self.timer = nil let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970 let timeout = userPresenceStringRefreshTimeout(presence, relativeTo: Int32(timestamp)) diff --git a/submodules/TelegramUI/TelegramUI/PeersNearbyController.swift b/submodules/TelegramUI/TelegramUI/PeersNearbyController.swift index 3938a7ba8b..5f8c623037 100644 --- a/submodules/TelegramUI/TelegramUI/PeersNearbyController.swift +++ b/submodules/TelegramUI/TelegramUI/PeersNearbyController.swift @@ -305,28 +305,39 @@ public func peersNearbyController(context: AccountContext) -> ViewController { guard let coordinate = coordinate else { return .single(nil) } - let poll = peersNearby(network: context.account.network, accountStateManager: context.account.stateManager, coordinate: (latitude: coordinate.latitude, longitude: coordinate.longitude)) - |> mapToSignal { peersNearby -> Signal in - return context.account.postbox.transaction { transaction -> PeersNearbyData? in - var users: [PeerNearbyEntry] = [] - var groups: [PeerNearbyEntry] = [] - for peerNearby in peersNearby { - if peerNearby.id != context.account.peerId, let peer = transaction.getPeer(peerNearby.id) { - if peerNearby.id.namespace == Namespaces.Peer.CloudUser { - users.append(PeerNearbyEntry(peer: (peer, nil), expires: peerNearby.expires, distance: peerNearby.distance)) - } else { - let cachedData = transaction.getPeerCachedData(peerId: peerNearby.id) as? CachedChannelData - groups.append(PeerNearbyEntry(peer: (peer, cachedData), expires: peerNearby.expires, distance: peerNearby.distance)) + + return Signal { subscriber in + let peersNearbyContext = PeersNearbyContext(network: context.account.network, accountStateManager: context.account.stateManager, coordinate: (latitude: coordinate.latitude, longitude: coordinate.longitude)) + + let disposable = (peersNearbyContext.get() + |> mapToSignal { peersNearby -> Signal in + return context.account.postbox.transaction { transaction -> PeersNearbyData? in + var users: [PeerNearbyEntry] = [] + var groups: [PeerNearbyEntry] = [] + for peerNearby in peersNearby { + if peerNearby.id != context.account.peerId, let peer = transaction.getPeer(peerNearby.id) { + if peerNearby.id.namespace == Namespaces.Peer.CloudUser { + users.append(PeerNearbyEntry(peer: (peer, nil), expires: peerNearby.expires, distance: peerNearby.distance)) + } else { + let cachedData = transaction.getPeerCachedData(peerId: peerNearby.id) as? CachedChannelData + groups.append(PeerNearbyEntry(peer: (peer, cachedData), expires: peerNearby.expires, distance: peerNearby.distance)) + } } } + return PeersNearbyData(users: users, groups: groups, channels: []) } - return PeersNearbyData(users: users, groups: groups, channels: []) + }).start(next: { data in + subscriber.putNext(data) + }) + + return ActionDisposable { + disposable.dispose() + let _ = peersNearbyContext.get() } } - return (poll |> then(.complete() |> suspendAwareDelay(25.0, queue: Queue.concurrentDefaultQueue()))) |> restart } - dataPromise.set(dataSignal) + dataPromise.set((dataSignal |> then(.complete() |> suspendAwareDelay(25.0, queue: Queue.concurrentDefaultQueue()))) |> restart) let signal = combineLatest(context.sharedContext.presentationData, statePromise.get(), dataPromise.get()) |> deliverOnMainQueue