no message

This commit is contained in:
Peter Iakovlev
2018-01-12 12:48:06 +04:00
parent 3a998955b7
commit f8afc46bef
20 changed files with 609 additions and 36 deletions

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LiveLocationTitlePin@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LiveLocationTitlePin@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

View File

@@ -86,6 +86,7 @@
D048EA8B1F4F298A00188713 /* InstantPageSettingsThemeItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048EA8A1F4F298A00188713 /* InstantPageSettingsThemeItemNode.swift */; }; D048EA8B1F4F298A00188713 /* InstantPageSettingsThemeItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048EA8A1F4F298A00188713 /* InstantPageSettingsThemeItemNode.swift */; };
D048EA8D1F4F299A00188713 /* InstantPageSettingsSwitchItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048EA8C1F4F299A00188713 /* InstantPageSettingsSwitchItemNode.swift */; }; D048EA8D1F4F299A00188713 /* InstantPageSettingsSwitchItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048EA8C1F4F299A00188713 /* InstantPageSettingsSwitchItemNode.swift */; };
D048EA8F1F4F2A9C00188713 /* InstantPageSettingsItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048EA8E1F4F2A9C00188713 /* InstantPageSettingsItemNode.swift */; }; D048EA8F1F4F2A9C00188713 /* InstantPageSettingsItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048EA8E1F4F2A9C00188713 /* InstantPageSettingsItemNode.swift */; };
D04B26EC20082EB50053A58C /* LocationBroadcastPanelWavesNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B26EB20082EB50053A58C /* LocationBroadcastPanelWavesNode.swift */; };
D04B4D111EEA04D400711AF6 /* MapResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B4D101EEA04D400711AF6 /* MapResources.swift */; }; D04B4D111EEA04D400711AF6 /* MapResources.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B4D101EEA04D400711AF6 /* MapResources.swift */; };
D04B4D131EEA0A6500711AF6 /* ChatMessageMapBubbleContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B4D121EEA0A6500711AF6 /* ChatMessageMapBubbleContentNode.swift */; }; D04B4D131EEA0A6500711AF6 /* ChatMessageMapBubbleContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B4D121EEA0A6500711AF6 /* ChatMessageMapBubbleContentNode.swift */; };
D04B4D661EEA993A00711AF6 /* LegacyLocationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B4D651EEA993A00711AF6 /* LegacyLocationController.swift */; }; D04B4D661EEA993A00711AF6 /* LegacyLocationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04B4D651EEA993A00711AF6 /* LegacyLocationController.swift */; };
@@ -137,6 +138,7 @@
D091C7A61F8ECEA300D7DE13 /* SettingsThemeWallpaperNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D091C7A51F8ECEA300D7DE13 /* SettingsThemeWallpaperNode.swift */; }; D091C7A61F8ECEA300D7DE13 /* SettingsThemeWallpaperNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D091C7A51F8ECEA300D7DE13 /* SettingsThemeWallpaperNode.swift */; };
D09250041FE5363D003F693F /* ExperimentalSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09250031FE5363D003F693F /* ExperimentalSettings.swift */; }; D09250041FE5363D003F693F /* ExperimentalSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09250031FE5363D003F693F /* ExperimentalSettings.swift */; };
D09250061FE5371D003F693F /* GlobalExperimentalSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09250051FE5371D003F693F /* GlobalExperimentalSettings.swift */; }; D09250061FE5371D003F693F /* GlobalExperimentalSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09250051FE5371D003F693F /* GlobalExperimentalSettings.swift */; };
D09394132007F5BB00997F31 /* LocationBroadcastNavigationAccessoryPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09394122007F5BB00997F31 /* LocationBroadcastNavigationAccessoryPanel.swift */; };
D0943AF61FDAAE7E001522CC /* MultipleAvatarsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */; }; D0943AF61FDAAE7E001522CC /* MultipleAvatarsNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */; };
D0943AFE1FDAE454001522CC /* ChatMultipleAvatarsNavigationNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0943AFD1FDAE454001522CC /* ChatMultipleAvatarsNavigationNode.swift */; }; D0943AFE1FDAE454001522CC /* ChatMultipleAvatarsNavigationNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0943AFD1FDAE454001522CC /* ChatMultipleAvatarsNavigationNode.swift */; };
D0943B001FDAE852001522CC /* ChatFeedNavigationInputPanelNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0943AFF1FDAE852001522CC /* ChatFeedNavigationInputPanelNode.swift */; }; D0943B001FDAE852001522CC /* ChatFeedNavigationInputPanelNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0943AFF1FDAE852001522CC /* ChatFeedNavigationInputPanelNode.swift */; };
@@ -1209,6 +1211,7 @@
D049EAE51E44AD5600A2CD3A /* ChatMediaInputMetaSectionItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMediaInputMetaSectionItemNode.swift; sourceTree = "<group>"; }; D049EAE51E44AD5600A2CD3A /* ChatMediaInputMetaSectionItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMediaInputMetaSectionItemNode.swift; sourceTree = "<group>"; };
D049EAED1E44BB3200A2CD3A /* ChatListRecentPeersListItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatListRecentPeersListItem.swift; sourceTree = "<group>"; }; D049EAED1E44BB3200A2CD3A /* ChatListRecentPeersListItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatListRecentPeersListItem.swift; sourceTree = "<group>"; };
D049EAF21E44DE2500A2CD3A /* AuthorizationSequenceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizationSequenceController.swift; sourceTree = "<group>"; }; D049EAF21E44DE2500A2CD3A /* AuthorizationSequenceController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthorizationSequenceController.swift; sourceTree = "<group>"; };
D04B26EB20082EB50053A58C /* LocationBroadcastPanelWavesNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationBroadcastPanelWavesNode.swift; sourceTree = "<group>"; };
D04B4D101EEA04D400711AF6 /* MapResources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapResources.swift; sourceTree = "<group>"; }; D04B4D101EEA04D400711AF6 /* MapResources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapResources.swift; sourceTree = "<group>"; };
D04B4D121EEA0A6500711AF6 /* ChatMessageMapBubbleContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMessageMapBubbleContentNode.swift; sourceTree = "<group>"; }; D04B4D121EEA0A6500711AF6 /* ChatMessageMapBubbleContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatMessageMapBubbleContentNode.swift; sourceTree = "<group>"; };
D04B4D651EEA993A00711AF6 /* LegacyLocationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyLocationController.swift; sourceTree = "<group>"; }; D04B4D651EEA993A00711AF6 /* LegacyLocationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyLocationController.swift; sourceTree = "<group>"; };
@@ -1423,6 +1426,7 @@
D091C7A51F8ECEA300D7DE13 /* SettingsThemeWallpaperNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsThemeWallpaperNode.swift; sourceTree = "<group>"; }; D091C7A51F8ECEA300D7DE13 /* SettingsThemeWallpaperNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsThemeWallpaperNode.swift; sourceTree = "<group>"; };
D09250031FE5363D003F693F /* ExperimentalSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperimentalSettings.swift; sourceTree = "<group>"; }; D09250031FE5363D003F693F /* ExperimentalSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExperimentalSettings.swift; sourceTree = "<group>"; };
D09250051FE5371D003F693F /* GlobalExperimentalSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalExperimentalSettings.swift; sourceTree = "<group>"; }; D09250051FE5371D003F693F /* GlobalExperimentalSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalExperimentalSettings.swift; sourceTree = "<group>"; };
D09394122007F5BB00997F31 /* LocationBroadcastNavigationAccessoryPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationBroadcastNavigationAccessoryPanel.swift; sourceTree = "<group>"; };
D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleAvatarsNode.swift; sourceTree = "<group>"; }; D0943AF51FDAAE7E001522CC /* MultipleAvatarsNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipleAvatarsNode.swift; sourceTree = "<group>"; };
D0943AFD1FDAE454001522CC /* ChatMultipleAvatarsNavigationNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMultipleAvatarsNavigationNode.swift; sourceTree = "<group>"; }; D0943AFD1FDAE454001522CC /* ChatMultipleAvatarsNavigationNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatMultipleAvatarsNavigationNode.swift; sourceTree = "<group>"; };
D0943AFF1FDAE852001522CC /* ChatFeedNavigationInputPanelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatFeedNavigationInputPanelNode.swift; sourceTree = "<group>"; }; D0943AFF1FDAE852001522CC /* ChatFeedNavigationInputPanelNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatFeedNavigationInputPanelNode.swift; sourceTree = "<group>"; };
@@ -2764,6 +2768,8 @@
D0736F2B1DF4DC2400F2C02A /* MediaNavigationAccessoryContainerNode.swift */, D0736F2B1DF4DC2400F2C02A /* MediaNavigationAccessoryContainerNode.swift */,
D0736F2D1DF4E54A00F2C02A /* MediaNavigationAccessoryHeaderNode.swift */, D0736F2D1DF4E54A00F2C02A /* MediaNavigationAccessoryHeaderNode.swift */,
D0177B811DFAEA5400A5083A /* MediaNavigationAccessoryItemListNode.swift */, D0177B811DFAEA5400A5083A /* MediaNavigationAccessoryItemListNode.swift */,
D09394122007F5BB00997F31 /* LocationBroadcastNavigationAccessoryPanel.swift */,
D04B26EB20082EB50053A58C /* LocationBroadcastPanelWavesNode.swift */,
); );
name = "Telegram Controller"; name = "Telegram Controller";
sourceTree = "<group>"; sourceTree = "<group>";
@@ -5114,6 +5120,7 @@
D0EC6CCF1EB9F58800EBF1C3 /* GeoLocation.swift in Sources */, D0EC6CCF1EB9F58800EBF1C3 /* GeoLocation.swift in Sources */,
D0EC6EA71EBA0FB000EBF1C3 /* BlockingQueue.cpp in Sources */, D0EC6EA71EBA0FB000EBF1C3 /* BlockingQueue.cpp in Sources */,
D0EC6CD01EB9F58800EBF1C3 /* PerformanceSpinner.swift in Sources */, D0EC6CD01EB9F58800EBF1C3 /* PerformanceSpinner.swift in Sources */,
D09394132007F5BB00997F31 /* LocationBroadcastNavigationAccessoryPanel.swift in Sources */,
D0471B5C1EFEB4F30074D609 /* BotPaymentFieldItemNode.swift in Sources */, D0471B5C1EFEB4F30074D609 /* BotPaymentFieldItemNode.swift in Sources */,
D0C27B3D1F4B454800A4E170 /* InstantPagePlayableVideoNode.swift in Sources */, D0C27B3D1F4B454800A4E170 /* InstantPagePlayableVideoNode.swift in Sources */,
D0EC6CD11EB9F58800EBF1C3 /* UrlHandling.swift in Sources */, D0EC6CD11EB9F58800EBF1C3 /* UrlHandling.swift in Sources */,
@@ -5167,6 +5174,7 @@
D0EC6FEF1EBA18E800EBF1C3 /* VoIPController.cpp in Sources */, D0EC6FEF1EBA18E800EBF1C3 /* VoIPController.cpp in Sources */,
D0EC6CED1EB9F58800EBF1C3 /* StringPluralization.swift in Sources */, D0EC6CED1EB9F58800EBF1C3 /* StringPluralization.swift in Sources */,
D020A9DC1FEAE6E7008C66F7 /* OverlayPlayerControllerNode.swift in Sources */, D020A9DC1FEAE6E7008C66F7 /* OverlayPlayerControllerNode.swift in Sources */,
D04B26EC20082EB50053A58C /* LocationBroadcastPanelWavesNode.swift in Sources */,
D0EC6FC61EBA135100EBF1C3 /* complex_fft.c in Sources */, D0EC6FC61EBA135100EBF1C3 /* complex_fft.c in Sources */,
D0EC6CEE1EB9F58800EBF1C3 /* InAppNotificationSettings.swift in Sources */, D0EC6CEE1EB9F58800EBF1C3 /* InAppNotificationSettings.swift in Sources */,
D0EC6CEF1EB9F58800EBF1C3 /* PresentationPasscodeSettings.swift in Sources */, D0EC6CEF1EB9F58800EBF1C3 /* PresentationPasscodeSettings.swift in Sources */,

