mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
92d53e6ca6
@ -351,6 +351,7 @@ public final class NavigateToChatControllerParams {
|
||||
public let activateInput: Bool
|
||||
public let keepStack: NavigateToChatKeepStack
|
||||
public let useExisting: Bool
|
||||
public let useBackAnimation: Bool
|
||||
public let purposefulAction: (() -> Void)?
|
||||
public let scrollToEndIfExists: Bool
|
||||
public let activateMessageSearch: (ChatSearchDomain, String)?
|
||||
@ -366,7 +367,7 @@ public final class NavigateToChatControllerParams {
|
||||
public let setupController: (ChatController) -> Void
|
||||
public let completion: (ChatController) -> Void
|
||||
|
||||
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, setupController: @escaping (ChatController) -> Void = { _ in }, completion: @escaping (ChatController) -> Void = { _ in }) {
|
||||
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, useBackAnimation: Bool = false, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, setupController: @escaping (ChatController) -> Void = { _ in }, completion: @escaping (ChatController) -> Void = { _ in }) {
|
||||
self.navigationController = navigationController
|
||||
self.chatController = chatController
|
||||
self.chatLocationContextHolder = chatLocationContextHolder
|
||||
@ -379,6 +380,7 @@ public final class NavigateToChatControllerParams {
|
||||
self.activateInput = activateInput
|
||||
self.keepStack = keepStack
|
||||
self.useExisting = useExisting
|
||||
self.useBackAnimation = useBackAnimation
|
||||
self.purposefulAction = purposefulAction
|
||||
self.scrollToEndIfExists = scrollToEndIfExists
|
||||
self.activateMessageSearch = activateMessageSearch
|
||||
|
@ -160,7 +160,7 @@ class BotCheckoutHeaderItemNode: ListViewItemNode {
|
||||
var imageApply: (() -> Void)?
|
||||
var updatedImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
|
||||
if let photo = item.invoice.photo, let dimensions = photo.dimensions {
|
||||
let arguments = TransformImageArguments(corners: ImageCorners(), imageSize: dimensions.cgSize.aspectFilled(imageSize), boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor)
|
||||
let arguments = TransformImageArguments(corners: ImageCorners(radius: 4.0), imageSize: dimensions.cgSize.aspectFilled(imageSize), boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor)
|
||||
imageApply = makeImageLayout(arguments)
|
||||
maxTextWidth = max(1.0, maxTextWidth - imageSize.width - imageTextSpacing)
|
||||
if imageUpdated {
|
||||
|
@ -352,7 +352,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|
||||
let accountPeer = self.context.account.postbox.loadedPeerWithId(self.context.account.peerId)
|
||||
|> take(1)
|
||||
|
||||
|
||||
self.suggestedFiltersDisposable.set((combineLatest(suggestedPeers, self.suggestedDates.get(), self.selectedFilterPromise.get(), self.searchQuery.get(), accountPeer)
|
||||
|> mapToSignal { peers, dates, selectedFilter, searchQuery, accountPeer -> Signal<([EnginePeer], [(Date?, Date, String?)], ChatListSearchFilterEntryId?, String?, EnginePeer?), NoError> in
|
||||
if searchQuery?.isEmpty ?? true {
|
||||
|
@ -275,6 +275,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
case recentlyDownloaded
|
||||
}
|
||||
|
||||
case recentlySearchedPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder)
|
||||
case localPeer(EnginePeer, EnginePeer?, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType)
|
||||
case globalPeer(FoundPeer, (Int32, Bool)?, Int, PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, ChatListSearchSectionExpandType)
|
||||
case message(EngineMessage, EngineRenderedPeer, EnginePeerReadCounters?, ChatListPresentationData, Int32, Bool?, Bool, MessageOrderingKey, (id: String, size: Int, isFirstInList: Bool)?, MessageSection, Bool)
|
||||
@ -282,126 +283,219 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
|
||||
public var stableId: ChatListSearchEntryStableId {
|
||||
switch self {
|
||||
case let .localPeer(peer, _, _, _, _, _, _, _, _):
|
||||
return .localPeerId(peer.id)
|
||||
case let .globalPeer(peer, _, _, _, _, _, _, _):
|
||||
return .globalPeerId(peer.peer.id)
|
||||
case let .message(message, _, _, _, _, _, _, _, _, section, _):
|
||||
return .messageId(message.id, section)
|
||||
case .addContact:
|
||||
return .addContact
|
||||
case let .recentlySearchedPeer(peer, _, _, _, _, _, _, _):
|
||||
return .localPeerId(peer.id)
|
||||
case let .localPeer(peer, _, _, _, _, _, _, _, _):
|
||||
return .localPeerId(peer.id)
|
||||
case let .globalPeer(peer, _, _, _, _, _, _, _):
|
||||
return .globalPeerId(peer.peer.id)
|
||||
case let .message(message, _, _, _, _, _, _, _, _, section, _):
|
||||
return .messageId(message.id, section)
|
||||
case .addContact:
|
||||
return .addContact
|
||||
}
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatListSearchEntry, rhs: ChatListSearchEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .localPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType):
|
||||
if case let .localPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType {
|
||||
return true
|
||||
} else {
|
||||
case let .recentlySearchedPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder):
|
||||
if case let .recentlySearchedPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .localPeer(lhsPeer, lhsAssociatedPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType):
|
||||
if case let .localPeer(rhsPeer, rhsAssociatedPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType) = rhs, lhsPeer == rhsPeer && lhsAssociatedPeer == rhsAssociatedPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .globalPeer(lhsPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType):
|
||||
if case let .globalPeer(rhsPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .message(lhsMessage, lhsPeer, lhsCombinedPeerReadState, lhsPresentationData, lhsTotalCount, lhsSelected, lhsDisplayCustomHeader, lhsKey, lhsResourceId, lhsSection, lhsAllPaused):
|
||||
if case let .message(rhsMessage, rhsPeer, rhsCombinedPeerReadState, rhsPresentationData, rhsTotalCount, rhsSelected, rhsDisplayCustomHeader, rhsKey, rhsResourceId, rhsSection, rhsAllPaused) = rhs {
|
||||
if lhsMessage.id != rhsMessage.id {
|
||||
return false
|
||||
}
|
||||
case let .globalPeer(lhsPeer, lhsUnreadBadge, lhsIndex, lhsTheme, lhsStrings, lhsSortOrder, lhsDisplayOrder, lhsExpandType):
|
||||
if case let .globalPeer(rhsPeer, rhsUnreadBadge, rhsIndex, rhsTheme, rhsStrings, rhsSortOrder, rhsDisplayOrder, rhsExpandType) = rhs, lhsPeer == rhsPeer && lhsIndex == rhsIndex && lhsTheme === rhsTheme && lhsStrings === rhsStrings && lhsSortOrder == rhsSortOrder && lhsDisplayOrder == rhsDisplayOrder && lhsUnreadBadge?.0 == rhsUnreadBadge?.0 && lhsUnreadBadge?.1 == rhsUnreadBadge?.1 && lhsExpandType == rhsExpandType {
|
||||
return true
|
||||
} else {
|
||||
if lhsMessage.stableVersion != rhsMessage.stableVersion {
|
||||
return false
|
||||
}
|
||||
case let .message(lhsMessage, lhsPeer, lhsCombinedPeerReadState, lhsPresentationData, lhsTotalCount, lhsSelected, lhsDisplayCustomHeader, lhsKey, lhsResourceId, lhsSection, lhsAllPaused):
|
||||
if case let .message(rhsMessage, rhsPeer, rhsCombinedPeerReadState, rhsPresentationData, rhsTotalCount, rhsSelected, rhsDisplayCustomHeader, rhsKey, rhsResourceId, rhsSection, rhsAllPaused) = rhs {
|
||||
if lhsMessage.id != rhsMessage.id {
|
||||
return false
|
||||
}
|
||||
if lhsMessage.stableVersion != rhsMessage.stableVersion {
|
||||
return false
|
||||
}
|
||||
if lhsPeer != rhsPeer {
|
||||
return false
|
||||
}
|
||||
if lhsPresentationData !== rhsPresentationData {
|
||||
return false
|
||||
}
|
||||
if lhsCombinedPeerReadState != rhsCombinedPeerReadState {
|
||||
return false
|
||||
}
|
||||
if lhsTotalCount != rhsTotalCount {
|
||||
return false
|
||||
}
|
||||
if lhsSelected != rhsSelected {
|
||||
return false
|
||||
}
|
||||
if lhsDisplayCustomHeader != rhsDisplayCustomHeader {
|
||||
return false
|
||||
}
|
||||
if lhsKey != rhsKey {
|
||||
return false
|
||||
}
|
||||
if lhsResourceId?.0 != rhsResourceId?.0 {
|
||||
return false
|
||||
}
|
||||
if lhsResourceId?.1 != rhsResourceId?.1 {
|
||||
return false
|
||||
}
|
||||
if lhsSection != rhsSection {
|
||||
return false
|
||||
}
|
||||
if lhsAllPaused != rhsAllPaused {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
if lhsPeer != rhsPeer {
|
||||
return false
|
||||
}
|
||||
case let .addContact(lhsPhoneNumber, lhsTheme, lhsStrings):
|
||||
if case let .addContact(rhsPhoneNumber, rhsTheme, rhsStrings) = rhs {
|
||||
if lhsPhoneNumber != rhsPhoneNumber {
|
||||
return false
|
||||
}
|
||||
if lhsTheme !== rhsTheme {
|
||||
return false
|
||||
}
|
||||
if lhsStrings !== rhsStrings {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
if lhsPresentationData !== rhsPresentationData {
|
||||
return false
|
||||
}
|
||||
if lhsCombinedPeerReadState != rhsCombinedPeerReadState {
|
||||
return false
|
||||
}
|
||||
if lhsTotalCount != rhsTotalCount {
|
||||
return false
|
||||
}
|
||||
if lhsSelected != rhsSelected {
|
||||
return false
|
||||
}
|
||||
if lhsDisplayCustomHeader != rhsDisplayCustomHeader {
|
||||
return false
|
||||
}
|
||||
if lhsKey != rhsKey {
|
||||
return false
|
||||
}
|
||||
if lhsResourceId?.0 != rhsResourceId?.0 {
|
||||
return false
|
||||
}
|
||||
if lhsResourceId?.1 != rhsResourceId?.1 {
|
||||
return false
|
||||
}
|
||||
if lhsSection != rhsSection {
|
||||
return false
|
||||
}
|
||||
if lhsAllPaused != rhsAllPaused {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .addContact(lhsPhoneNumber, lhsTheme, lhsStrings):
|
||||
if case let .addContact(rhsPhoneNumber, rhsTheme, rhsStrings) = rhs {
|
||||
if lhsPhoneNumber != rhsPhoneNumber {
|
||||
return false
|
||||
}
|
||||
if lhsTheme !== rhsTheme {
|
||||
return false
|
||||
}
|
||||
if lhsStrings !== rhsStrings {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func <(lhs: ChatListSearchEntry, rhs: ChatListSearchEntry) -> Bool {
|
||||
switch lhs {
|
||||
case let .localPeer(_, _, _, lhsIndex, _, _, _, _, _):
|
||||
if case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _) = rhs {
|
||||
return lhsIndex <= rhsIndex
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
case let .globalPeer(_, _, lhsIndex, _, _, _, _, _):
|
||||
switch rhs {
|
||||
case .localPeer:
|
||||
return false
|
||||
case let .globalPeer(_, _, rhsIndex, _, _, _, _, _):
|
||||
return lhsIndex <= rhsIndex
|
||||
case .message, .addContact:
|
||||
return true
|
||||
}
|
||||
case let .message(_, _, _, _, _, _, _, lhsKey, _, _, _):
|
||||
if case let .message(_, _, _, _, _, _, _, rhsKey, _, _, _) = rhs {
|
||||
return lhsKey < rhsKey
|
||||
} else if case .addContact = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .addContact:
|
||||
case let .recentlySearchedPeer(_, _, _, lhsIndex, _, _, _, _):
|
||||
if case let .recentlySearchedPeer(_, _, _, rhsIndex, _, _, _, _) = rhs {
|
||||
return lhsIndex <= rhsIndex
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
case let .localPeer(_, _, _, lhsIndex, _, _, _, _, _):
|
||||
switch rhs {
|
||||
case .recentlySearchedPeer:
|
||||
return false
|
||||
case let .localPeer(_, _, _, rhsIndex, _, _, _, _, _):
|
||||
return lhsIndex <= rhsIndex
|
||||
case .globalPeer, .message, .addContact:
|
||||
return true
|
||||
}
|
||||
case let .globalPeer(_, _, lhsIndex, _, _, _, _, _):
|
||||
switch rhs {
|
||||
case .recentlySearchedPeer, .localPeer:
|
||||
return false
|
||||
case let .globalPeer(_, _, rhsIndex, _, _, _, _, _):
|
||||
return lhsIndex <= rhsIndex
|
||||
case .message, .addContact:
|
||||
return true
|
||||
}
|
||||
case let .message(_, _, _, _, _, _, _, lhsKey, _, _, _):
|
||||
if case let .message(_, _, _, _, _, _, _, rhsKey, _, _, _) = rhs {
|
||||
return lhsKey < rhsKey
|
||||
} else if case .addContact = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case .addContact:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, key: ChatListSearchPaneKey, tagMask: EngineMessage.Tags?, interaction: ChatListNodeInteraction, listInteraction: ListMessageItemInteraction, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, toggleExpandLocalResults: @escaping () -> Void, toggleExpandGlobalResults: @escaping () -> Void, searchPeer: @escaping (EnginePeer) -> Void, searchQuery: String?, searchOptions: ChatListSearchOptions?, messageContextAction: ((EngineMessage, ASDisplayNode?, CGRect?, UIGestureRecognizer?, ChatListSearchPaneKey, (id: String, size: Int, isFirstInList: Bool)?) -> Void)?, openClearRecentlyDownloaded: @escaping () -> Void, toggleAllPaused: @escaping () -> Void) -> ListViewItem {
|
||||
switch self {
|
||||
case let .recentlySearchedPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder):
|
||||
let primaryPeer: EnginePeer
|
||||
var chatPeer: EnginePeer?
|
||||
if let associatedPeer = associatedPeer {
|
||||
primaryPeer = associatedPeer
|
||||
chatPeer = peer
|
||||
} else {
|
||||
primaryPeer = peer
|
||||
chatPeer = peer
|
||||
}
|
||||
|
||||
var enabled = true
|
||||
if filter.contains(.onlyWriteable) {
|
||||
if let peer = chatPeer {
|
||||
enabled = canSendMessagesToPeer(peer._asPeer())
|
||||
} else {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
if filter.contains(.onlyPrivateChats) {
|
||||
if let peer = chatPeer {
|
||||
switch peer {
|
||||
case .user, .secretChat:
|
||||
break
|
||||
default:
|
||||
enabled = false
|
||||
}
|
||||
} else {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
if filter.contains(.onlyGroups) {
|
||||
if let peer = chatPeer {
|
||||
if case .legacyGroup = peer {
|
||||
} else if case let .channel(peer) = peer, case .group = peer.info {
|
||||
} else {
|
||||
enabled = false
|
||||
}
|
||||
} else {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
var badge: ContactsPeerItemBadge?
|
||||
if let unreadBadge = unreadBadge {
|
||||
badge = ContactsPeerItemBadge(count: unreadBadge.0, type: unreadBadge.1 ? .inactive : .active)
|
||||
}
|
||||
|
||||
let header: ChatListSearchItemHeader?
|
||||
if filter.contains(.removeSearchHeader) {
|
||||
header = nil
|
||||
} else {
|
||||
let headerType: ChatListSearchItemHeaderType
|
||||
if filter.contains(.onlyGroups) {
|
||||
headerType = .chats
|
||||
} else {
|
||||
headerType = .recentPeers
|
||||
}
|
||||
header = ChatListSearchItemHeader(type: headerType, theme: theme, strings: strings, actionTitle: nil, action: nil)
|
||||
}
|
||||
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .generalSearch, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { contactPeer in
|
||||
if case let .peer(maybePeer, maybeChatPeer) = contactPeer, let peer = maybePeer, let chatPeer = maybeChatPeer {
|
||||
interaction.peerSelected(chatPeer, peer, nil)
|
||||
} else {
|
||||
interaction.peerSelected(peer, nil, nil)
|
||||
}
|
||||
}, contextAction: peerContextAction.flatMap { peerContextAction in
|
||||
return { node, gesture in
|
||||
if let chatPeer = chatPeer, chatPeer.id.namespace != Namespaces.Peer.SecretChat {
|
||||
peerContextAction(chatPeer, .search(nil), node, gesture)
|
||||
} else {
|
||||
gesture?.cancel()
|
||||
}
|
||||
}
|
||||
}, arrowAction: nil)
|
||||
case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder, expandType):
|
||||
let primaryPeer: EnginePeer
|
||||
var chatPeer: EnginePeer?
|
||||
@ -1089,27 +1183,53 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}
|
||||
|
||||
let accountPeer = context.account.postbox.loadedPeerWithId(context.account.peerId) |> take(1)
|
||||
let foundLocalPeers: Signal<(peers: [EngineRenderedPeer], unread: [EnginePeer.Id: (Int32, Bool)]), NoError>
|
||||
let foundLocalPeers: Signal<(peers: [EngineRenderedPeer], unread: [EnginePeer.Id: (Int32, Bool)], recentlySearchedPeerIds: Set<EnginePeer.Id>), NoError>
|
||||
if let query = query {
|
||||
foundLocalPeers = context.engine.contacts.searchLocalPeers(query: query.lowercased())
|
||||
|> mapToSignal { local -> Signal<([EnginePeer.Id: Optional<EnginePeer.NotificationSettings>], [EnginePeer.Id: Int], [EngineRenderedPeer]), NoError> in
|
||||
foundLocalPeers = combineLatest(
|
||||
context.engine.contacts.searchLocalPeers(query: query.lowercased()),
|
||||
context.engine.peers.recentlySearchedPeers()
|
||||
)
|
||||
|> mapToSignal { local, allRecentlySearched -> Signal<([EnginePeer.Id: Optional<EnginePeer.NotificationSettings>], [EnginePeer.Id: Int], [EngineRenderedPeer], Set<EnginePeer.Id>), NoError> in
|
||||
let recentlySearched = allRecentlySearched.filter { peer in
|
||||
guard let peer = peer.peer.peer else {
|
||||
return false
|
||||
}
|
||||
return peer.indexName.matchesByTokens(query)
|
||||
}
|
||||
|
||||
var peerIds = Set<EnginePeer.Id>()
|
||||
|
||||
var peers: [EngineRenderedPeer] = []
|
||||
for peer in recentlySearched {
|
||||
if !peerIds.contains(peer.peer.peerId) {
|
||||
peerIds.insert(peer.peer.peerId)
|
||||
peers.append(EngineRenderedPeer(peer.peer))
|
||||
}
|
||||
}
|
||||
for peer in local {
|
||||
if !peerIds.contains(peer.peerId) {
|
||||
peerIds.insert(peer.peerId)
|
||||
peers.append(peer)
|
||||
}
|
||||
}
|
||||
|
||||
return context.engine.data.subscribe(
|
||||
EngineDataMap(
|
||||
local.map { peer -> TelegramEngine.EngineData.Item.Peer.NotificationSettings in
|
||||
return TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peer.peerId)
|
||||
peerIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.NotificationSettings in
|
||||
return TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peerId)
|
||||
}
|
||||
),
|
||||
EngineDataMap(
|
||||
local.map { peer -> TelegramEngine.EngineData.Item.Messages.PeerUnreadCount in
|
||||
return TelegramEngine.EngineData.Item.Messages.PeerUnreadCount(id: peer.peerId)
|
||||
peerIds.map { peerId -> TelegramEngine.EngineData.Item.Messages.PeerUnreadCount in
|
||||
return TelegramEngine.EngineData.Item.Messages.PeerUnreadCount(id: peerId)
|
||||
}
|
||||
)
|
||||
)
|
||||
|> map { notificationSettings, unreadCounts in
|
||||
return (notificationSettings, unreadCounts, local)
|
||||
return (notificationSettings, unreadCounts, peers, Set(recentlySearched.map(\.peer.peerId)))
|
||||
}
|
||||
}
|
||||
|> map { notificationSettings, unreadCounts, peers -> (peers: [EngineRenderedPeer], unread: [EnginePeer.Id: (Int32, Bool)]) in
|
||||
|> map { notificationSettings, unreadCounts, peers, recentlySearchedPeerIds -> (peers: [EngineRenderedPeer], unread: [EnginePeer.Id: (Int32, Bool)], recentlySearchedPeerIds: Set<EnginePeer.Id>) in
|
||||
var unread: [EnginePeer.Id: (Int32, Bool)] = [:]
|
||||
for peer in peers {
|
||||
var isMuted: Bool = false
|
||||
@ -1127,10 +1247,10 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
unread[peer.peerId] = (Int32(unreadCount), isMuted)
|
||||
}
|
||||
}
|
||||
return (peers: peers, unread: unread)
|
||||
return (peers: peers, unread: unread, recentlySearchedPeerIds: recentlySearchedPeerIds)
|
||||
}
|
||||
} else {
|
||||
foundLocalPeers = .single((peers: [], unread: [:]))
|
||||
foundLocalPeers = .single((peers: [], unread: [:], recentlySearchedPeerIds: Set()))
|
||||
}
|
||||
|
||||
let foundRemotePeers: Signal<([FoundPeer], [FoundPeer], Bool), NoError>
|
||||
@ -1319,6 +1439,26 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}
|
||||
}
|
||||
|
||||
for renderedPeer in foundLocalPeers.peers {
|
||||
if !foundLocalPeers.recentlySearchedPeerIds.contains(renderedPeer.peerId) {
|
||||
continue
|
||||
}
|
||||
|
||||
if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != context.account.peerId, filteredPeer(peer, EnginePeer(accountPeer)) {
|
||||
if !existingPeerIds.contains(peer.id) {
|
||||
existingPeerIds.insert(peer.id)
|
||||
var associatedPeer: EnginePeer?
|
||||
if case let .secretChat(secretChat) = peer, let associatedPeerId = secretChat.associatedPeerId {
|
||||
associatedPeer = renderedPeer.peers[associatedPeerId]
|
||||
}
|
||||
|
||||
entries.append(.recentlySearchedPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder))
|
||||
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if lowercasedQuery.count > 1 {
|
||||
for peer in recentPeers {
|
||||
if let peer = peer.peer.chatMainPeer, !existingPeerIds.contains(peer.id) {
|
||||
@ -1348,6 +1488,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
if case .expand = localExpandType, numberOfLocalPeers >= 3 {
|
||||
break
|
||||
}
|
||||
if foundLocalPeers.recentlySearchedPeerIds.contains(renderedPeer.peerId) {
|
||||
continue
|
||||
}
|
||||
|
||||
if let peer = renderedPeer.peers[renderedPeer.peerId], peer.id != context.account.peerId, filteredPeer(peer, EnginePeer(accountPeer)) {
|
||||
if !existingPeerIds.contains(peer.id) {
|
||||
@ -1356,6 +1499,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
if case let .secretChat(secretChat) = peer, let associatedPeerId = secretChat.associatedPeerId {
|
||||
associatedPeer = renderedPeer.peers[associatedPeerId]
|
||||
}
|
||||
|
||||
entries.append(.localPeer(peer, associatedPeer, foundLocalPeers.unread[peer.id], index, presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder, localExpandType))
|
||||
index += 1
|
||||
numberOfLocalPeers += 1
|
||||
|
@ -1274,6 +1274,12 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
completion()
|
||||
}
|
||||
|
||||
public func replaceControllers(controllers: [UIViewController], animated: Bool, options: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
|
||||
ready?.set(true)
|
||||
self.setViewControllers(controllers, animated: animated)
|
||||
completion()
|
||||
}
|
||||
|
||||
public func replaceAllButRootController(_ controller: ViewController, animated: Bool, animationOptions: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
|
||||
ready?.set(true)
|
||||
var controllers = self.viewControllers
|
||||
|
@ -33,6 +33,8 @@
|
||||
#import <MtProtoKit/MTSerialization.h>
|
||||
#import <MtProtoKit/MTEncryption.h>
|
||||
|
||||
#import <MtProtoKit/MTTimer.h>
|
||||
|
||||
#import "MTBuffer.h"
|
||||
#import "MTInternalMessageParser.h"
|
||||
#import "MTMsgContainerMessage.h"
|
||||
@ -125,6 +127,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
|
||||
bool _isProbing;
|
||||
MTMetaDisposable *_probingDisposable;
|
||||
NSNumber *_probingStatus;
|
||||
|
||||
bool _isConnectionThrottled;
|
||||
MTTimer *_unthrottleConnectionTimer;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -625,8 +630,9 @@ static const NSUInteger MTMaxUnacknowledgedMessageCount = 64;
|
||||
{
|
||||
_willRequestTransactionOnNextQueuePass = false;
|
||||
|
||||
if ([self isStopped] || [self isPaused])
|
||||
if ([self isStopped] || [self isPaused] || _isConnectionThrottled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_transport == nil)
|
||||
[self resetTransport];
|
||||
@ -1940,8 +1946,6 @@ static NSString *dumpHexString(NSData *data, int maxLength) {
|
||||
|
||||
id currentTransport = _transport;
|
||||
|
||||
[self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]];
|
||||
|
||||
for (NSInteger i = (NSInteger)_messageServices.count - 1; i >= 0; i--)
|
||||
{
|
||||
id<MTMessageService> messageService = _messageServices[(NSUInteger)i];
|
||||
@ -1954,8 +1958,28 @@ static NSString *dumpHexString(NSData *data, int maxLength) {
|
||||
[self handleMissingKey:scheme];
|
||||
}
|
||||
|
||||
if (currentTransport == _transport)
|
||||
[self requestSecureTransportReset];
|
||||
if (protocolErrorCode == -429) {
|
||||
_isConnectionThrottled = true;
|
||||
if (_unthrottleConnectionTimer == nil) {
|
||||
__weak MTProto *weakSelf = self;
|
||||
_unthrottleConnectionTimer = [[MTTimer alloc] initWithTimeout:5.0 repeat:false completion:^{
|
||||
__strong MTProto *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
strongSelf->_isConnectionThrottled = false;
|
||||
strongSelf->_unthrottleConnectionTimer = nil;
|
||||
[strongSelf requestTransportTransaction];
|
||||
} queue:[MTProto managerQueue].nativeQueue];
|
||||
}
|
||||
} else {
|
||||
if (currentTransport == _transport) {
|
||||
[self requestSecureTransportReset];
|
||||
}
|
||||
|
||||
[self transportTransactionsMayHaveFailed:transport transactionIds:@[transactionId]];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -110,9 +110,11 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.contentContainer.addSubnode(self.scrollNode)
|
||||
|
||||
self.contentContainerMask = UIImageView()
|
||||
let maskGradientWidth: CGFloat = 10.0
|
||||
self.contentContainerMask.image = generateImage(CGSize(width: maskGradientWidth * 2.0 + 1.0, height: 8.0), rotatedContext: { size, context in
|
||||
self.contentContainerMask.image = generateImage(CGSize(width: 52.0, height: 52.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.translateBy(x: size.width / 2.0, y: size.height / 2.0)
|
||||
context.scaleBy(x: 1.0, y: 1.1)
|
||||
context.translateBy(x: -size.width / 2.0, y: -size.height / 2.0)
|
||||
|
||||
let shadowColor = UIColor.black
|
||||
|
||||
@ -122,17 +124,21 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
for i in 0 ... stepCount {
|
||||
let t = CGFloat(i) / CGFloat(stepCount)
|
||||
colors.append(shadowColor.withAlphaComponent(t * t).cgColor)
|
||||
colors.append(shadowColor.withAlphaComponent(t).cgColor)
|
||||
locations.append(t)
|
||||
}
|
||||
|
||||
let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colors as CFArray, locations: &locations)!
|
||||
context.drawLinearGradient(gradient, start: CGPoint(), end: CGPoint(x: maskGradientWidth, y: 0.0), options: CGGradientDrawingOptions())
|
||||
context.drawLinearGradient(gradient, start: CGPoint(x: size.width, y: 0.0), end: CGPoint(x: maskGradientWidth + 1.0, y: 0.0), options: CGGradientDrawingOptions())
|
||||
|
||||
let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
|
||||
let gradientWidth = 6.0
|
||||
context.drawRadialGradient(gradient, startCenter: center, startRadius: size.width / 2.0, endCenter: center, endRadius: size.width / 2.0 - gradientWidth, options: [])
|
||||
|
||||
context.setFillColor(shadowColor.cgColor)
|
||||
context.fill(CGRect(origin: CGPoint(x: maskGradientWidth, y: 0.0), size: CGSize(width: 1.0, height: size.height)))
|
||||
})?.stretchableImage(withLeftCapWidth: Int(maskGradientWidth), topCapHeight: 0)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: gradientWidth - 1.0, dy: gradientWidth - 1.0))
|
||||
})?.stretchableImage(withLeftCapWidth: Int(52.0 / 2.0), topCapHeight: Int(52.0 / 2.0))
|
||||
self.contentContainer.view.mask = self.contentContainerMask
|
||||
//self.contentContainer.view.addSubview(self.contentContainerMask)
|
||||
|
||||
super.init()
|
||||
|
||||
|
@ -567,6 +567,8 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
|
||||
private var scheduledDismissUITimer: SwiftSignalKit.Timer?
|
||||
|
||||
let deactivatePictureInPictureIfVisible = StoredActionSlot(Void.self)
|
||||
|
||||
init(call: PresentationGroupCallImpl) {
|
||||
self.call = call
|
||||
|
||||
@ -639,8 +641,6 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
}
|
||||
})
|
||||
|
||||
//let _ = call.accountContext.engine.calls.getGroupCallStreamCredentials(peerId: call.peerId, revokePreviousCredentials: false).start()
|
||||
|
||||
self.isVisibleInHierarchyDisposable = (call.accountContext.sharedContext.applicationBindings.applicationInForeground
|
||||
|> deliverOnMainQueue).start(next: { [weak self] inForeground in
|
||||
guard let strongSelf = self else {
|
||||
@ -649,6 +649,16 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
if strongSelf.isVisibleInHierarchy != inForeground {
|
||||
strongSelf.isVisibleInHierarchy = inForeground
|
||||
strongSelf.updated(transition: .immediate)
|
||||
|
||||
if inForeground {
|
||||
Queue.mainQueue().after(0.5, {
|
||||
guard let strongSelf = self, strongSelf.isVisibleInHierarchy else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.deactivatePictureInPictureIfVisible.invoke(Void())
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -705,6 +715,7 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
let toolbar = Child(ToolbarComponent.self)
|
||||
|
||||
let activatePictureInPicture = StoredActionSlot(Action<Void>.self)
|
||||
let deactivatePictureInPicture = StoredActionSlot(Void.self)
|
||||
let moreButtonTag = GenericComponentViewTag()
|
||||
let moreAnimationTag = GenericComponentViewTag()
|
||||
|
||||
@ -725,6 +736,16 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
let state = context.state
|
||||
let controller = environment.controller
|
||||
|
||||
context.state.deactivatePictureInPictureIfVisible.connect {
|
||||
guard let controller = controller() else {
|
||||
return
|
||||
}
|
||||
if controller.view.window == nil {
|
||||
return
|
||||
}
|
||||
deactivatePictureInPicture.invoke(Void())
|
||||
}
|
||||
|
||||
let video = video.update(
|
||||
component: MediaStreamVideoComponent(
|
||||
call: context.component.call,
|
||||
@ -733,6 +754,7 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
isAdmin: context.state.canManageCall,
|
||||
peerTitle: context.state.peerTitle,
|
||||
activatePictureInPicture: activatePictureInPicture,
|
||||
deactivatePictureInPicture: deactivatePictureInPicture,
|
||||
bringBackControllerForPictureInPictureDeactivation: { [weak call] completed in
|
||||
guard let call = call else {
|
||||
completed()
|
||||
@ -742,6 +764,9 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
call.accountContext.sharedContext.mainWindow?.inCallNavigate?()
|
||||
|
||||
completed()
|
||||
},
|
||||
pictureInPictureClosed: { [weak call] in
|
||||
let _ = call?.leave(terminateIfPossible: false)
|
||||
}
|
||||
),
|
||||
availableSize: context.availableSize,
|
||||
@ -1095,8 +1120,13 @@ public final class MediaStreamComponent: CombinedComponent {
|
||||
state.updateDismissOffset(value: offset.y, interactive: true)
|
||||
case let .ended(velocity):
|
||||
if abs(velocity.y) > 200.0 {
|
||||
state.updateDismissOffset(value: velocity.y < 0 ? -height : height, interactive: false)
|
||||
(controller() as? MediaStreamComponentController)?.dismiss(closing: false, manual: true)
|
||||
activatePictureInPicture.invoke(Action { [weak state] in
|
||||
guard let state = state, let controller = controller() as? MediaStreamComponentController else {
|
||||
return
|
||||
}
|
||||
state.updateDismissOffset(value: velocity.y < 0 ? -height : height, interactive: false)
|
||||
controller.dismiss(closing: false, manual: true)
|
||||
})
|
||||
} else {
|
||||
state.updateDismissOffset(value: 0.0, interactive: false)
|
||||
}
|
||||
|
@ -14,16 +14,30 @@ final class MediaStreamVideoComponent: Component {
|
||||
let isAdmin: Bool
|
||||
let peerTitle: String
|
||||
let activatePictureInPicture: ActionSlot<Action<Void>>
|
||||
let deactivatePictureInPicture: ActionSlot<Void>
|
||||
let bringBackControllerForPictureInPictureDeactivation: (@escaping () -> Void) -> Void
|
||||
let pictureInPictureClosed: () -> Void
|
||||
|
||||
init(call: PresentationGroupCallImpl, hasVideo: Bool, isVisible: Bool, isAdmin: Bool, peerTitle: String, activatePictureInPicture: ActionSlot<Action<Void>>, bringBackControllerForPictureInPictureDeactivation: @escaping (@escaping () -> Void) -> Void) {
|
||||
init(
|
||||
call: PresentationGroupCallImpl,
|
||||
hasVideo: Bool,
|
||||
isVisible: Bool,
|
||||
isAdmin: Bool,
|
||||
peerTitle: String,
|
||||
activatePictureInPicture: ActionSlot<Action<Void>>,
|
||||
deactivatePictureInPicture: ActionSlot<Void>,
|
||||
bringBackControllerForPictureInPictureDeactivation: @escaping (@escaping () -> Void) -> Void,
|
||||
pictureInPictureClosed: @escaping () -> Void
|
||||
) {
|
||||
self.call = call
|
||||
self.hasVideo = hasVideo
|
||||
self.isVisible = isVisible
|
||||
self.isAdmin = isAdmin
|
||||
self.peerTitle = peerTitle
|
||||
self.activatePictureInPicture = activatePictureInPicture
|
||||
self.deactivatePictureInPicture = deactivatePictureInPicture
|
||||
self.bringBackControllerForPictureInPictureDeactivation = bringBackControllerForPictureInPictureDeactivation
|
||||
self.pictureInPictureClosed = pictureInPictureClosed
|
||||
}
|
||||
|
||||
public static func ==(lhs: MediaStreamVideoComponent, rhs: MediaStreamVideoComponent) -> Bool {
|
||||
@ -72,6 +86,8 @@ final class MediaStreamVideoComponent: Component {
|
||||
private var component: MediaStreamVideoComponent?
|
||||
private var hadVideo: Bool = false
|
||||
|
||||
private var requestedExpansion: Bool = false
|
||||
|
||||
private var noSignalTimer: Timer?
|
||||
private var noSignalTimeout: Bool = false
|
||||
|
||||
@ -101,7 +117,10 @@ final class MediaStreamVideoComponent: Component {
|
||||
}
|
||||
|
||||
func expandFromPictureInPicture() {
|
||||
self.pictureInPictureController?.stopPictureInPicture()
|
||||
if let pictureInPictureController = self.pictureInPictureController, pictureInPictureController.isPictureInPictureActive {
|
||||
self.requestedExpansion = true
|
||||
self.pictureInPictureController?.stopPictureInPicture()
|
||||
}
|
||||
}
|
||||
|
||||
func update(component: MediaStreamVideoComponent, availableSize: CGSize, state: State, transition: Transition) -> CGSize {
|
||||
@ -290,6 +309,14 @@ final class MediaStreamVideoComponent: Component {
|
||||
completion(Void())
|
||||
}
|
||||
|
||||
component.deactivatePictureInPicture.connect { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.expandFromPictureInPicture()
|
||||
}
|
||||
|
||||
return availableSize
|
||||
}
|
||||
|
||||
@ -308,6 +335,14 @@ final class MediaStreamVideoComponent: Component {
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
|
||||
func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
||||
if self.requestedExpansion {
|
||||
self.requestedExpansion = false
|
||||
} else {
|
||||
self.component?.pictureInPictureClosed()
|
||||
}
|
||||
}
|
||||
|
||||
func pictureInPictureControllerDidStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
|
||||
self.state?.updated(transition: .immediate)
|
||||
}
|
||||
|
@ -8861,7 +8861,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
updatedChatNavigationStack.removeSubrange(0 ..< (index + 1))
|
||||
}
|
||||
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), animated: true, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(id: peer.id), useBackAnimation: true, animated: true, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in
|
||||
let _ = nextController
|
||||
}))
|
||||
})))
|
||||
|
@ -122,9 +122,16 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
params.completion(controller)
|
||||
})
|
||||
} else {
|
||||
params.navigationController.replaceControllersAndPush(controllers: viewControllers, controller: controller, animated: params.animated, options: params.options, completion: {
|
||||
params.completion(controller)
|
||||
})
|
||||
if params.useBackAnimation {
|
||||
params.navigationController.viewControllers = [controller] + params.navigationController.viewControllers
|
||||
params.navigationController.replaceControllers(controllers: viewControllers + [controller], animated: params.animated, options: params.options, completion: {
|
||||
params.completion(controller)
|
||||
})
|
||||
} else {
|
||||
params.navigationController.replaceControllersAndPush(controllers: viewControllers, controller: controller, animated: params.animated, options: params.options, completion: {
|
||||
params.completion(controller)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
if params.activateInput {
|
||||
|
Loading…
x
Reference in New Issue
Block a user