View File

@@ -7,7 +7,7 @@
<key>TelegramUI.xcscheme</key> <key>TelegramUI.xcscheme</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>13</integer> <integer>3</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@@ -149,10 +149,14 @@ public final class ChatController: TelegramController {
self.messageId = messageId self.messageId = messageId
self.botStart = botStart self.botStart = botStart
let locationBroadcastPanelSource: LocationBroadcastPanelSource
switch chatLocation { switch chatLocation {
case .peer: case let .peer(peerId):
locationBroadcastPanelSource = .peer(peerId)
self.chatLocationInfoData = .peer(Promise()) self.chatLocationInfoData = .peer(Promise())
case .group: case .group:
locationBroadcastPanelSource = .none
self.chatLocationInfoData = .group(Promise()) self.chatLocationInfoData = .group(Promise())
} }
@@ -166,7 +170,7 @@ public final class ChatController: TelegramController {
if case .overlay = mode { if case .overlay = mode {
enableMediaAccessoryPanel = false enableMediaAccessoryPanel = false
} }
super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), enableMediaAccessoryPanel: enableMediaAccessoryPanel) super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), enableMediaAccessoryPanel: enableMediaAccessoryPanel, locationBroadcastPanelSource: locationBroadcastPanelSource)
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)

View File

@@ -39,7 +39,7 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
self.titleView = NetworkStatusTitleView(theme: self.presentationData.theme) self.titleView = NetworkStatusTitleView(theme: self.presentationData.theme)
super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), enableMediaAccessoryPanel: true) super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), enableMediaAccessoryPanel: true, locationBroadcastPanelSource: .summary)
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style

View File

@@ -22,7 +22,7 @@ final class HashtagSearchController: TelegramController {
self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), enableMediaAccessoryPanel: true) super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), enableMediaAccessoryPanel: true, locationBroadcastPanelSource: .none)
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBar.style.style

View File

@@ -213,4 +213,13 @@ public final class LiveLocationManager {
self.pollingOnceValue = true self.pollingOnceValue = true
} }
} }
func internalMessageForPeerId(_ peerId: PeerId) -> MessageId? {
for id in self.broadcastToMessageIds {
if id.peerId == peerId {
return id
}
}
return nil
}
} }

View File

@@ -82,7 +82,7 @@ private final class LiveLocationPeerSummaryContext {
private let peerId: PeerId private let peerId: PeerId
private let becameEmpty: () -> Void private let becameEmpty: () -> Void
private var peers: [Peer] = [] { private var peers: [Peer]? = nil {
didSet { didSet {
assert(self.queue.isCurrent()) assert(self.queue.isCurrent())
@@ -106,7 +106,7 @@ private final class LiveLocationPeerSummaryContext {
} }
} }
} }
private var subscribers = Bag<([Peer]) -> Void>() private var subscribers = Bag<([Peer]?) -> Void>()
var isEmpty: Bool { var isEmpty: Bool {
return !self.isActive && self.subscribers.isEmpty return !self.isActive && self.subscribers.isEmpty
@@ -126,7 +126,7 @@ private final class LiveLocationPeerSummaryContext {
self.peerDisposable.dispose() self.peerDisposable.dispose()
} }
func subscribe(_ f: @escaping ([Peer]) -> Void) -> Disposable { func subscribe(_ f: @escaping ([Peer]?) -> Void) -> Disposable {
let index = self.subscribers.add({ next in let index = self.subscribers.add({ next in
f(next) f(next)
}) })
@@ -165,7 +165,7 @@ private final class LiveLocationPeerSummaryContext {
})) }))
} else { } else {
self.peerDisposable.set(nil) self.peerDisposable.set(nil)
self.peers = [] self.peers = nil
} }
} }
} }
@@ -195,21 +195,6 @@ final class LiveLocationSummaryManager {
peerIds.insert(id.peerId) peerIds.insert(id.peerId)
} }
var removedPeerIds: [PeerId] = []
for peerId in self.peerContexts.keys {
if !peerIds.contains(peerId) {
removedPeerIds.append(peerId)
}
}
for peerId in removedPeerIds {
if let _ = self.peerContexts[peerId] {
self.peerContexts.removeValue(forKey: peerId)
} else {
assertionFailure()
}
}
for peerId in peerIds { for peerId in peerIds {
if self.peerContexts[peerId] == nil { if self.peerContexts[peerId] == nil {
let context = LiveLocationPeerSummaryContext(queue: self.queue, accountPeerId: self.accountPeerId, viewTracker: self.viewTracker, peerId: peerId, becameEmpty: { [weak self] in let context = LiveLocationPeerSummaryContext(queue: self.queue, accountPeerId: self.accountPeerId, viewTracker: self.viewTracker, peerId: peerId, becameEmpty: { [weak self] in
@@ -232,7 +217,7 @@ final class LiveLocationSummaryManager {
return self.globalContext.subscribe() return self.globalContext.subscribe()
} }
func peersBroadcastingTo(peerId: PeerId) -> Signal<[Peer], NoError> { func peersBroadcastingTo(peerId: PeerId) -> Signal<[Peer]?, NoError> {
let queue = self.queue let queue = self.queue
return Signal { [weak self] subscriber in return Signal { [weak self] subscriber in
let disposable = MetaDisposable() let disposable = MetaDisposable()
@@ -247,6 +232,7 @@ final class LiveLocationSummaryManager {
strongSelf.peerContexts.removeValue(forKey: peerId) strongSelf.peerContexts.removeValue(forKey: peerId)
} }
}) })
strongSelf.peerContexts[peerId] = context
} }
disposable.set(context.subscribe({ next in disposable.set(context.subscribe({ next in

View File

@@ -0,0 +1,184 @@
import Foundation
import AsyncDisplayKit
import Display
import TelegramCore
import Postbox
private let titleFont = Font.regular(12.0)
private let subtitleFont = Font.regular(10.0)
enum LocationBroadcastNavigationAccessoryPanelMode {
case summary
case peer
}
final class LocationBroadcastNavigationAccessoryPanel: ASDisplayNode {
private var theme: PresentationTheme
private var strings: PresentationStrings
private let tapAction: () -> Void
private let close: () -> Void
private let contentNode: ASDisplayNode
private let iconNode: ASImageNode
private let wavesNode: LocationBroadcastPanelWavesNode
private let titleNode: TextNode
private let subtitleNode: TextNode
private let closeButton: HighlightableButtonNode
private let separatorNode: ASDisplayNode
private var validLayout: CGSize?
private var peersAndMode: ([Peer], LocationBroadcastNavigationAccessoryPanelMode)?
init(theme: PresentationTheme, strings: PresentationStrings, tapAction: @escaping () -> Void, close: @escaping () -> Void) {
self.theme = theme
self.strings = strings
self.tapAction = tapAction
self.close = close
self.contentNode = ASDisplayNode()
self.contentNode.backgroundColor = self.theme.rootController.navigationBar.backgroundColor
self.iconNode = ASImageNode()
self.iconNode.isLayerBacked = true
self.iconNode.displayWithoutProcessing = true
self.iconNode.displaysAsynchronously = false
self.iconNode.image = PresentationResourcesRootController.navigationLiveLocationIcon(self.theme)
self.wavesNode = LocationBroadcastPanelWavesNode(color: self.theme.rootController.navigationBar.accentTextColor)
self.titleNode = TextNode()
self.titleNode.isLayerBacked = true
self.subtitleNode = TextNode()
self.subtitleNode.isLayerBacked = true
self.closeButton = HighlightableButtonNode()
self.closeButton.setImage(PresentationResourcesRootController.navigationPlayerCloseButton(self.theme), for: [])
self.closeButton.hitTestSlop = UIEdgeInsetsMake(-8.0, -8.0, -8.0, -8.0)
self.closeButton.displaysAsynchronously = false
self.separatorNode = ASDisplayNode()
self.separatorNode.isLayerBacked = true
self.separatorNode.backgroundColor = theme.rootController.navigationBar.separatorColor
super.init()
self.addSubnode(self.contentNode)
self.contentNode.addSubnode(self.iconNode)
self.contentNode.addSubnode(self.wavesNode)
self.contentNode.addSubnode(self.titleNode)
self.contentNode.addSubnode(self.subtitleNode)
self.contentNode.addSubnode(self.closeButton)
self.contentNode.addSubnode(self.separatorNode)
self.closeButton.addTarget(self, action: #selector(self.closePressed), forControlEvents: .touchUpInside)
}
override func didLoad() {
super.didLoad()
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))
self.view.addGestureRecognizer(tapRecognizer)
}
func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) {
self.validLayout = size
transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(), size: size))
let titleString = NSAttributedString(string: self.strings.Conversation_LiveLocation, font: titleFont, textColor: self.theme.rootController.navigationBar.primaryTextColor)
var subtitleString: NSAttributedString?
if let (peers, mode) = self.peersAndMode {
switch mode {
case .summary:
let text: String
if peers.count == 1 {
text = self.strings.DialogList_LiveLocationSharingTo(peers[0].displayTitle).0
} else {
text = self.strings.DialogList_LiveLocationChatsCount(Int32(peers.count))
}
subtitleString = NSAttributedString(string: text, font: subtitleFont, textColor: self.theme.rootController.navigationBar.secondaryTextColor)
case .peer:
if peers.count == 0 {
subtitleString = NSAttributedString(string: self.strings.Conversation_LiveLocationYou, font: subtitleFont, textColor: self.theme.rootController.navigationBar.accentTextColor)
} else {
let otherString: String
if peers.count == 1 {
otherString = peers[0].compactDisplayTitle
} else {
otherString = self.strings.Conversation_LiveLocationMembersCount(Int32(peers.count))
}
let rawText = self.strings.Conversation_LiveLocationYouAnd(otherString).0.replacingOccurrences(of: "*", with: "**")
let body = MarkdownAttributeSet(font: subtitleFont, textColor: self.theme.rootController.navigationBar.secondaryTextColor)
let accent = MarkdownAttributeSet(font: subtitleFont, textColor: self.theme.rootController.navigationBar.accentTextColor)
subtitleString = parseMarkdownIntoAttributedString(rawText, attributes: MarkdownAttributes(body: body, bold: accent, link: body, linkAttribute: { _ in nil }))
}
}
}
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
let makeSubtitleLayout = TextNode.asyncLayout(self.subtitleNode)
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .middle, constrainedSize: CGSize(width: size.width - 80.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: subtitleString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .middle, constrainedSize: CGSize(width: size.width - 80.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let _ = titleApply()
let _ = subtitleApply()
let minimizedTitleOffset: CGFloat = subtitleString == nil ? 6.0 : 0.0
let minimizedTitleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleLayout.size.width) / 2.0), y: 4.0 + minimizedTitleOffset), size: titleLayout.size)
let minimizedSubtitleFrame = CGRect(origin: CGPoint(x: floor((size.width - subtitleLayout.size.width) / 2.0), y: 20.0), size: subtitleLayout.size)
if let image = self.iconNode.image {
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: 7.0, y: 8.0), size: image.size))
transition.updateFrame(node: self.wavesNode, frame: CGRect(origin: CGPoint(x: -2.0, y: -4.0), size: CGSize(width: 48.0, height: 48.0)))
}
transition.updateFrame(node: self.titleNode, frame: minimizedTitleFrame)
transition.updateFrame(node: self.subtitleNode, frame: minimizedSubtitleFrame)
let closeButtonSize = self.closeButton.measure(CGSize(width: 100.0, height: 100.0))
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: bounds.size.width - 18.0 - closeButtonSize.width, y: minimizedTitleFrame.minY + 8.0), size: closeButtonSize))
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel)))
}
func update(peers: [Peer], mode: LocationBroadcastNavigationAccessoryPanelMode) {
self.peersAndMode = (peers, mode)
if let size = validLayout {
self.updateLayout(size: size, transition: .immediate)
}
}
func animateIn(_ transition: ContainedViewLayoutTransition) {
self.clipsToBounds = true
let contentPosition = self.contentNode.layer.position
transition.animatePosition(node: self.contentNode, from: CGPoint(x: contentPosition.x, y: contentPosition.y - 37.0), completion: { [weak self] _ in
self?.clipsToBounds = false
})
}
func animateOut(_ transition: ContainedViewLayoutTransition, completion: @escaping () -> Void) {
self.clipsToBounds = true
let contentPosition = self.contentNode.layer.position
transition.animatePosition(node: self.contentNode, to: CGPoint(x: contentPosition.x, y: contentPosition.y - 37.0), removeOnCompletion: false, completion: { [weak self] _ in
self?.clipsToBounds = false
completion()
})
}
@objc func closePressed() {
self.close()
}
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
if case .ended = recognizer.state {
self.tapAction()
}
}
}

View File

@@ -0,0 +1,129 @@
import Foundation
import Display
import AsyncDisplayKit
import LegacyComponents
private final class LocationBroadcastPanelWavesNodeParams: NSObject {
let color: UIColor
let progress: CGFloat
init(color: UIColor, progress: CGFloat) {
self.color = color
self.progress = progress
super.init()
}
}
private func degToRad(_ degrees: CGFloat) -> CGFloat {
return degrees * CGFloat.pi / 180.0
}
final class LocationBroadcastPanelWavesNode: ASDisplayNode {
private var color: UIColor
private var effectiveProgress: CGFloat = 0.0 {
didSet {
self.setNeedsDisplay()
}
}
init(color: UIColor) {
self.color = color
super.init()
self.isLayerBacked = true
self.isOpaque = false
}
override func willEnterHierarchy() {
super.willEnterHierarchy()
self.pop_removeAnimation(forKey: "indefiniteProgress")
let animation = POPBasicAnimation()
animation.property = POPAnimatableProperty.property(withName: "progress", initializer: { property in
property?.readBlock = { node, values in
values?.pointee = (node as! LocationBroadcastPanelWavesNode).effectiveProgress
}
property?.writeBlock = { node, values in
(node as! LocationBroadcastPanelWavesNode).effectiveProgress = values!.pointee
}
property?.threshold = 0.01
}) as! POPAnimatableProperty
animation.fromValue = CGFloat(0.0) as NSNumber
animation.toValue = CGFloat(1.0) as NSNumber
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 2.5
animation.repeatForever = true
self.pop_add(animation, forKey: "indefiniteProgress")
}
override func didExitHierarchy() {
super.didExitHierarchy()
self.pop_removeAnimation(forKey: "indefiniteProgress")
}
override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
let t = CACurrentMediaTime()
let value: CGFloat = CGFloat(t.truncatingRemainder(dividingBy: 2.0)) / 2.0
return LocationBroadcastPanelWavesNodeParams(color: self.color, progress: value)
}
@objc override class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
let context = UIGraphicsGetCurrentContext()!
if !isRasterizing {
context.setBlendMode(.copy)
context.setFillColor(UIColor.clear.cgColor)
context.fill(bounds)
}
if let parameters = parameters as? LocationBroadcastPanelWavesNodeParams {
let center = CGPoint(x: bounds.width / 2.0, y: bounds.height / 2.0)
let length: CGFloat = 9.0
context.setFillColor(parameters.color.cgColor)
let draw: (CGContext, CGFloat, Bool) -> Void = { context, pos, right in
let path = CGMutablePath()
path.addArc(center: center, radius: length * pos + 7.0, startAngle: right ? degToRad(-26.0) : degToRad(154.0), endAngle: right ? degToRad(26.0) : degToRad(206.0), clockwise: false)
let strokedArc = path.copy(strokingWithWidth: 1.65, lineCap: .round, lineJoin: .miter, miterLimit: 10.0)
context.addPath(strokedArc)
context.fillPath()
}
let position = parameters.progress
var alpha = position / 0.5
if alpha > 1.0 {
alpha = 2.0 - alpha
}
context.setAlpha(alpha * 0.7)
draw(context, position, false)
draw(context, position, true)
var progress = parameters.progress + 0.5
if progress > 1.0 {
progress = progress - 1.0
}
let largerPos = progress
var largerAlpha = largerPos / 0.5
if largerAlpha > 1.0 {
largerAlpha = 2.0 - largerAlpha
}
context.setAlpha(largerAlpha * 0.7)
draw(context, largerPos, false)
draw(context, largerPos, true)
}
}
}

View File

@@ -5,8 +5,6 @@ import SwiftSignalKit
private let titleFont = Font.regular(12.0) private let titleFont = Font.regular(12.0)
private let subtitleFont = Font.regular(10.0) private let subtitleFont = Font.regular(10.0)
private let maximizedTitleFont = Font.bold(17.0)
private let maximizedSubtitleFont = Font.regular(12.0)
final class MediaNavigationAccessoryHeaderNode: ASDisplayNode { final class MediaNavigationAccessoryHeaderNode: ASDisplayNode {
static let minimizedHeight: CGFloat = 37.0 static let minimizedHeight: CGFloat = 37.0

View File

@@ -78,7 +78,8 @@ func openChatMessage(account: Account, message: Message, reverseMessageGalleryOr
present(legacyLocationController(message: message, mapMedia: mapMedia, account: account, openPeer: { peer in present(legacyLocationController(message: message, mapMedia: mapMedia, account: account, openPeer: { peer in
openPeer(peer, .info) openPeer(peer, .info)
}, sendLiveLocation: { coordinate, period in }, sendLiveLocation: { coordinate, period in
let outMessage: EnqueueMessage = .message(text: "", attributes: [], media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, geoPlace: nil, venue: nil, liveBroadcastingTimeout: period), replyToMessageId: nil, localGroupingKey: nil)
let _ = enqueueMessages(account: account, peerId: message.id.peerId, messages: [outMessage]).start()
}, stopLiveLocation: { }, stopLiveLocation: {
account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: message.id.peerId) account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: message.id.peerId)
}), nil) }), nil)

View File

@@ -44,7 +44,7 @@ public class PeerMediaCollectionController: TelegramController {
self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 } self.presentationData = account.telegramApplicationContext.currentPresentationData.with { $0 }
self.interfaceState = PeerMediaCollectionInterfaceState(theme: self.presentationData.theme, strings: self.presentationData.strings) self.interfaceState = PeerMediaCollectionInterfaceState(theme: self.presentationData.theme, strings: self.presentationData.strings)
super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme).withUpdatedSeparatorColor(self.presentationData.theme.rootController.navigationBar.backgroundColor), enableMediaAccessoryPanel: true) super.init(account: account, navigationBarTheme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme).withUpdatedSeparatorColor(self.presentationData.theme.rootController.navigationBar.backgroundColor), enableMediaAccessoryPanel: true, locationBroadcastPanelSource: .none)
self.title = self.presentationData.strings.SharedMedia_TitleAll self.title = self.presentationData.strings.SharedMedia_TitleAll

View File

@@ -19,6 +19,8 @@ enum PresentationResourceKey: Int32 {
case navigationSearchIcon case navigationSearchIcon
case navigationPlayerCloseButton case navigationPlayerCloseButton
case navigationLiveLocationIcon
case navigationPlayerPlayIcon case navigationPlayerPlayIcon
case navigationPlayerPauseIcon case navigationPlayerPauseIcon
case navigationPlayerMaximizedPlayIcon case navigationPlayerMaximizedPlayIcon

View File

@@ -112,6 +112,12 @@ struct PresentationResourcesRootController {
}) })
} }
static func navigationLiveLocationIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.navigationLiveLocationIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat List/LiveLocationPanelIcon"), color: theme.rootController.navigationBar.accentTextColor)
})
}
static func navigationPlayerMaximizedPlayIcon(_ theme: PresentationTheme) -> UIImage? { static func navigationPlayerMaximizedPlayIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.navigationPlayerMaximizedPlayIcon.rawValue, { theme in return theme.image(PresentationResourceKey.navigationPlayerMaximizedPlayIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "GlobalMusicPlayer/Play"), color: theme.rootController.navigationBar.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: "GlobalMusicPlayer/Play"), color: theme.rootController.navigationBar.primaryTextColor)

View File

@@ -6,6 +6,10 @@ public enum PresentationThemeParsingError: Error {
case generic case generic
} }
public final class PresentationThemeColorPlaceholder {
}
public final class PresentationThemeRootTabBar { public final class PresentationThemeRootTabBar {
public let backgroundColor: UIColor public let backgroundColor: UIColor
public let separatorColor: UIColor public let separatorColor: UIColor

View File

@@ -4,16 +4,52 @@ import TelegramCore
import SwiftSignalKit import SwiftSignalKit
import Postbox import Postbox
enum LocationBroadcastPanelSource {
case none
case summary
case peer(PeerId)
}
private func presentLiveLocationController(account: Account, peerId: PeerId, controller: ViewController) {
if let id = account.telegramApplicationContext.liveLocationManager?.internalMessageForPeerId(peerId) {
let _ = (account.postbox.modify { modifier -> Message? in
return modifier.getMessage(id)
} |> deliverOnMainQueue).start(next: { [weak controller] message in
if let message = message, let strongController = controller {
let _ = openChatMessage(account: account, message: message, reverseMessageGalleryOrder: false, navigationController: strongController.navigationController as? NavigationController, dismissInput: {
controller?.view.endEditing(true)
}, present: { c, a in
controller?.present(c, in: .window(.root), with: a)
}, transitionNode: { _, _ in
return nil
}, addToTransitionSurface: { _ in
}, openUrl: { _ in
}, openPeer: { peer, navigation in
}, callPeer: { _ in
}, sendSticker: { _ in
}, setupTemporaryHiddenMedia: { _, _, _ in
})
}
})
}
}
public class TelegramController: ViewController { public class TelegramController: ViewController {
private let account: Account private let account: Account
let enableMediaAccessoryPanel: Bool let enableMediaAccessoryPanel: Bool
let locationBroadcastPanelSource: LocationBroadcastPanelSource
private var mediaStatusDisposable: Disposable? private var mediaStatusDisposable: Disposable?
private var locationBroadcastDisposable: Disposable?
private(set) var playlistStateAndType: (SharedMediaPlaylistItem, MusicPlaybackSettingsOrder, MediaManagerPlayerType)? private(set) var playlistStateAndType: (SharedMediaPlaylistItem, MusicPlaybackSettingsOrder, MediaManagerPlayerType)?
private var mediaAccessoryPanel: (MediaNavigationAccessoryPanel, MediaManagerPlayerType)? private var mediaAccessoryPanel: (MediaNavigationAccessoryPanel, MediaManagerPlayerType)?
private var locationBroadcastMode: LocationBroadcastNavigationAccessoryPanelMode?
private var locationBroadcastPeers: [Peer]?
private var locationBroadcastAccessoryPanel: LocationBroadcastNavigationAccessoryPanel?
private var dismissingPanel: ASDisplayNode? private var dismissingPanel: ASDisplayNode?
override public var navigationHeight: CGFloat { override public var navigationHeight: CGFloat {
@@ -21,17 +57,21 @@ public class TelegramController: ViewController {
if let _ = self.mediaAccessoryPanel { if let _ = self.mediaAccessoryPanel {
height += 36.0 height += 36.0
} }
if let _ = self.locationBroadcastAccessoryPanel {
height += 36.0
}
return height return height
} }
init(account: Account, navigationBarTheme: NavigationBarTheme?, enableMediaAccessoryPanel: Bool) { init(account: Account, navigationBarTheme: NavigationBarTheme?, enableMediaAccessoryPanel: Bool, locationBroadcastPanelSource: LocationBroadcastPanelSource) {
self.account = account self.account = account
self.enableMediaAccessoryPanel = enableMediaAccessoryPanel self.enableMediaAccessoryPanel = enableMediaAccessoryPanel
self.locationBroadcastPanelSource = locationBroadcastPanelSource
super.init(navigationBarTheme: navigationBarTheme) super.init(navigationBarTheme: navigationBarTheme)
if let applicationContext = account.applicationContext as? TelegramApplicationContext { if enableMediaAccessoryPanel {
self.mediaStatusDisposable = (applicationContext.mediaManager.globalMediaPlayerState self.mediaStatusDisposable = (account.telegramApplicationContext.mediaManager.globalMediaPlayerState
|> deliverOnMainQueue).start(next: { [weak self] playlistStateAndType in |> deliverOnMainQueue).start(next: { [weak self] playlistStateAndType in
if let strongSelf = self, strongSelf.enableMediaAccessoryPanel { if let strongSelf = self, strongSelf.enableMediaAccessoryPanel {
if !arePlaylistItemsEqual(strongSelf.playlistStateAndType?.0, playlistStateAndType?.0.item) || if !arePlaylistItemsEqual(strongSelf.playlistStateAndType?.0, playlistStateAndType?.0.item) ||
@@ -46,10 +86,52 @@ public class TelegramController: ViewController {
} }
}) })
} }
if let liveLocationManager = account.telegramApplicationContext.liveLocationManager {
switch locationBroadcastPanelSource {
case .none:
self.locationBroadcastMode = nil
case .summary, .peer:
let signal: Signal<[Peer]?, NoError>
switch locationBroadcastPanelSource {
case let .peer(peerId):
self.locationBroadcastMode = .peer
signal = liveLocationManager.summaryManager.peersBroadcastingTo(peerId: peerId)
default:
self.locationBroadcastMode = .summary
signal = liveLocationManager.summaryManager.broadcastingToPeers()
|> map { $0.isEmpty ? nil : $0 }
}
self.locationBroadcastDisposable = (signal
|> deliverOnMainQueue).start(next: { [weak self] peers in
if let strongSelf = self {
var updated = false
if let current = strongSelf.locationBroadcastPeers, let peers = peers {
updated = !arePeerArraysEqual(current, peers)
} else if (strongSelf.locationBroadcastPeers != nil) != (peers != nil) {
updated = true
}
if updated {
let wasEmpty = strongSelf.locationBroadcastPeers == nil
strongSelf.locationBroadcastPeers = peers
if wasEmpty != (peers == nil) {
strongSelf.requestLayout(transition: .animated(duration: 0.4, curve: .spring))
} else if let peers = peers, let locationBroadcastMode = strongSelf.locationBroadcastMode {
strongSelf.locationBroadcastAccessoryPanel?.update(peers: peers, mode: locationBroadcastMode)
}
}
}
})
}
}
} }
deinit { deinit {
self.mediaStatusDisposable?.dispose() self.mediaStatusDisposable?.dispose()
self.locationBroadcastDisposable?.dispose()
} }
required public init(coder aDecoder: NSCoder) { required public init(coder aDecoder: NSCoder) {
@@ -59,10 +141,148 @@ public class TelegramController: ViewController {
public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { public override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
super.containerLayoutUpdated(layout, transition: transition) super.containerLayoutUpdated(layout, transition: transition)
if let (item, _, type) = self.playlistStateAndType {
let navigationHeight = super.navigationHeight let navigationHeight = super.navigationHeight
var additionalHeight: CGFloat = 0.0
if let locationBroadcastPeers = self.locationBroadcastPeers, let locationBroadcastMode = self.locationBroadcastMode {
let panelHeight = MediaNavigationAccessoryHeaderNode.minimizedHeight let panelHeight = MediaNavigationAccessoryHeaderNode.minimizedHeight
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: navigationHeight.isZero ? -panelHeight : (navigationHeight + UIScreenPixel)), size: CGSize(width: layout.size.width, height: panelHeight)) let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: navigationHeight.isZero ? -panelHeight : (navigationHeight + additionalHeight + UIScreenPixel)), size: CGSize(width: layout.size.width, height: panelHeight))
additionalHeight += panelHeight
let locationBroadcastAccessoryPanel: LocationBroadcastNavigationAccessoryPanel
if let current = self.locationBroadcastAccessoryPanel {
locationBroadcastAccessoryPanel = current
transition.updateFrame(node: locationBroadcastAccessoryPanel, frame: panelFrame)
locationBroadcastAccessoryPanel.updateLayout(size: panelFrame.size, transition: transition)
} else {
let presentationData = self.account.telegramApplicationContext.currentPresentationData.with { $0 }
locationBroadcastAccessoryPanel = LocationBroadcastNavigationAccessoryPanel(theme: presentationData.theme, strings: presentationData.strings, tapAction: { [weak self] in
if let strongSelf = self {
switch strongSelf.locationBroadcastPanelSource {
case .none:
break
case .summary:
if let locationBroadcastPeers = strongSelf.locationBroadcastPeers {
if locationBroadcastPeers.count == 1 {
presentLiveLocationController(account: strongSelf.account, peerId: locationBroadcastPeers[0].id, controller: strongSelf)
} else {
let presentationData = strongSelf.account.telegramApplicationContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
var items: [ActionSheetItem] = []
if !locationBroadcastPeers.isEmpty {
items.append(ActionSheetTextItem(title: presentationData.strings.LiveLocation_MenuChatsCount(Int32(locationBroadcastPeers.count))))
for peer in locationBroadcastPeers {
items.append(ActionSheetButtonItem(title: peer.displayTitle, action: {
dismissAction()
if let strongSelf = self {
presentLiveLocationController(account: strongSelf.account, peerId: peer.id, controller: strongSelf)
}
}))
}
items.append(ActionSheetButtonItem(title: presentationData.strings.LiveLocation_MenuStopAll, color: .destructive, action: {
dismissAction()
for peer in locationBroadcastPeers {
self?.account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: peer.id)
}
}))
}
controller.setItemGroups([
ActionSheetItemGroup(items: items),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
strongSelf.view.endEditing(true)
strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
}
case let .peer(peerId):
presentLiveLocationController(account: strongSelf.account, peerId: peerId, controller: strongSelf)
}
}
}, close: { [weak self] in
if let strongSelf = self {
var closePeers: [Peer]?
var closePeerId: PeerId?
switch strongSelf.locationBroadcastPanelSource {
case .none:
break
case .summary:
if let locationBroadcastPeers = strongSelf.locationBroadcastPeers {
if locationBroadcastPeers.count > 1 {
closePeers = locationBroadcastPeers
} else {
closePeerId = locationBroadcastPeers.first?.id
}
}
case let .peer(peerId):
closePeerId = peerId
}
let presentationData = strongSelf.account.telegramApplicationContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationTheme: presentationData.theme)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
}
var items: [ActionSheetItem] = []
if let closePeers = closePeers, !closePeers.isEmpty {
items.append(ActionSheetTextItem(title: presentationData.strings.LiveLocation_MenuChatsCount(Int32(closePeers.count))))
for peer in closePeers {
items.append(ActionSheetButtonItem(title: peer.displayTitle, action: {
dismissAction()
if let strongSelf = self {
presentLiveLocationController(account: strongSelf.account, peerId: peer.id, controller: strongSelf)
}
}))
}
items.append(ActionSheetButtonItem(title: presentationData.strings.LiveLocation_MenuStopAll, color: .destructive, action: {
dismissAction()
for peer in closePeers {
self?.account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: peer.id)
}
}))
} else if let closePeerId = closePeerId {
items.append(ActionSheetButtonItem(title: presentationData.strings.Map_StopLiveLocation, color: .destructive, action: {
dismissAction()
self?.account.telegramApplicationContext.liveLocationManager?.cancelLiveLocation(peerId: closePeerId)
}))
}
controller.setItemGroups([
ActionSheetItemGroup(items: items),
ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })])
])
strongSelf.view.endEditing(true)
strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
})
if let navigationBar = self.navigationBar {
self.displayNode.insertSubnode(locationBroadcastAccessoryPanel, aboveSubnode: navigationBar)
} else {
self.displayNode.addSubnode(locationBroadcastAccessoryPanel)
}
self.locationBroadcastAccessoryPanel = locationBroadcastAccessoryPanel
locationBroadcastAccessoryPanel.frame = panelFrame
locationBroadcastAccessoryPanel.update(peers: locationBroadcastPeers, mode: locationBroadcastMode)
locationBroadcastAccessoryPanel.updateLayout(size: panelFrame.size, transition: .immediate)
if transition.isAnimated {
locationBroadcastAccessoryPanel.animateIn(transition)
}
}
} else if let locationBroadcastAccessoryPanel = self.locationBroadcastAccessoryPanel {
self.locationBroadcastAccessoryPanel = nil
if transition.isAnimated {
locationBroadcastAccessoryPanel.animateOut(transition, completion: { [weak locationBroadcastAccessoryPanel] in
locationBroadcastAccessoryPanel?.removeFromSupernode()
})
} else {
locationBroadcastAccessoryPanel.removeFromSupernode()
}
}
if let (item, _, type) = self.playlistStateAndType {
let panelHeight = MediaNavigationAccessoryHeaderNode.minimizedHeight
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: navigationHeight.isZero ? -panelHeight : (navigationHeight + additionalHeight + UIScreenPixel)), size: CGSize(width: layout.size.width, height: panelHeight))
if let (mediaAccessoryPanel, mediaType) = self.mediaAccessoryPanel, mediaType == type { if let (mediaAccessoryPanel, mediaType) = self.mediaAccessoryPanel, mediaType == type {
transition.updateFrame(layer: mediaAccessoryPanel.layer, frame: panelFrame) transition.updateFrame(layer: mediaAccessoryPanel.layer, frame: panelFrame)
mediaAccessoryPanel.updateLayout(size: panelFrame.size, transition: transition) mediaAccessoryPanel.updateLayout(size: panelFrame.size, transition: transition)