mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
[WIP] Saved messages
This commit is contained in:
parent
4651c39083
commit
0e75f18f14
@ -758,7 +758,13 @@ public enum ChatControllerSubject: Equatable {
|
||||
}
|
||||
|
||||
public enum ChatControllerPresentationMode: Equatable {
|
||||
case standard(previewing: Bool)
|
||||
public enum StandardPresentation {
|
||||
case `default`
|
||||
case previewing
|
||||
case embedded
|
||||
}
|
||||
|
||||
case standard(StandardPresentation)
|
||||
case overlay(NavigationController?)
|
||||
case inline(NavigationController?)
|
||||
}
|
||||
|
@ -737,7 +737,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
self.makeEntityInputView = makeEntityInputView
|
||||
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: chatLocation ?? .peer(id: context.account.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(.default), chatLocation: chatLocation ?? .peer(id: context.account.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
|
||||
self.containerNode = ASDisplayNode()
|
||||
self.containerNode.clipsToBounds = true
|
||||
|
@ -92,6 +92,8 @@ private func calculateColors(context: AccountContext?, explicitColorIndex: Int?,
|
||||
colors = AvatarNode.repostColors
|
||||
} else if case .repliesIcon = icon {
|
||||
colors = AvatarNode.savedMessagesColors
|
||||
} else if case .anonymousSavedMessagesIcon = icon {
|
||||
colors = AvatarNode.savedMessagesColors
|
||||
} else if case .editAvatarIcon = icon, let theme {
|
||||
colors = [theme.list.itemAccentColor.withAlphaComponent(0.1), theme.list.itemAccentColor.withAlphaComponent(0.1)]
|
||||
} else if case let .archivedChatsIcon(hiddenByDefault) = icon, let theme = theme {
|
||||
@ -172,6 +174,7 @@ private enum AvatarNodeIcon: Equatable {
|
||||
case none
|
||||
case savedMessagesIcon
|
||||
case repliesIcon
|
||||
case anonymousSavedMessagesIcon
|
||||
case archivedChatsIcon(hiddenByDefault: Bool)
|
||||
case editAvatarIcon
|
||||
case deletedIcon
|
||||
@ -184,6 +187,7 @@ public enum AvatarNodeImageOverride: Equatable {
|
||||
case image(TelegramMediaImageRepresentation)
|
||||
case savedMessagesIcon
|
||||
case repliesIcon
|
||||
case anonymousSavedMessagesIcon
|
||||
case archivedChatsIcon(hiddenByDefault: Bool)
|
||||
case editAvatarIcon(forceNone: Bool)
|
||||
case deletedIcon
|
||||
@ -484,6 +488,9 @@ public final class AvatarNode: ASDisplayNode {
|
||||
case .repliesIcon:
|
||||
representation = nil
|
||||
icon = .repliesIcon
|
||||
case .anonymousSavedMessagesIcon:
|
||||
representation = nil
|
||||
icon = .anonymousSavedMessagesIcon
|
||||
case let .archivedChatsIcon(hiddenByDefault):
|
||||
representation = nil
|
||||
icon = .archivedChatsIcon(hiddenByDefault: hiddenByDefault)
|
||||
@ -651,6 +658,9 @@ public final class AvatarNode: ASDisplayNode {
|
||||
case .repliesIcon:
|
||||
representation = nil
|
||||
icon = .repliesIcon
|
||||
case .anonymousSavedMessagesIcon:
|
||||
representation = nil
|
||||
icon = .repliesIcon
|
||||
case let .archivedChatsIcon(hiddenByDefault):
|
||||
representation = nil
|
||||
icon = .archivedChatsIcon(hiddenByDefault: hiddenByDefault)
|
||||
@ -878,6 +888,15 @@ public final class AvatarNode: ASDisplayNode {
|
||||
context.scaleBy(x: factor, y: -factor)
|
||||
context.translateBy(x: -bounds.size.width / 2.0, y: -bounds.size.height / 2.0)
|
||||
|
||||
if let repliesIcon = repliesIcon {
|
||||
context.draw(repliesIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - repliesIcon.size.width) / 2.0), y: floor((bounds.size.height - repliesIcon.size.height) / 2.0)), size: repliesIcon.size))
|
||||
}
|
||||
} else if case .anonymousSavedMessagesIcon = parameters.icon {
|
||||
let factor = bounds.size.width / 60.0
|
||||
context.translateBy(x: bounds.size.width / 2.0, y: bounds.size.height / 2.0)
|
||||
context.scaleBy(x: factor, y: -factor)
|
||||
context.translateBy(x: -bounds.size.width / 2.0, y: -bounds.size.height / 2.0)
|
||||
|
||||
if let repliesIcon = repliesIcon {
|
||||
context.draw(repliesIcon.cgImage!, in: CGRect(origin: CGPoint(x: floor((bounds.size.width - repliesIcon.size.width) / 2.0), y: floor((bounds.size.height - repliesIcon.size.height) / 2.0)), size: repliesIcon.size))
|
||||
}
|
||||
|
@ -1346,7 +1346,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
let source: ContextContentSource
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
)), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
|
||||
@ -1363,7 +1363,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
if let location = location {
|
||||
source = .location(ChatListContextLocationContentSource(controller: strongSelf, location: location))
|
||||
} else {
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peer.peerId), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peer.peerId), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
}
|
||||
@ -1382,7 +1382,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
let source: ContextContentSource
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
)), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
|
||||
@ -1432,7 +1432,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
if case let .search(messageId) = source, let id = messageId {
|
||||
subject = .message(id: .id(id), highlight: nil, timecode: nil)
|
||||
}
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
contextContentSource = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
}
|
||||
@ -3399,7 +3399,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
||||
return
|
||||
}
|
||||
|
||||
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false))
|
||||
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default))
|
||||
|
||||
if let sourceController = sourceController as? ChatListControllerImpl, case .forum(peerId) = sourceController.location {
|
||||
navigationController.replaceController(sourceController, with: chatController, animated: false)
|
||||
@ -6541,7 +6541,7 @@ private final class ChatListLocationContext {
|
||||
|
||||
if let channel = peerView.peers[peerView.peerId] as? TelegramChannel, !channel.flags.contains(.isForum) {
|
||||
if let parentController = self.parentController, let navigationController = parentController.navigationController as? NavigationController {
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false))
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default))
|
||||
navigationController.replaceController(parentController, with: chatController, animated: true)
|
||||
}
|
||||
} else {
|
||||
|
@ -1137,7 +1137,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
return
|
||||
}
|
||||
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default))
|
||||
(controller.navigationController as? NavigationController)?.replaceController(controller, with: chatController, animated: false)
|
||||
}
|
||||
|
||||
|
@ -1559,7 +1559,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
|
||||
})
|
||||
},
|
||||
peerContextAction: { peer, node, gesture, location in
|
||||
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
|
@ -1507,7 +1507,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
proceed(chatController)
|
||||
})
|
||||
} else {
|
||||
proceed(strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||
proceed(strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default)))
|
||||
}
|
||||
|
||||
strongSelf.updateState { state in
|
||||
|
@ -1228,6 +1228,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
enableRecentlySearched = true
|
||||
}
|
||||
}
|
||||
if case .savedMessagesChats = location {
|
||||
enableRecentlySearched = false
|
||||
}
|
||||
|
||||
if enableRecentlySearched {
|
||||
fixedRecentlySearchedPeers = context.engine.peers.recentlySearchedPeers()
|
||||
@ -1406,7 +1409,26 @@ 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)], recentlySearchedPeerIds: Set<EnginePeer.Id>), NoError>
|
||||
if let query = query, (key == .chats || key == .topics) {
|
||||
|
||||
if case .savedMessagesChats = location {
|
||||
if let query {
|
||||
foundLocalPeers = context.engine.messages.searchLocalSavedMessagesPeers(query: query.lowercased(), indexNameMapping: [
|
||||
context.account.peerId: [
|
||||
PeerIndexNameRepresentation.title(title: "saved messages", addressNames: []),
|
||||
PeerIndexNameRepresentation.title(title: presentationData.strings.DialogList_SavedMessages.lowercased(), addressNames: [])
|
||||
],
|
||||
PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(2666000)): [
|
||||
//TODO:localize
|
||||
PeerIndexNameRepresentation.title(title: "author hidden", addressNames: [])
|
||||
]
|
||||
])
|
||||
|> map { peers -> (peers: [EngineRenderedPeer], unread: [EnginePeer.Id: (Int32, Bool)], recentlySearchedPeerIds: Set<EnginePeer.Id>) in
|
||||
return (peers.map(EngineRenderedPeer.init(peer:)), [:], Set())
|
||||
}
|
||||
} else {
|
||||
foundLocalPeers = .single(([], [:], Set()))
|
||||
}
|
||||
} else if let query = query, (key == .chats || key == .topics) {
|
||||
let fixedOrRemovedRecentlySearchedPeers = context.engine.peers.recentlySearchedPeers()
|
||||
|> map { peers -> [RecentlySearchedPeer] in
|
||||
let allIds = peers.map(\.peer.peerId)
|
||||
@ -1524,7 +1546,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
|
||||
let foundRemotePeers: Signal<([FoundPeer], [FoundPeer], Bool), NoError>
|
||||
let currentRemotePeersValue: ([FoundPeer], [FoundPeer]) = currentRemotePeers.with { $0 } ?? ([], [])
|
||||
if let query = query, case .chats = key {
|
||||
if case .savedMessagesChats = location {
|
||||
foundRemotePeers = .single(([], [], false))
|
||||
} else if let query = query, case .chats = key {
|
||||
foundRemotePeers = (
|
||||
.single((currentRemotePeersValue.0, currentRemotePeersValue.1, true))
|
||||
|> then(
|
||||
@ -1579,7 +1603,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
}
|
||||
|
||||
let foundRemoteMessages: Signal<([FoundRemoteMessages], Bool), NoError>
|
||||
if peersFilter.contains(.doNotSearchMessages) {
|
||||
if case .savedMessagesChats = location {
|
||||
foundRemoteMessages = .single(([FoundRemoteMessages(messages: [], readCounters: [:], threadsData: [:], totalCount: 0)], false))
|
||||
} else if peersFilter.contains(.doNotSearchMessages) {
|
||||
foundRemoteMessages = .single(([FoundRemoteMessages(messages: [], readCounters: [:], threadsData: [:], totalCount: 0)], false))
|
||||
} else {
|
||||
if !finalQuery.isEmpty {
|
||||
@ -1676,7 +1702,11 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
)
|
||||
}
|
||||
|
||||
let resolvedMessage = .single(nil)
|
||||
let resolvedMessage: Signal<EngineMessage?, NoError>
|
||||
if case .savedMessagesChats = location {
|
||||
resolvedMessage = .single(nil)
|
||||
} else {
|
||||
resolvedMessage = .single(nil)
|
||||
|> then(context.sharedContext.resolveUrl(context: context, peerId: nil, url: finalQuery, skipUrlAuth: true)
|
||||
|> mapToSignal { resolvedUrl -> Signal<EngineMessage?, NoError> in
|
||||
if case let .channelMessage(_, messageId, _) = resolvedUrl {
|
||||
@ -1688,6 +1718,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
return .single(nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let foundThreads: Signal<[EngineChatList.Item], NoError>
|
||||
if case let .forum(peerId) = location, (key == .topics || key == .chats) {
|
||||
@ -2619,6 +2650,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
if peersFilter.contains(.excludeRecent) {
|
||||
recentItems = .single([])
|
||||
}
|
||||
if case .savedMessagesChats = location {
|
||||
recentItems = .single([])
|
||||
}
|
||||
|
||||
if case .chats = key, !peersFilter.contains(.excludeRecent) {
|
||||
self.updatedRecentPeersDisposable.set(context.engine.peers.managedUpdatedRecentPeers().startStrict())
|
||||
|
@ -379,9 +379,10 @@ final class ChatListSearchPaneContainerNode: ASDisplayNode, UIGestureRecognizerD
|
||||
|
||||
self.currentParams = (size, sideInset, bottomInset, visibleHeight, presentationData, availablePanes)
|
||||
|
||||
if case .forum = self.location {
|
||||
switch self.location {
|
||||
case .forum, .savedMessagesChats:
|
||||
self.backgroundColor = .clear
|
||||
} else {
|
||||
default:
|
||||
self.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
|
||||
}
|
||||
let paneFrame = CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height))
|
||||
|
@ -1394,6 +1394,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var overrideImage: AvatarNodeImageOverride?
|
||||
if peer.id.isReplies {
|
||||
overrideImage = .repliesIcon
|
||||
} else if peer.id.isAnonymousSavedMessages {
|
||||
overrideImage = .anonymousSavedMessagesIcon
|
||||
} else if peer.id == item.context.account.peerId && !displayAsMessage {
|
||||
overrideImage = .savedMessagesIcon
|
||||
} else if peer.isDeleted {
|
||||
@ -2294,6 +2296,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: titleFont, textColor: theme.titleColor)
|
||||
} else if let id = itemPeer.chatMainPeer?.id, id.isReplies {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: titleFont, textColor: theme.titleColor)
|
||||
} else if let id = itemPeer.chatMainPeer?.id, id.isAnonymousSavedMessages {
|
||||
//TODO:localize
|
||||
titleAttributedString = NSAttributedString(string: "Author Hidden", font: titleFont, textColor: theme.titleColor)
|
||||
} else if let displayTitle = itemPeer.chatMainPeer?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) {
|
||||
let textColor: UIColor
|
||||
if case let .chatList(index) = item.index, index.messageIndex.id.peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
|
@ -312,7 +312,6 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
case .savedMessagesChats:
|
||||
if "".isEmpty {
|
||||
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: account.peerId)
|
||||
|
||||
var isFirst = true
|
||||
@ -376,102 +375,5 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
||||
isFirst = false
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
} else {
|
||||
var isFirst = true
|
||||
|
||||
return account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 1000, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal])), orderStatistics: [])
|
||||
|> map { view, _, _ -> ChatListNodeViewUpdate in
|
||||
let isLoading = view.isLoading
|
||||
|
||||
var items: [EngineChatList.Item] = []
|
||||
|
||||
var topMessageByPeerId: [EnginePeer.Id: Message] = [:]
|
||||
if !isLoading {
|
||||
for entry in view.entries {
|
||||
guard let threadId = entry.message.threadId else {
|
||||
continue
|
||||
}
|
||||
let sourcePeerId = PeerId(threadId)
|
||||
|
||||
if let currentTopMessage = topMessageByPeerId[sourcePeerId] {
|
||||
if currentTopMessage.index < entry.index {
|
||||
topMessageByPeerId[sourcePeerId] = entry.message
|
||||
}
|
||||
} else {
|
||||
topMessageByPeerId[sourcePeerId] = entry.message
|
||||
}
|
||||
}
|
||||
for (_, message) in topMessageByPeerId.sorted(by: { $0.value.index > $1.value.index }) {
|
||||
guard let threadId = message.threadId else {
|
||||
continue
|
||||
}
|
||||
let sourceId = PeerId(threadId)
|
||||
var sourcePeer = message.peers[sourceId]
|
||||
if sourcePeer == nil, let forwardInfo = message.forwardInfo, let authorSignature = forwardInfo.authorSignature {
|
||||
sourcePeer = TelegramUser(
|
||||
id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(1)),
|
||||
accessHash: nil,
|
||||
firstName: authorSignature,
|
||||
lastName: nil,
|
||||
username: nil,
|
||||
phone: nil,
|
||||
photo: [],
|
||||
botInfo: nil,
|
||||
restrictionInfo: nil,
|
||||
flags: [],
|
||||
emojiStatus: nil,
|
||||
usernames: [],
|
||||
storiesHidden: nil,
|
||||
nameColor: nil,
|
||||
backgroundEmojiId: nil,
|
||||
profileColor: nil,
|
||||
profileBackgroundEmojiId: nil
|
||||
)
|
||||
}
|
||||
guard let sourcePeer else {
|
||||
continue
|
||||
}
|
||||
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: message.index.id.namespace, id: message.index.id.id), timestamp: message.index.timestamp)
|
||||
items.append(EngineChatList.Item(
|
||||
id: .chatList(sourceId),
|
||||
index: .chatList(ChatListIndex(pinningIndex: nil, messageIndex: mappedMessageIndex)),
|
||||
messages: [EngineMessage(message)],
|
||||
readCounters: nil,
|
||||
isMuted: false,
|
||||
draft: nil,
|
||||
threadData: nil,
|
||||
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
||||
presence: nil,
|
||||
hasUnseenMentions: false,
|
||||
hasUnseenReactions: false,
|
||||
forumTopicData: nil,
|
||||
topForumTopicItems: [],
|
||||
hasFailed: false,
|
||||
isContact: false,
|
||||
autoremoveTimeout: nil,
|
||||
storyStats: nil
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
let list = EngineChatList(
|
||||
items: items.reversed(),
|
||||
groupItems: [],
|
||||
additionalItems: [],
|
||||
hasEarlier: false,
|
||||
hasLater: false,
|
||||
isLoading: isLoading
|
||||
)
|
||||
|
||||
let type: ViewUpdateType
|
||||
if isFirst {
|
||||
type = .Initial
|
||||
} else {
|
||||
type = .Generic
|
||||
}
|
||||
isFirst = false
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -439,7 +439,7 @@ final class ContactsControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
|
||||
let controller = ContextController(presentationData: self.presentationData, source: .extracted(ContactContextExtractedContentSource(sourceNode: node, shouldBeDismissed: .single(false))), items: items, recognizer: nil, gesture: gesture)
|
||||
contactsController.presentInGlobalOverlay(controller)
|
||||
} else {
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(presentationData: self.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: items, gesture: gesture)
|
||||
contactsController.presentInGlobalOverlay(contextController)
|
||||
|
@ -783,6 +783,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: titleBoldFont, textColor: textColor)
|
||||
} else if peer.id.isReplies {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: titleBoldFont, textColor: textColor)
|
||||
} else if peer.id.isAnonymousSavedMessages {
|
||||
//TODO:localize
|
||||
titleAttributedString = NSAttributedString(string: "Author Hidden", font: titleBoldFont, textColor: textColor)
|
||||
} else if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
switch item.displayOrder {
|
||||
@ -1030,6 +1033,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
overrideImage = .savedMessagesIcon
|
||||
} else if peer.id.isReplies, case .generalSearch = item.peerMode {
|
||||
overrideImage = .repliesIcon
|
||||
} else if peer.id.isAnonymousSavedMessages, case .generalSearch = item.peerMode {
|
||||
overrideImage = .anonymousSavedMessagesIcon
|
||||
} else if peer.isDeleted {
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
|
@ -217,10 +217,10 @@ public func galleryItemForEntry(
|
||||
if file.isVideo {
|
||||
let content: UniversalVideoContent
|
||||
if file.isAnimated {
|
||||
content = NativeVideoContent(id: .message(message.stableId, file.fileId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), loopVideo: true, enableSound: false, tempFilePath: tempFilePath, captureProtected: message.isCopyProtected(), storeAfterDownload: generateStoreAfterDownload?(message, file))
|
||||
content = NativeVideoContent(id: .message(message.stableId, file.fileId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), loopVideo: true, enableSound: false, tempFilePath: tempFilePath, captureProtected: message.isCopyProtected() || message.containsSecretMedia, storeAfterDownload: generateStoreAfterDownload?(message, file))
|
||||
} else {
|
||||
if true || (file.mimeType == "video/mpeg4" || file.mimeType == "video/mov" || file.mimeType == "video/mp4") {
|
||||
content = NativeVideoContent(id: .message(message.stableId, file.fileId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, loopVideo: loopVideos, tempFilePath: tempFilePath, captureProtected: message.isCopyProtected(), storeAfterDownload: generateStoreAfterDownload?(message, file))
|
||||
content = NativeVideoContent(id: .message(message.stableId, file.fileId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, loopVideo: loopVideos, tempFilePath: tempFilePath, captureProtected: message.isCopyProtected() || message.containsSecretMedia, storeAfterDownload: generateStoreAfterDownload?(message, file))
|
||||
} else {
|
||||
content = PlatformVideoContent(id: .message(message.id, message.stableId, file.fileId), userLocation: .peer(message.id.peerId), content: .file(.message(message: MessageReference(message), media: file)), streamVideo: streamVideos, loopVideo: loopVideos)
|
||||
}
|
||||
@ -323,11 +323,11 @@ public func galleryItemForEntry(
|
||||
var content: UniversalVideoContent?
|
||||
switch websiteType(of: webpageContent.websiteName) {
|
||||
case .instagram where webpageContent.file != nil && webpageContent.image != nil && webpageContent.file!.isVideo:
|
||||
content = NativeVideoContent(id: .message(message.stableId, webpageContent.file?.id ?? webpage.webpageId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: webpageContent.file!), imageReference: webpageContent.image.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, enableSound: true, captureProtected: message.isCopyProtected(), storeAfterDownload: nil)
|
||||
content = NativeVideoContent(id: .message(message.stableId, webpageContent.file?.id ?? webpage.webpageId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: webpageContent.file!), imageReference: webpageContent.image.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, enableSound: true, captureProtected: message.isCopyProtected() || message.containsSecretMedia, storeAfterDownload: nil)
|
||||
default:
|
||||
if let embedUrl = webpageContent.embedUrl, let image = webpageContent.image {
|
||||
if let file = webpageContent.file, file.isVideo {
|
||||
content = NativeVideoContent(id: .message(message.stableId, file.fileId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, loopVideo: loopVideos, tempFilePath: tempFilePath, captureProtected: message.isCopyProtected(), storeAfterDownload: generateStoreAfterDownload?(message, file))
|
||||
content = NativeVideoContent(id: .message(message.stableId, file.fileId), userLocation: .peer(message.id.peerId), fileReference: .message(message: MessageReference(message), media: file), imageReference: mediaImage.flatMap({ ImageMediaReference.message(message: MessageReference(message), media: $0) }), streamVideo: .conservative, loopVideo: loopVideos, tempFilePath: tempFilePath, captureProtected: message.isCopyProtected() || message.containsSecretMedia, storeAfterDownload: generateStoreAfterDownload?(message, file))
|
||||
} else if URL(string: embedUrl)?.pathExtension == "mp4" {
|
||||
content = SystemVideoContent(userLocation: .peer(message.id.peerId), url: embedUrl, imageReference: .webPage(webPage: WebpageReference(webpage), media: image), dimensions: webpageContent.embedSize?.cgSize ?? CGSize(width: 640.0, height: 640.0), duration: webpageContent.duration.flatMap(Double.init) ?? 0.0)
|
||||
}
|
||||
|
@ -1041,6 +1041,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: currentBoldFont, textColor: titleColor)
|
||||
} else if item.peer.id.isReplies {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_Replies, font: currentBoldFont, textColor: titleColor)
|
||||
} else if item.peer.id.isAnonymousSavedMessages {
|
||||
//TODO:localize
|
||||
titleAttributedString = NSAttributedString(string: "Author Hidden", font: currentBoldFont, textColor: titleColor)
|
||||
} else if case let .user(user) = item.peer {
|
||||
if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
|
@ -818,7 +818,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
|
||||
descriptionText = NSAttributedString(string: " ", font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
|
||||
if let _ = item.message?.threadId, let threadInfo = item.message?.associatedThreadInfo {
|
||||
if let _ = item.message?.threadId, item.message?.id.peerId.namespace == Namespaces.Peer.CloudChannel, let threadInfo = item.message?.associatedThreadInfo {
|
||||
if isInstantVideo || isVoice {
|
||||
titleExtraData = (NSAttributedString(string: threadInfo.title, font: titleFont, textColor: item.presentationData.theme.theme.list.itemPrimaryTextColor), true, threadInfo.icon, threadInfo.iconColor)
|
||||
} else {
|
||||
|
@ -509,7 +509,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
|
||||
var forumThreadTitle: (title: NSAttributedString, showIcon: Bool, iconId: Int64?, iconColor: Int32)? = nil
|
||||
|
||||
var authorString = ""
|
||||
if let message = item.message, let _ = message.threadId, let threadInfo = message.associatedThreadInfo {
|
||||
if let message = item.message, let _ = message.threadId, item.message?.id.peerId.namespace == Namespaces.Peer.CloudChannel, let threadInfo = message.associatedThreadInfo {
|
||||
let fullAuthorString = stringForFullAuthorName(message: EngineMessage(message), strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, accountPeerId: item.context.account.peerId)
|
||||
authorString = fullAuthorString.first ?? ""
|
||||
forumThreadTitle = (NSAttributedString(string: threadInfo.title, font: descriptionFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor), true, threadInfo.icon, threadInfo.iconColor)
|
||||
|
@ -2327,7 +2327,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta
|
||||
})
|
||||
} else {
|
||||
if let navigationController = controller.navigationController as? NavigationController {
|
||||
navigationController.replaceAllButRootController(context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)), animated: true)
|
||||
navigationController.replaceAllButRootController(context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default)), animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ public func convertToSupergroupController(context: AccountContext, peerId: Engin
|
||||
if !alreadyConverting {
|
||||
convertDisposable.set((context.engine.peers.convertGroupToSupergroup(peerId: peerId)
|
||||
|> deliverOnMainQueue).start(next: { createdPeerId in
|
||||
replaceControllerImpl?(context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: createdPeerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||
replaceControllerImpl?(context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: createdPeerId), subject: nil, botStart: nil, mode: .standard(.default)))
|
||||
}))
|
||||
}
|
||||
})]), nil)
|
||||
|
@ -486,7 +486,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|
||||
}))
|
||||
}, contextAction: { peer, node, gesture in
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: peerNearbyContextMenuItems(context: context, peerId: peer.id, present: { c in
|
||||
presentControllerImpl?(c, nil)
|
||||
|
@ -0,0 +1,55 @@
|
||||
import Foundation
|
||||
|
||||
final class MutableMessageHistorySavedMessagesStatsView: MutablePostboxView {
|
||||
fileprivate let peerId: PeerId
|
||||
fileprivate var count: Int = 0
|
||||
fileprivate var isLoading: Bool = false
|
||||
|
||||
init(postbox: PostboxImpl, peerId: PeerId) {
|
||||
self.peerId = peerId
|
||||
|
||||
self.reload(postbox: postbox)
|
||||
}
|
||||
|
||||
private func reload(postbox: PostboxImpl) {
|
||||
let validIndexBoundary = postbox.peerThreadCombinedStateTable.get(peerId: peerId)?.validIndexBoundary
|
||||
self.isLoading = validIndexBoundary == nil
|
||||
|
||||
if !self.isLoading {
|
||||
self.count = postbox.messageHistoryThreadIndexTable.getCount(peerId: self.peerId)
|
||||
} else {
|
||||
self.count = 0
|
||||
}
|
||||
}
|
||||
|
||||
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
|
||||
var updated = false
|
||||
|
||||
if transaction.updatedMessageThreadPeerIds.contains(self.peerId) {
|
||||
self.reload(postbox: postbox)
|
||||
updated = true
|
||||
}
|
||||
|
||||
return updated
|
||||
}
|
||||
|
||||
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
|
||||
self.reload(postbox: postbox)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func immutableView() -> PostboxView {
|
||||
return MessageHistorySavedMessagesStatsView(self)
|
||||
}
|
||||
}
|
||||
|
||||
public final class MessageHistorySavedMessagesStatsView: PostboxView {
|
||||
public let isLoading: Bool
|
||||
public let count: Int
|
||||
|
||||
init(_ view: MutableMessageHistorySavedMessagesStatsView) {
|
||||
self.isLoading = view.isLoading
|
||||
self.count = view.count
|
||||
}
|
||||
}
|
@ -1554,7 +1554,7 @@ final class MessageHistoryTable: Table {
|
||||
|
||||
let updatedGroupInfo = self.updateMovingGroupInfoInNamespace(index: updatedIndex, updatedIndex: updatedIndex, groupingKey: message.groupingKey, previousInfo: previousMessage.groupInfo, updatedGroupInfos: &updatedGroupInfos)
|
||||
|
||||
if previousMessage.tags != message.tags || index != updatedIndex {
|
||||
if previousMessage.tags != message.tags || previousMessage.threadId != message.threadId || index != updatedIndex {
|
||||
if !previousMessage.tags.isEmpty {
|
||||
self.tagsTable.remove(tags: previousMessage.tags, index: index, updatedSummaries: &updatedMessageTagSummaries, invalidateSummaries: &invalidateMessageTagSummaries)
|
||||
if let threadId = previousMessage.threadId {
|
||||
|
@ -300,6 +300,10 @@ class MessageHistoryThreadIndexTable: Table {
|
||||
return result
|
||||
}
|
||||
|
||||
func getCount(peerId: PeerId) -> Int {
|
||||
return self.valueBox.count(self.table, start: self.lowerBound(peerId: peerId), end: self.upperBound(peerId: peerId))
|
||||
}
|
||||
|
||||
override func beforeCommit() {
|
||||
super.beforeCommit()
|
||||
|
||||
|
@ -1075,6 +1075,11 @@ public final class Transaction {
|
||||
self.postbox?.scanMessages(peerId: peerId, namespace: namespace, tag: tag, f)
|
||||
}
|
||||
|
||||
public func scanMessages(peerId: PeerId, threadId: Int64, namespace: MessageId.Namespace, tag: MessageTags, _ f: (Message) -> Bool) {
|
||||
assert(!self.disposed)
|
||||
self.postbox?.scanMessages(peerId: peerId, threadId: threadId, namespace: namespace, tag: tag, f)
|
||||
}
|
||||
|
||||
public func scanTopMessages(peerId: PeerId, namespace: MessageId.Namespace, limit: Int, _ f: (Message) -> Bool) {
|
||||
assert(!self.disposed)
|
||||
self.postbox?.scanTopMessages(peerId: peerId, namespace: namespace, limit: limit, f)
|
||||
@ -1336,6 +1341,26 @@ public final class Transaction {
|
||||
public func getPeerStoryStats(peerId: PeerId) -> PeerStoryStats? {
|
||||
return fetchPeerStoryStats(postbox: self.postbox!, peerId: peerId)
|
||||
}
|
||||
|
||||
public func searchSubPeers(peerId: PeerId, query: String, indexNameMapping: [PeerId: [PeerIndexNameRepresentation]]) -> [Peer] {
|
||||
let allThreads = self.postbox!.messageHistoryThreadIndexTable.getAll(peerId: peerId)
|
||||
var matchingPeers: [(Peer, MessageIndex)] = []
|
||||
for (threadId, index, _) in allThreads {
|
||||
if let peer = self.postbox!.peerTable.get(PeerId(threadId)) {
|
||||
if let mappings = indexNameMapping[peer.id] {
|
||||
inner: for mapping in mappings {
|
||||
if mapping.matchesByTokens(query) {
|
||||
matchingPeers.append((peer, index))
|
||||
break inner
|
||||
}
|
||||
}
|
||||
} else if peer.indexName.matchesByTokens(query) {
|
||||
matchingPeers.append((peer, index))
|
||||
}
|
||||
}
|
||||
}
|
||||
return matchingPeers.sorted(by: { $0.1 > $1.1 }).map(\.0)
|
||||
}
|
||||
}
|
||||
|
||||
public enum PostboxResult {
|
||||
@ -3938,6 +3963,28 @@ final class PostboxImpl {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func scanMessages(peerId: PeerId, threadId: Int64, namespace: MessageId.Namespace, tag: MessageTags, _ f: (Message) -> Bool) {
|
||||
var index = MessageIndex.lowerBound(peerId: peerId, namespace: namespace)
|
||||
while true {
|
||||
let indices = self.messageHistoryThreadTagsTable.laterIndices(tag: tag, threadId: threadId, peerId: peerId, namespace: namespace, index: index, includeFrom: false, count: 10)
|
||||
for index in indices {
|
||||
if let message = self.messageHistoryTable.getMessage(index) {
|
||||
if !f(self.renderIntermediateMessage(message)) {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
break
|
||||
}
|
||||
}
|
||||
if let last = indices.last {
|
||||
index = last
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate func scanTopMessages(peerId: PeerId, namespace: MessageId.Namespace, limit: Int, _ f: (Message) -> Bool) {
|
||||
let lowerBound = MessageIndex.lowerBound(peerId: peerId, namespace: namespace)
|
||||
var index = MessageIndex.upperBound(peerId: peerId, namespace: namespace)
|
||||
|
@ -47,6 +47,7 @@ public enum PostboxViewKey: Hashable {
|
||||
case peerStoryStats(peerIds: Set<PeerId>)
|
||||
case story(id: StoryId)
|
||||
case savedMessagesIndex(peerId: PeerId)
|
||||
case savedMessagesStats(peerId: PeerId)
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
switch self {
|
||||
@ -156,6 +157,8 @@ public enum PostboxViewKey: Hashable {
|
||||
hasher.combine(id)
|
||||
case let .savedMessagesIndex(peerId):
|
||||
hasher.combine(peerId)
|
||||
case let .savedMessagesStats(peerId):
|
||||
hasher.combine(peerId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -437,6 +440,12 @@ public enum PostboxViewKey: Hashable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .savedMessagesStats(peerId):
|
||||
if case .savedMessagesStats(peerId) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -535,5 +544,7 @@ func postboxViewForKey(postbox: PostboxImpl, key: PostboxViewKey) -> MutablePost
|
||||
return MutableStoryView(postbox: postbox, id: id)
|
||||
case let .savedMessagesIndex(peerId):
|
||||
return MutableMessageHistorySavedMessagesIndexView(postbox: postbox, peerId: peerId)
|
||||
case let .savedMessagesStats(peerId):
|
||||
return MutableMessageHistorySavedMessagesStatsView(postbox: postbox, peerId: peerId)
|
||||
}
|
||||
}
|
||||
|
@ -997,7 +997,7 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
|
||||
allItems.append(contentsOf: profileItems)
|
||||
|
||||
let savedMessages = SettingsSearchableItem(id: .savedMessages(0), title: strings.Settings_SavedMessages, alternate: synonyms(strings.SettingsSearch_Synonyms_SavedMessages), icon: .savedMessages, breadcrumbs: [], present: { context, _, present in
|
||||
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: context.account.peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: context.account.peerId), subject: nil, botStart: nil, mode: .standard(.default)))
|
||||
})
|
||||
allItems.append(savedMessages)
|
||||
|
||||
@ -1057,7 +1057,7 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList
|
||||
let _ = (context.engine.peers.supportPeerId()
|
||||
|> deliverOnMainQueue).start(next: { peerId in
|
||||
if let peerId = peerId {
|
||||
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||
present(.push, context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default)))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -471,10 +471,21 @@ public extension TelegramEngine {
|
||||
for i in 0 ..< tags.count {
|
||||
let (count, maxId) = counts[i]
|
||||
if let count = count {
|
||||
if count == 0, peerId == account.peerId, let threadId {
|
||||
var localCount = 0
|
||||
var maxId: Int32 = 1
|
||||
transaction.scanMessages(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, tag: tags[i], { message in
|
||||
localCount += 1
|
||||
maxId = max(maxId, message.id.id)
|
||||
return true
|
||||
})
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tags[i], namespace: Namespaces.Message.Cloud, count: Int32(localCount), maxId: maxId)
|
||||
} else {
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, threadId: threadId, tagMask: tags[i], namespace: Namespaces.Message.Cloud, count: count, maxId: maxId ?? 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|> ignoreValues
|
||||
}
|
||||
}
|
||||
@ -1300,7 +1311,25 @@ public extension TelegramEngine {
|
||||
}
|
||||
|
||||
public func synchronouslyIsMessageDeletedInteractively(ids: [EngineMessage.Id]) -> [EngineMessage.Id] {
|
||||
return account.stateManager.synchronouslyIsMessageDeletedInteractively(ids: ids)
|
||||
return self.account.stateManager.synchronouslyIsMessageDeletedInteractively(ids: ids)
|
||||
}
|
||||
|
||||
public func savedMessagesPeersStats() -> Signal<Int?, NoError> {
|
||||
return self.account.postbox.combinedView(keys: [.savedMessagesStats(peerId: self.account.peerId)])
|
||||
|> map { views -> Int? in
|
||||
guard let view = views.views[.savedMessagesStats(peerId: self.account.peerId)] as? MessageHistorySavedMessagesStatsView else {
|
||||
return nil
|
||||
}
|
||||
if view.isLoading {
|
||||
return nil
|
||||
} else {
|
||||
return view.count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func searchLocalSavedMessagesPeers(query: String, indexNameMapping: [EnginePeer.Id: [PeerIndexNameRepresentation]]) -> Signal<[EnginePeer], NoError> {
|
||||
return _internal_searchLocalSavedMessagesPeers(account: self.account, query: query, indexNameMapping: indexNameMapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,3 +83,8 @@ public func _internal_searchPeers(accountPeerId: PeerId, postbox: Postbox, netwo
|
||||
return processedSearchResult
|
||||
}
|
||||
|
||||
func _internal_searchLocalSavedMessagesPeers(account: Account, query: String, indexNameMapping: [EnginePeer.Id: [PeerIndexNameRepresentation]]) -> Signal<[EnginePeer], NoError> {
|
||||
return account.postbox.transaction { transaction -> [EnginePeer] in
|
||||
return transaction.searchSubPeers(peerId: account.peerId, query: query, indexNameMapping: indexNameMapping).map(EnginePeer.init)
|
||||
}
|
||||
}
|
||||
|
@ -424,4 +424,13 @@ public extension PeerId {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var isAnonymousSavedMessages: Bool {
|
||||
if self.namespace == Namespaces.Peer.CloudUser {
|
||||
if self.id._internalGetInt64Value() == 2666000 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,9 @@ public func stringForFullAuthorName(message: EngineMessage, strings: Presentatio
|
||||
} else {
|
||||
if message.id.peerId == accountPeerId {
|
||||
authorString = [strings.DialogList_SavedMessages]
|
||||
} else if message.id.peerId.isAnonymousSavedMessages {
|
||||
//TODO:localize
|
||||
authorString = ["Author Hidden"]
|
||||
} else if message.flags.contains(.Incoming) {
|
||||
authorString = [peer.displayTitle(strings: strings, displayOrder: nameDisplayOrder)]
|
||||
} else {
|
||||
|
@ -71,22 +71,24 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess
|
||||
}
|
||||
}
|
||||
|
||||
let timestamp: Int32
|
||||
var timestamp: Int32
|
||||
if let scheduleTime = message.scheduleTime {
|
||||
timestamp = scheduleTime
|
||||
} else {
|
||||
timestamp = message.timestamp
|
||||
}
|
||||
var dateText = stringForMessageTimestamp(timestamp: timestamp, dateTimeFormat: dateTimeFormat)
|
||||
if timestamp == scheduleWhenOnlineTimestamp {
|
||||
dateText = " "
|
||||
}
|
||||
|
||||
var displayFullDate = false
|
||||
if case .full = format, timestamp > 100000 {
|
||||
displayFullDate = true
|
||||
} else if let _ = message.forwardInfo, message.id.peerId == accountPeerId {
|
||||
} else if let forwardInfo = message.forwardInfo, message.id.peerId == accountPeerId {
|
||||
displayFullDate = true
|
||||
timestamp = forwardInfo.date
|
||||
}
|
||||
|
||||
var dateText = stringForMessageTimestamp(timestamp: timestamp, dateTimeFormat: dateTimeFormat)
|
||||
if timestamp == scheduleWhenOnlineTimestamp {
|
||||
dateText = " "
|
||||
}
|
||||
|
||||
if displayFullDate {
|
||||
|
@ -2429,7 +2429,7 @@ public final class EntityInputView: UIInputView, AttachmentTextInputPanelInputVi
|
||||
fontSize: self.presentationData.chatFontSize,
|
||||
bubbleCorners: self.presentationData.chatBubbleCorners,
|
||||
accountPeerId: self.context.account.peerId,
|
||||
mode: .standard(previewing: false),
|
||||
mode: .standard(.default),
|
||||
chatLocation: .peer(id: self.context.account.peerId),
|
||||
subject: nil,
|
||||
peerNearbyData: nil,
|
||||
|
@ -247,6 +247,9 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
||||
segments = [.text(0, NSAttributedString(string: customTitle, font: titleFont, textColor: titleTheme.rootController.navigationBar.primaryTextColor))]
|
||||
} else if peerView.peerId == self.context.account.peerId {
|
||||
segments = [.text(0, NSAttributedString(string: self.strings.Conversation_SavedMessages, font: titleFont, textColor: titleTheme.rootController.navigationBar.primaryTextColor))]
|
||||
} else if peerView.peerId.isAnonymousSavedMessages {
|
||||
//TODO:localize
|
||||
segments = [.text(0, NSAttributedString(string: "Author Hidden", font: titleFont, textColor: titleTheme.rootController.navigationBar.primaryTextColor))]
|
||||
} else {
|
||||
if !peerView.isContact, let user = peer as? TelegramUser, !user.flags.contains(.isSupport), user.botInfo == nil, let phone = user.phone, !phone.isEmpty {
|
||||
segments = [.text(0, NSAttributedString(string: formatPhoneNumber(context: self.context, number: phone), font: titleFont, textColor: titleTheme.rootController.navigationBar.primaryTextColor))]
|
||||
|
@ -1015,7 +1015,7 @@ final class MediaEditorScreenComponent: Component {
|
||||
fontSize: presentationData.chatFontSize,
|
||||
bubbleCorners: presentationData.chatBubbleCorners,
|
||||
accountPeerId: component.context.account.peerId,
|
||||
mode: .standard(previewing: false),
|
||||
mode: .standard(.default),
|
||||
chatLocation: .peer(id: component.context.account.peerId),
|
||||
subject: nil,
|
||||
peerNearbyData: nil,
|
||||
|
@ -52,7 +52,9 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
||||
public init(context: AccountContext, navigationController: @escaping () -> NavigationController?) {
|
||||
self.context = context
|
||||
self.navigationController = navigationController
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationData = presentationData
|
||||
let strings = presentationData.strings
|
||||
|
||||
self.chatListNode = ChatListNode(
|
||||
context: self.context,
|
||||
@ -90,6 +92,15 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
||||
|
||||
self.ready.set(self.chatListNode.ready)
|
||||
|
||||
self.statusPromise.set(self.context.engine.messages.savedMessagesPeersStats()
|
||||
|> map { count in
|
||||
if let count {
|
||||
return PeerInfoStatusData(text: strings.Notifications_Exceptions(Int32(count)), isActivity: false, key: .savedMessagesChats)
|
||||
} else {
|
||||
return PeerInfoStatusData(text: strings.Channel_NotificationLoading.lowercased(), isActivity: false, key: .savedMessagesChats)
|
||||
}
|
||||
})
|
||||
|
||||
self.chatListNode.peerSelected = { [weak self] peer, _, _, _, _ in
|
||||
guard let self, let navigationController = self.navigationController() else {
|
||||
return
|
||||
@ -229,7 +240,7 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
||||
public func updateSelectedMessages(animated: Bool) {
|
||||
}
|
||||
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
transition.updateFrame(node: self.chatListNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
|
@ -0,0 +1,27 @@
|
||||
load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
|
||||
|
||||
swift_library(
|
||||
name = "PeerInfoChatPaneNode",
|
||||
module_name = "PeerInfoChatPaneNode",
|
||||
srcs = glob([
|
||||
"Sources/**/*.swift",
|
||||
]),
|
||||
copts = [
|
||||
"-warnings-as-errors",
|
||||
],
|
||||
deps = [
|
||||
"//submodules/SSignalKit/SwiftSignalKit",
|
||||
"//submodules/AsyncDisplayKit",
|
||||
"//submodules/TelegramCore",
|
||||
"//submodules/Postbox",
|
||||
"//submodules/TelegramPresentationData",
|
||||
"//submodules/AccountContext",
|
||||
"//submodules/TelegramStringFormatting",
|
||||
"//submodules/ComponentFlow",
|
||||
"//submodules/AppBundle",
|
||||
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
],
|
||||
)
|
@ -0,0 +1,156 @@
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramCore
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import TelegramStringFormatting
|
||||
import ComponentFlow
|
||||
import TelegramUIPreferences
|
||||
import AppBundle
|
||||
import PeerInfoPaneNode
|
||||
|
||||
public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate {
|
||||
private let context: AccountContext
|
||||
private let peerId: EnginePeer.Id
|
||||
private let navigationController: () -> NavigationController?
|
||||
|
||||
private let chatController: ChatController
|
||||
|
||||
public weak var parentController: ViewController? {
|
||||
didSet {
|
||||
if self.parentController !== oldValue {
|
||||
if let parentController = self.parentController {
|
||||
self.chatController.willMove(toParent: parentController)
|
||||
parentController.addChild(self.chatController)
|
||||
self.chatController.didMove(toParent: parentController)
|
||||
} else {
|
||||
self.chatController.willMove(toParent: nil)
|
||||
self.chatController.removeFromParent()
|
||||
self.chatController.didMove(toParent: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
|
||||
private let ready = Promise<Bool>()
|
||||
private var didSetReady: Bool = false
|
||||
public var isReady: Signal<Bool, NoError> {
|
||||
return self.ready.get()
|
||||
}
|
||||
|
||||
private let statusPromise = Promise<PeerInfoStatusData?>(nil)
|
||||
public var status: Signal<PeerInfoStatusData?, NoError> {
|
||||
self.statusPromise.get()
|
||||
}
|
||||
|
||||
public var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)?
|
||||
public var tabBarOffset: CGFloat {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
public init(context: AccountContext, peerId: EnginePeer.Id, navigationController: @escaping () -> NavigationController?) {
|
||||
self.context = context
|
||||
self.peerId = peerId
|
||||
self.navigationController = navigationController
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.chatController = context.sharedContext.makeChatController(context: context, chatLocation: .replyThread(message: ChatReplyThreadMessage(peerId: context.account.peerId, threadId: peerId.toInt64(), channelMessageId: nil, isChannelPost: false, isForumPost: false, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)), subject: nil, botStart: nil, mode: .standard(.embedded))
|
||||
|
||||
super.init()
|
||||
|
||||
self.presentationDataDisposable = (self.context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.presentationData = presentationData
|
||||
})
|
||||
|
||||
self.ready.set(self.chatController.ready.get())
|
||||
|
||||
self.addSubnode(self.chatController.displayNode)
|
||||
self.chatController.displayNode.clipsToBounds = true
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.presentationDataDisposable?.dispose()
|
||||
}
|
||||
|
||||
public func ensureMessageIsVisible(id: MessageId) {
|
||||
}
|
||||
|
||||
public func scrollToTop() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func hitTestResultForScrolling() -> UIView? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func brieflyDisableTouchActions() {
|
||||
}
|
||||
|
||||
public func findLoadedMessage(id: MessageId) -> Message? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func updateHiddenMedia() {
|
||||
}
|
||||
|
||||
public func transferVelocity(_ velocity: CGFloat) {
|
||||
}
|
||||
|
||||
public func cancelPreviewGestures() {
|
||||
}
|
||||
|
||||
public func transitionNodeForGallery(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func addToTransitionSurface(view: UIView) {
|
||||
}
|
||||
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
}
|
||||
|
||||
|
||||
override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
if gestureRecognizer.state != .failed, let otherGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer {
|
||||
let _ = otherGestureRecognizer
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public func updateSelectedMessages(animated: Bool) {
|
||||
}
|
||||
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
let chatFrame = CGRect(origin: CGPoint(x: 0.0, y: topInset), size: CGSize(width: size.width, height: size.height - topInset))
|
||||
|
||||
let combinedBottomInset = max(0.0, size.height - visibleHeight) + bottomInset
|
||||
transition.updateFrame(node: self.chatController.displayNode, frame: chatFrame)
|
||||
self.chatController.containerLayoutUpdated(ContainerViewLayout(size: chatFrame.size, metrics: LayoutMetrics(widthClass: .compact, heightClass: .compact, orientation: nil), deviceMetrics: deviceMetrics, intrinsicInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: combinedBottomInset, right: sideInset), safeInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: combinedBottomInset, right: sideInset), additionalInsets: UIEdgeInsets(), statusBarHeight: nil, inputHeight: nil, inputHeightIsInteractivellyChanging: false, inVoiceOver: false), transition: transition)
|
||||
}
|
||||
|
||||
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
guard let result = super.hitTest(point, with: event) else {
|
||||
return nil
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ public enum PeerInfoPaneKey: Int32 {
|
||||
case groupsInCommon
|
||||
case recommended
|
||||
case savedMessagesChats
|
||||
case savedMessages
|
||||
}
|
||||
|
||||
public struct PeerInfoStatusData: Equatable {
|
||||
@ -44,7 +45,7 @@ public protocol PeerInfoPaneNode: ASDisplayNode {
|
||||
var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
|
||||
var tabBarOffset: CGFloat { get }
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition)
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition)
|
||||
func scrollToTop() -> Bool
|
||||
func transferVelocity(_ velocity: CGFloat)
|
||||
func cancelPreviewGestures()
|
||||
|
@ -133,6 +133,7 @@ swift_library(
|
||||
"//submodules/SolidRoundedButtonNode",
|
||||
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoPaneNode",
|
||||
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoChatListPaneNode",
|
||||
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoChatPaneNode",
|
||||
"//submodules/MediaPickerUI",
|
||||
"//submodules/AttachmentUI",
|
||||
"//submodules/TelegramUI/Components/Settings/BoostLevelIconComponent",
|
||||
|
@ -786,7 +786,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe
|
||||
return self._itemInteraction!
|
||||
}
|
||||
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
|
||||
private let ready = Promise<Bool>()
|
||||
private var didSetReady: Bool = false
|
||||
@ -959,8 +959,8 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe
|
||||
let wasFirstHistoryView = self.isFirstHistoryView
|
||||
self.isFirstHistoryView = false
|
||||
|
||||
if let (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate)
|
||||
if let (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: wasFirstHistoryView, transition: .immediate)
|
||||
if !self.didSetReady {
|
||||
self.didSetReady = true
|
||||
self.ready.set(.single(true))
|
||||
@ -1066,9 +1066,9 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let previousParams = self.currentParams
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(x: 0.0, y: topInset), size: CGSize(width: size.width, height: size.height - topInset)))
|
||||
|
||||
@ -1110,7 +1110,7 @@ final class PeerInfoGifPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDe
|
||||
private var previousDidScrollTimestamp: Double = 0.0
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if let (size, _, sideInset, bottomInset, visibleHeight, _, _, presentationData) = self.currentParams {
|
||||
if let (size, _, sideInset, bottomInset, _, visibleHeight, _, _, presentationData) = self.currentParams {
|
||||
self.updateVisibleItems(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, theme: presentationData.theme, strings: presentationData.strings, synchronousLoad: false)
|
||||
|
||||
if scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.bounds.height * 2.0, let currentView = self.currentView, currentView.earlierId != nil {
|
||||
|
@ -155,7 +155,7 @@ final class PeerInfoGroupsInCommonPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstLayout = self.currentParams == nil
|
||||
self.currentParams = (size, isScrollingLockedAtTop, presentationData)
|
||||
|
||||
|
@ -31,7 +31,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
|
||||
private let listNode: ChatHistoryListNode
|
||||
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
|
||||
private let ready = Promise<Bool>()
|
||||
private var didSetReady: Bool = false
|
||||
@ -146,8 +146,8 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
strongSelf.playlistLocation = nil
|
||||
}
|
||||
|
||||
if let (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: true, transition: .animated(duration: 0.4, curve: .spring))
|
||||
if let (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: true, transition: .animated(duration: 0.4, curve: .spring))
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -200,8 +200,8 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
var topPanelHeight: CGFloat = 0.0
|
||||
if let (item, previousItem, nextItem, order, type, _) = self.playlistStateAndType {
|
||||
|
@ -238,7 +238,7 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstLayout = self.currentParams == nil
|
||||
self.currentParams = (size, isScrollingLockedAtTop)
|
||||
self.presentationDataPromise.set(.single(presentationData))
|
||||
|
@ -195,7 +195,7 @@ final class PeerInfoRecommendedChannelsPaneNode: ASDisplayNode, PeerInfoPaneNode
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstLayout = self.currentParams == nil
|
||||
self.currentParams = (size, sideInset, bottomInset, isScrollingLockedAtTop, presentationData)
|
||||
self.presentationDataPromise.set(.single(presentationData))
|
||||
|
@ -806,6 +806,21 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
savedMessagesPeer = .single(nil)
|
||||
}
|
||||
|
||||
let hasSavedMessages: Signal<Bool, NoError>
|
||||
if case .peer = chatLocation {
|
||||
hasSavedMessages = context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.MessageCount(peerId: context.account.peerId, threadId: peerId.toInt64(), tag: MessageTags()))
|
||||
|> map { count -> Bool in
|
||||
if let count, count != 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
} else {
|
||||
hasSavedMessages = .single(false)
|
||||
}
|
||||
|
||||
return combineLatest(
|
||||
context.account.viewTracker.peerView(peerId, updateData: true),
|
||||
peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder),
|
||||
@ -814,9 +829,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
status,
|
||||
hasStories,
|
||||
accountIsPremium,
|
||||
savedMessagesPeer
|
||||
savedMessagesPeer,
|
||||
hasSavedMessages
|
||||
)
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, accountIsPremium, savedMessagesPeer -> PeerInfoScreenData in
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, accountIsPremium, savedMessagesPeer, hasSavedMessages -> PeerInfoScreenData in
|
||||
var availablePanes = availablePanes
|
||||
|
||||
if let hasStories {
|
||||
@ -830,8 +846,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
}
|
||||
}
|
||||
|
||||
if peerId == context.account.peerId, case .peer = chatLocation {
|
||||
if case .peer = chatLocation {
|
||||
if peerId == context.account.peerId {
|
||||
availablePanes?.insert(.savedMessagesChats, at: 0)
|
||||
} else if hasSavedMessages {
|
||||
if var availablePanesValue = availablePanes {
|
||||
if let index = availablePanesValue.firstIndex(of: .media) {
|
||||
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||
} else {
|
||||
availablePanesValue.insert(.savedMessages, at: 0)
|
||||
}
|
||||
availablePanes = availablePanesValue
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
availablePanes = nil
|
||||
@ -923,6 +950,17 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
if let recommendedChannels, !recommendedChannels.channels.isEmpty {
|
||||
availablePanes?.append(.recommended)
|
||||
}
|
||||
|
||||
if case .peer = chatLocation {
|
||||
if var availablePanesValue = availablePanes {
|
||||
if let index = availablePanesValue.firstIndex(of: .media) {
|
||||
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||
} else {
|
||||
availablePanesValue.insert(.savedMessages, at: 0)
|
||||
}
|
||||
availablePanes = availablePanesValue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
availablePanes = nil
|
||||
}
|
||||
@ -1129,6 +1167,17 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
}
|
||||
}
|
||||
|
||||
if case .peer = chatLocation {
|
||||
if var availablePanesValue = availablePanes {
|
||||
if let index = availablePanesValue.firstIndex(of: .media) {
|
||||
availablePanesValue.insert(.savedMessages, at: index + 1)
|
||||
} else {
|
||||
availablePanesValue.insert(.savedMessages, at: 0)
|
||||
}
|
||||
availablePanes = availablePanesValue
|
||||
}
|
||||
}
|
||||
|
||||
var canManageInvitations = false
|
||||
if let group = peerViewMainPeer(peerView) as? TelegramGroup {
|
||||
let previousValue = wasUpgradedGroup.swap(group.migrationReference != nil)
|
||||
|
@ -968,6 +968,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
var title: String
|
||||
if peer.id == self.context.account.peerId && !self.isSettings {
|
||||
title = presentationData.strings.Conversation_SavedMessages
|
||||
} else if peer.id.isAnonymousSavedMessages {
|
||||
//TODO:localize
|
||||
title = "Author Hidden"
|
||||
} else if let threadData = threadData {
|
||||
title = threadData.info.title
|
||||
} else {
|
||||
|
@ -12,26 +12,27 @@ import ChatControllerInteraction
|
||||
import PeerInfoVisualMediaPaneNode
|
||||
import PeerInfoPaneNode
|
||||
import PeerInfoChatListPaneNode
|
||||
import PeerInfoChatPaneNode
|
||||
|
||||
final class PeerInfoPaneWrapper {
|
||||
let key: PeerInfoPaneKey
|
||||
let node: PeerInfoPaneNode
|
||||
var isAnimatingOut: Bool = false
|
||||
private var appliedParams: (CGSize, CGFloat, CGFloat, CGFloat, CGFloat, Bool, CGFloat, PresentationData)?
|
||||
private var appliedParams: (CGSize, CGFloat, CGFloat, CGFloat, DeviceMetrics, CGFloat, Bool, CGFloat, PresentationData)?
|
||||
|
||||
init(key: PeerInfoPaneKey, node: PeerInfoPaneNode) {
|
||||
self.key = key
|
||||
self.node = node
|
||||
}
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
if let (currentSize, currentTopInset, currentSideInset, currentBottomInset, _, currentIsScrollingLockedAtTop, currentExpandProgress, currentPresentationData) = self.appliedParams {
|
||||
if currentSize == size && currentTopInset == topInset, currentSideInset == sideInset && currentBottomInset == bottomInset, currentIsScrollingLockedAtTop == isScrollingLockedAtTop && currentExpandProgress == expandProgress && currentPresentationData === presentationData {
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
if let (currentSize, currentTopInset, currentSideInset, currentBottomInset, _, currentVisibleHeight, currentIsScrollingLockedAtTop, currentExpandProgress, currentPresentationData) = self.appliedParams {
|
||||
if currentSize == size && currentTopInset == topInset, currentSideInset == sideInset && currentBottomInset == bottomInset && currentVisibleHeight == visibleHeight && currentIsScrollingLockedAtTop == isScrollingLockedAtTop && currentExpandProgress == expandProgress && currentPresentationData === presentationData {
|
||||
return
|
||||
}
|
||||
}
|
||||
self.appliedParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
self.node.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: synchronous, transition: transition)
|
||||
self.appliedParams = (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
self.node.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: synchronous, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -422,6 +423,8 @@ private final class PeerInfoPendingPane {
|
||||
paneNode = PeerInfoRecommendedChannelsPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, openPeerContextAction: openPeerContextAction)
|
||||
case .savedMessagesChats:
|
||||
paneNode = PeerInfoChatListPaneNode(context: context, navigationController: chatControllerInteraction.navigationController)
|
||||
case .savedMessages:
|
||||
paneNode = PeerInfoChatPaneNode(context: context, peerId: peerId, navigationController: chatControllerInteraction.navigationController)
|
||||
}
|
||||
paneNode.parentController = parentController
|
||||
self.pane = PeerInfoPaneWrapper(key: key, node: paneNode)
|
||||
@ -456,7 +459,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
let isReady = Promise<Bool>()
|
||||
var didSetIsReady = false
|
||||
|
||||
private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)?
|
||||
private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)?
|
||||
|
||||
private(set) var currentPaneKey: PeerInfoPaneKey?
|
||||
var pendingSwitchToPaneKey: PeerInfoPaneKey?
|
||||
@ -548,8 +551,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
if strongSelf.currentPanes[key] != nil {
|
||||
strongSelf.currentPaneKey = key
|
||||
|
||||
if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring))
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring))
|
||||
|
||||
strongSelf.currentPaneUpdated?(true)
|
||||
|
||||
@ -561,8 +564,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
strongSelf.pendingSwitchToPaneKey = key
|
||||
strongSelf.expandOnSwitch = true
|
||||
|
||||
if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring))
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -621,7 +624,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
|
||||
cancelContextGestures(view: self.view)
|
||||
case .changed:
|
||||
if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
let translation = recognizer.translation(in: self.view)
|
||||
var transitionFraction = translation.x / size.width
|
||||
if currentIndex <= 0 {
|
||||
@ -636,11 +639,11 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
// print(transitionFraction)
|
||||
self.paneTransitionPromise.set(transitionFraction)
|
||||
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate)
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate)
|
||||
self.currentPaneUpdated?(false)
|
||||
}
|
||||
case .cancelled, .ended:
|
||||
if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
let translation = recognizer.translation(in: self.view)
|
||||
let velocity = recognizer.velocity(in: self.view)
|
||||
var directionIsToRight: Bool?
|
||||
@ -664,7 +667,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
}
|
||||
}
|
||||
self.transitionFraction = 0.0
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.35, curve: .spring))
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.35, curve: .spring))
|
||||
self.currentPaneUpdated?(false)
|
||||
|
||||
self.currentPaneStatusPromise.set(self.currentPane?.node.status ?? .single(nil))
|
||||
@ -703,7 +706,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) {
|
||||
func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) {
|
||||
let previousAvailablePanes = self.currentAvailablePanes
|
||||
let availablePanes = data?.availablePanes ?? []
|
||||
self.currentAvailablePanes = data?.availablePanes
|
||||
@ -747,7 +750,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
currentIndex = nil
|
||||
}
|
||||
|
||||
self.currentParams = (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data)
|
||||
self.currentParams = (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data)
|
||||
|
||||
transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction)
|
||||
|
||||
@ -817,12 +820,12 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
var transition: ContainedViewLayoutTransition = .immediate
|
||||
if strongSelf.pendingSwitchToPaneKey == key && strongSelf.currentPaneKey != nil {
|
||||
transition = .animated(duration: 0.4, curve: .spring)
|
||||
}
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: transition)
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: transition)
|
||||
}
|
||||
}
|
||||
if leftScope {
|
||||
@ -845,14 +848,14 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
)
|
||||
self.pendingPanes[key] = pane
|
||||
pane.pane.node.frame = paneFrame
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: .immediate)
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: .immediate)
|
||||
let paneNode = pane.pane.node
|
||||
pane.pane.node.tabBarOffsetUpdated = { [weak self, weak paneNode] transition in
|
||||
guard let strongSelf = self, let paneNode = paneNode, let currentPane = strongSelf.currentPane, paneNode === currentPane.node else {
|
||||
return
|
||||
}
|
||||
if let (size, sideInset, bottomInset, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: transition)
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: transition)
|
||||
}
|
||||
}
|
||||
leftScope = true
|
||||
@ -861,7 +864,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
|
||||
for (key, pane) in self.pendingPanes {
|
||||
pane.pane.node.frame = paneFrame
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: self.currentPaneKey == nil, transition: .immediate)
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: self.currentPaneKey == nil, transition: .immediate)
|
||||
|
||||
if pane.isReady {
|
||||
self.pendingPanes.removeValue(forKey: key)
|
||||
@ -922,7 +925,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
return
|
||||
}
|
||||
pane.isAnimatingOut = false
|
||||
if let (_, _, _, _, _, _, data) = strongSelf.currentParams {
|
||||
if let (_, _, _, _, _, _, _, data) = strongSelf.currentParams {
|
||||
if let availablePanes = data?.availablePanes, let currentPaneKey = strongSelf.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey), let paneIndex = availablePanes.firstIndex(of: key), abs(paneIndex - currentIndex) <= 1 {
|
||||
} else {
|
||||
if let pane = strongSelf.currentPanes.removeValue(forKey: key) {
|
||||
@ -953,7 +956,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
paneCompletion()
|
||||
})
|
||||
}
|
||||
pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition)
|
||||
pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1002,6 +1005,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
title = presentationData.strings.PeerInfo_PaneRecommended
|
||||
case .savedMessagesChats:
|
||||
title = presentationData.strings.DialogList_TabTitle
|
||||
case .savedMessages:
|
||||
//TODO:localize
|
||||
title = "Saved"
|
||||
}
|
||||
return PeerInfoPaneSpecifier(key: key, title: title)
|
||||
}, selectedPane: self.currentPaneKey, transitionFraction: self.transitionFraction, transition: transition)
|
||||
@ -1009,7 +1015,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
for (_, pane) in self.pendingPanes {
|
||||
let paneTransition: ContainedViewLayoutTransition = .immediate
|
||||
paneTransition.updateFrame(node: pane.pane.node, frame: paneFrame)
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: paneTransition)
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: paneTransition)
|
||||
}
|
||||
|
||||
var removeKeys: [PeerInfoPaneKey] = []
|
||||
|
@ -429,7 +429,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
self.backgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
|
||||
self.separatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
|
||||
|
||||
let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: self.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
let interfaceState = ChatPresentationInterfaceState(chatWallpaper: .color(0), theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, limitsConfiguration: .defaultValue, fontSize: .regular, bubbleCorners: PresentationChatBubbleCorners(mainRadius: 16.0, auxiliaryRadius: 8.0, mergeBubbleCorners: true), accountPeerId: self.context.account.peerId, mode: .standard(.default), chatLocation: .peer(id: self.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
let panelHeight = self.selectionPanel.updateLayout(width: layout.size.width, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: layout.intrinsicInsets.bottom, additionalSideInsets: UIEdgeInsets(), maxHeight: 0.0, isSecondary: false, transition: transition, interfaceState: interfaceState, metrics: layout.metrics, isMediaInputExpanded: false)
|
||||
|
||||
transition.updateFrame(node: self.selectionPanel, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: panelHeight)))
|
||||
@ -3060,7 +3060,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
return
|
||||
}
|
||||
let presentationData = strongSelf.presentationData
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
let items: [ContextMenuItem]
|
||||
if recommended {
|
||||
@ -5484,7 +5484,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
}
|
||||
if !foundController {
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId), subject: nil, botStart: nil, mode: .standard(previewing: false))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId), subject: nil, botStart: nil, mode: .standard(.default))
|
||||
chatController.hintPlayNextOutgoingGift()
|
||||
controllers.append(chatController)
|
||||
}
|
||||
@ -8709,7 +8709,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
self.supportPeerDisposable.set((supportPeer.get() |> take(1) |> deliverOnMainQueue).startStrict(next: { [weak self] peerId in
|
||||
if let strongSelf = self, let peerId = peerId {
|
||||
push(strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(previewing: false)))
|
||||
push(strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: nil, botStart: nil, mode: .standard(.default)))
|
||||
}
|
||||
}))
|
||||
})]), in: .window(.root))
|
||||
@ -9171,7 +9171,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
proceed(chatController)
|
||||
})
|
||||
} else {
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .none, botStart: nil, mode: .standard(previewing: false))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .none, botStart: nil, mode: .standard(.default))
|
||||
proceed(chatController)
|
||||
}
|
||||
}
|
||||
@ -9230,6 +9230,84 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}), cancel: { [weak self] in
|
||||
self?.deactivateSearch()
|
||||
})
|
||||
} else if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .savedMessagesChats = currentPaneKey {
|
||||
let contentNode = ChatListSearchContainerNode(context: self.context, animationCache: self.context.animationCache, animationRenderer: self.context.animationRenderer, filter: [.removeSearchHeader], requestPeerType: nil, location: .savedMessagesChats, displaySearchFilters: false, hasDownloads: false, initialFilter: .chats, openPeer: { [weak self] peer, _, _, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard let navigationController = self.controller?.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
navigationController: navigationController,
|
||||
context: self.context,
|
||||
chatLocation: .replyThread(ChatReplyThreadMessage(
|
||||
peerId: self.context.account.peerId,
|
||||
threadId: peer.id.toInt64(),
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
unreadCount: 0,
|
||||
initialFilledHoles: IndexSet(),
|
||||
initialAnchor: .automatic,
|
||||
isNotAvailable: false
|
||||
)),
|
||||
subject: nil,
|
||||
keepStack: .always
|
||||
))
|
||||
}, openDisabledPeer: { _, _ in
|
||||
}, openRecentPeerOptions: { _ in
|
||||
}, openMessage: { [weak self] peer, threadId, messageId, deactivateOnAction in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
guard let navigationController = self.controller?.navigationController as? NavigationController else {
|
||||
return
|
||||
}
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
navigationController: navigationController,
|
||||
context: self.context,
|
||||
chatLocation: .replyThread(ChatReplyThreadMessage(
|
||||
peerId: self.context.account.peerId,
|
||||
threadId: peer.id.toInt64(),
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
isForumPost: false,
|
||||
maxMessage: nil,
|
||||
maxReadIncomingMessageId: nil,
|
||||
maxReadOutgoingMessageId: nil,
|
||||
unreadCount: 0,
|
||||
initialFilledHoles: IndexSet(),
|
||||
initialAnchor: .automatic,
|
||||
isNotAvailable: false
|
||||
)),
|
||||
subject: nil,
|
||||
keepStack: .always
|
||||
))
|
||||
}, addContact: { _ in
|
||||
}, peerContextAction: nil, present: { [weak self] c, a in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.controller?.present(c, in: .window(.root), with: a)
|
||||
}, presentInGlobalOverlay: { [weak self] c, a in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.controller?.presentInGlobalOverlay(c, with: a)
|
||||
}, navigationController: self.controller?.navigationController as? NavigationController, parentController: { [weak self] in
|
||||
guard let self else {
|
||||
return nil
|
||||
}
|
||||
return self.controller
|
||||
})
|
||||
|
||||
self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, hasBackground: true, hasSeparator: true, contentNode: contentNode, cancel: { [weak self] in
|
||||
self?.deactivateSearch()
|
||||
})
|
||||
} else {
|
||||
var tagMask: MessageTags = .file
|
||||
if let currentPaneKey = self.paneContainerNode.currentPaneKey {
|
||||
@ -9549,7 +9627,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
))
|
||||
})))
|
||||
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId), subject: .message(id: .id(index.id), highlight: nil, timecode: nil), botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId), subject: .message(id: .id(index.id), highlight: nil, timecode: nil), botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: sourceNode, sourceRect: sourceRect, passthroughTouches: true)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||
strongSelf.controller?.presentInGlobalOverlay(contextController)
|
||||
@ -10063,7 +10141,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
|
||||
let navigationBarHeight: CGFloat = !self.isSettings && layout.isModalOverlay ? 56.0 : 44.0
|
||||
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition)
|
||||
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.headerNode.navigationButtonContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight)))
|
||||
|
||||
@ -10088,7 +10166,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
if self.state.selectedMessageIds == nil {
|
||||
if let currentPaneKey = self.paneContainerNode.currentPaneKey {
|
||||
switch currentPaneKey {
|
||||
case .files, .music, .links, .members:
|
||||
case .files, .music, .links, .members, .savedMessagesChats:
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
||||
case .media:
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true))
|
||||
|
@ -482,6 +482,7 @@ final class PeerInfoStoryGridScreenComponent: Component {
|
||||
topInset: environment.navigationHeight,
|
||||
sideInset: environment.safeInsets.left,
|
||||
bottomInset: bottomInset,
|
||||
deviceMetrics: environment.deviceMetrics,
|
||||
visibleHeight: availableSize.height,
|
||||
isScrollingLockedAtTop: false,
|
||||
expandProgress: 1.0,
|
||||
|
@ -950,7 +950,7 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
|
||||
public private(set) var isSelectionModeActive: Bool
|
||||
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
|
||||
private let ready = Promise<Bool>()
|
||||
private var didSetReady: Bool = false
|
||||
@ -1730,12 +1730,12 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
private func updateHistory(items: SparseItemGrid.Items, synchronous: Bool, reloadAtTop: Bool) {
|
||||
self.items = items
|
||||
|
||||
if let (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
if let (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
var gridSnapshot: UIView?
|
||||
if reloadAtTop {
|
||||
gridSnapshot = self.itemGrid.view.snapshotView(afterScreenUpdates: false)
|
||||
}
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: false, transition: .immediate)
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: false, transition: .immediate)
|
||||
self.updateSelectedItems(animated: false)
|
||||
if let gridSnapshot = gridSnapshot {
|
||||
self.view.addSubview(gridSnapshot)
|
||||
@ -2006,8 +2006,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
||||
}
|
||||
}
|
||||
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
transition.updateFrame(node: self.contextGestureContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
|
||||
|
@ -1101,7 +1101,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
||||
return self._itemInteraction!
|
||||
}
|
||||
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
private var currentParams: (size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData)?
|
||||
|
||||
private let ready = Promise<Bool>()
|
||||
private var didSetReady: Bool = false
|
||||
@ -1605,7 +1605,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
||||
|
||||
self.presentationDataDisposable = (self.context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
guard let strongSelf = self, let (size, topInset, sideInset, bottomInset, _, _, _, _) = strongSelf.currentParams else {
|
||||
guard let strongSelf = self, let (size, topInset, sideInset, bottomInset, _, _, _, _, _) = strongSelf.currentParams else {
|
||||
return
|
||||
}
|
||||
strongSelf.itemGridBinding.updatePresentationData(presentationData: presentationData)
|
||||
@ -1742,12 +1742,12 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
||||
private func updateHistory(items: SparseItemGrid.Items, synchronous: Bool, reloadAtTop: Bool) {
|
||||
self.items = items
|
||||
|
||||
if let (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
if let (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData) = self.currentParams {
|
||||
var gridSnapshot: UIView?
|
||||
if reloadAtTop {
|
||||
gridSnapshot = self.itemGrid.view.snapshotView(afterScreenUpdates: false)
|
||||
}
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: false, transition: .immediate)
|
||||
self.update(size: size, topInset: topInset, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expandProgress, presentationData: presentationData, synchronous: false, transition: .immediate)
|
||||
if let gridSnapshot = gridSnapshot {
|
||||
self.view.addSubview(gridSnapshot)
|
||||
gridSnapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak gridSnapshot] _ in
|
||||
@ -2036,7 +2036,7 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
||||
switch self.contentType {
|
||||
case .files, .music, .voiceAndVideoMessages:
|
||||
self.itemGrid.forEachVisibleItem { item in
|
||||
guard let itemView = item.view as? ItemView, let (size, topInset, sideInset, bottomInset, _, _, _, _) = self.currentParams else {
|
||||
guard let itemView = item.view as? ItemView, let (size, topInset, sideInset, bottomInset, _, _, _, _, _) = self.currentParams else {
|
||||
return
|
||||
}
|
||||
if let item = itemView.item {
|
||||
@ -2093,8 +2093,8 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
|
||||
}
|
||||
}
|
||||
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
public func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.currentParams = (size, topInset, sideInset, bottomInset, deviceMetrics, visibleHeight, isScrollingLockedAtTop, expandProgress, presentationData)
|
||||
|
||||
transition.updateFrame(node: self.contextGestureContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
|
||||
|
@ -124,7 +124,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
self.animationCache = context.animationCache
|
||||
self.animationRenderer = context.animationRenderer
|
||||
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(.default), chatLocation: .peer(id: PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
|
||||
self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds) }
|
||||
self.presentationInterfaceStatePromise.set(self.presentationInterfaceState)
|
||||
@ -371,7 +371,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
chatLocation: .peer(id: strongSelf.context.account.peerId),
|
||||
subject: .messageOptions(peerIds: peerIds, ids: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: .forward(ChatControllerSubject.MessageOptionsInfo.Forward(options: forwardOptions))),
|
||||
botStart: nil,
|
||||
mode: .standard(previewing: true)
|
||||
mode: .standard(.previewing)
|
||||
)
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
|
@ -259,7 +259,7 @@ final class StoryItemSetContainerSendMessage {
|
||||
fontSize: presentationData.chatFontSize,
|
||||
bubbleCorners: presentationData.chatBubbleCorners,
|
||||
accountPeerId: context.account.peerId,
|
||||
mode: .standard(previewing: false),
|
||||
mode: .standard(.default),
|
||||
chatLocation: .peer(id: context.account.peerId),
|
||||
subject: nil,
|
||||
peerNearbyData: nil,
|
||||
|
@ -135,6 +135,8 @@ extension ChatControllerImpl {
|
||||
navigateToLocation = .peer(peer)
|
||||
}
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: navigateToLocation, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil), keepStack: .always))
|
||||
|
||||
completion?()
|
||||
})
|
||||
} else if case let .peer(peerId) = self.chatLocation, let messageId = messageLocation.messageId, (messageId.peerId != peerId && !forceInCurrentChat) || (isScheduledMessages && messageId.id != 0 && !Namespaces.Message.allScheduled.contains(messageId.namespace)) {
|
||||
let _ = (self.context.engine.data.get(
|
||||
@ -158,6 +160,8 @@ extension ChatControllerImpl {
|
||||
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: chatLocation, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: quote), timecode: nil), keepStack: .always))
|
||||
}
|
||||
|
||||
completion?()
|
||||
})
|
||||
} else if forceInCurrentChat {
|
||||
if let _ = fromId, let fromIndex = fromIndex, rememberInStack {
|
||||
@ -308,17 +312,19 @@ extension ChatControllerImpl {
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] index in
|
||||
if let strongSelf = self, let index = index.0 {
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToMessage(from: scrollFromIndex, to: index, animated: animated, quote: quote, scrollPosition: scrollPosition)
|
||||
completion?()
|
||||
} else if index.1 {
|
||||
if !progressStarted {
|
||||
progressStarted = true
|
||||
progressDisposable.set(progressSignal.start())
|
||||
}
|
||||
} else if let strongSelf = self {
|
||||
strongSelf.controllerInteraction?.displayUndo(.info(title: nil, text: strongSelf.presentationData.strings.Conversation_MessageDoesntExist, timeout: nil, customUndoText: nil))
|
||||
}
|
||||
}, completed: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.loadingMessage.set(.single(nil))
|
||||
}
|
||||
completion?()
|
||||
}))
|
||||
cancelImpl = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
|
@ -100,7 +100,7 @@ private func chatForwardOptions(selfController: ChatControllerImpl, sourceNode:
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [peerId], ids: selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: .forward(ChatControllerSubject.MessageOptionsInfo.Forward(options: forwardOptions))), botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [peerId], ids: selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: .forward(ChatControllerSubject.MessageOptionsInfo.Forward(options: forwardOptions))), botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
let messageIds = selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
@ -508,7 +508,7 @@ private func chatReplyOptions(selfController: ChatControllerImpl, sourceNode: AS
|
||||
}
|
||||
|> distinctUntilChanged)
|
||||
|
||||
guard let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [replySubject.messageId.peerId], ids: [replySubject.messageId], info: .reply(ChatControllerSubject.MessageOptionsInfo.Reply(quote: replyQuote, selectionState: selectionState))), botStart: nil, mode: .standard(previewing: true)) as? ChatControllerImpl else {
|
||||
guard let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [replySubject.messageId.peerId], ids: [replySubject.messageId], info: .reply(ChatControllerSubject.MessageOptionsInfo.Reply(quote: replyQuote, selectionState: selectionState))), botStart: nil, mode: .standard(.previewing)) as? ChatControllerImpl else {
|
||||
return nil
|
||||
}
|
||||
chatController.canReadHistory.set(false)
|
||||
@ -736,7 +736,7 @@ private func chatLinkOptions(selfController: ChatControllerImpl, sourceNode: ASD
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
guard let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [peerId], ids: selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: .link(ChatControllerSubject.MessageOptionsInfo.Link(options: linkOptions))), botStart: nil, mode: .standard(previewing: true)) as? ChatControllerImpl else {
|
||||
guard let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [peerId], ids: selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: .link(ChatControllerSubject.MessageOptionsInfo.Link(options: linkOptions))), botStart: nil, mode: .standard(.previewing)) as? ChatControllerImpl else {
|
||||
return nil
|
||||
}
|
||||
chatController.canReadHistory.set(false)
|
||||
|
@ -565,7 +565,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
var performTextSelectionAction: ((Message?, Bool, NSAttributedString, TextSelectionAction) -> Void)?
|
||||
var performOpenURL: ((Message?, String, Promise<Bool>?) -> Void)?
|
||||
|
||||
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, botAppStart: ChatControllerInitialBotAppStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [ChatNavigationStackItem] = []) {
|
||||
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, attachBotStart: ChatControllerInitialAttachBotStart? = nil, botAppStart: ChatControllerInitialBotAppStart? = nil, mode: ChatControllerPresentationMode = .standard(.default), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [ChatNavigationStackItem] = []) {
|
||||
let _ = ChatControllerCount.modify { value in
|
||||
return value + 1
|
||||
}
|
||||
@ -583,7 +583,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
var useSharedAnimationPhase = false
|
||||
switch mode {
|
||||
case .standard(false):
|
||||
case .standard(.default):
|
||||
useSharedAnimationPhase = true
|
||||
default:
|
||||
break
|
||||
@ -643,7 +643,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
let navigationBarPresentationData: NavigationBarPresentationData?
|
||||
switch mode {
|
||||
case .inline:
|
||||
case .inline, .standard(.embedded):
|
||||
navigationBarPresentationData = nil
|
||||
default:
|
||||
navigationBarPresentationData = NavigationBarPresentationData(presentationData: self.presentationData, hideBackground: self.context.sharedContext.immediateExperimentalUISettings.playerEmbedding ? true : false, hideBadge: false)
|
||||
@ -4597,7 +4597,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
return
|
||||
}
|
||||
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(id: peer.id), subject: nil, botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
var items: [ContextMenuItem] = [
|
||||
@ -5264,6 +5264,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
imageOverride = .savedMessagesIcon
|
||||
} else if peer.id.isReplies {
|
||||
imageOverride = .repliesIcon
|
||||
} else if peer.id.isAnonymousSavedMessages {
|
||||
imageOverride = .anonymousSavedMessagesIcon
|
||||
} else if peer.isDeleted {
|
||||
imageOverride = .deletedIcon
|
||||
} else {
|
||||
@ -5623,7 +5625,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
})
|
||||
|
||||
if case .standard(previewing: false) = mode, let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
|
||||
if case .standard(.default) = mode, let channel = renderedPeer?.chatMainPeer as? TelegramChannel, case .broadcast = channel.info {
|
||||
var isRegularChat = false
|
||||
if let subject = subject {
|
||||
if case .message = subject {
|
||||
@ -5897,6 +5899,19 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
strongSelf.peerView = peerView
|
||||
|
||||
let imageOverride: AvatarNodeImageOverride?
|
||||
if strongSelf.context.account.peerId == savedMessagesPeerId {
|
||||
imageOverride = .savedMessagesIcon
|
||||
} else if savedMessagesPeerId.isReplies {
|
||||
imageOverride = .repliesIcon
|
||||
} else if savedMessagesPeerId.isAnonymousSavedMessages {
|
||||
imageOverride = .anonymousSavedMessagesIcon
|
||||
} else if let peer = savedMessagesPeer?.peer, peer.isDeleted {
|
||||
imageOverride = .deletedIcon
|
||||
} else {
|
||||
imageOverride = nil
|
||||
}
|
||||
|
||||
if strongSelf.isNodeLoaded {
|
||||
strongSelf.chatDisplayNode.overlayTitle = strongSelf.overlayTitle
|
||||
}
|
||||
@ -5908,7 +5923,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}.updatedSavedMessagesTopicPeer(savedMessagesPeer?.peer)
|
||||
})
|
||||
|
||||
(strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: savedMessagesPeer?.peer)
|
||||
(strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: savedMessagesPeer?.peer, overrideImage: imageOverride)
|
||||
(strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.contextActionIsEnabled = false
|
||||
strongSelf.chatInfoNavigationButton?.buttonItem.accessibilityLabel = strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile
|
||||
} else {
|
||||
@ -6619,7 +6634,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
|
||||
self.networkStateDisposable = (context.account.networkState |> deliverOnMainQueue).startStrict(next: { [weak self] state in
|
||||
if let strongSelf = self, case .standard(previewing: false) = strongSelf.presentationInterfaceState.mode {
|
||||
if let strongSelf = self, case .standard(.default) = strongSelf.presentationInterfaceState.mode {
|
||||
strongSelf.chatTitleView?.networkState = state
|
||||
}
|
||||
})
|
||||
@ -6746,9 +6761,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
func themeAndStringsUpdated() {
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
switch self.presentationInterfaceState.mode {
|
||||
case .standard:
|
||||
case let .standard(standardMode):
|
||||
switch standardMode {
|
||||
case .embedded:
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
default:
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
self.deferScreenEdgeGestures = []
|
||||
}
|
||||
case .overlay:
|
||||
self.statusBar.statusBarStyle = .Hide
|
||||
self.deferScreenEdgeGestures = [.top]
|
||||
@ -7180,7 +7200,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
if closeOnEmpty {
|
||||
self.chatDisplayNode.historyNode.setLoadStateUpdated({ [weak self] state, _ in
|
||||
self.chatDisplayNode.historyNode.addSetLoadStateUpdated({ [weak self] state, _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -7534,7 +7554,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
threadData = .single(nil)
|
||||
}
|
||||
|
||||
if case .standard(previewing: true) = self.presentationInterfaceState.mode {
|
||||
if case .standard(.previewing) = self.presentationInterfaceState.mode {
|
||||
|
||||
} else if peerId.namespace != Namespaces.Peer.SecretChat && peerId != context.account.peerId && self.subject != .scheduledMessages {
|
||||
self.premiumGiftSuggestionDisposable = (ApplicationSpecificNotice.dismissedPremiumGiftSuggestion(accountManager: self.context.sharedContext.accountManager, peerId: peerId)
|
||||
@ -10576,7 +10596,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
chatLocation = .peer(id: peerId)
|
||||
}
|
||||
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: chatLocation, subject: .pinnedMessages(id: pinnedMessage.message.id), botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: chatLocation, subject: .pinnedMessages(id: pinnedMessage.message.id), botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
|
||||
@ -10967,7 +10987,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
self.chatUnreadMentionCountDisposable = (self.context.account.viewTracker.unseenPersonalMessagesAndReactionCount(peerId: peerId, threadId: nil) |> deliverOnMainQueue).startStrict(next: { [weak self] mentionCount, reactionCount in
|
||||
if let strongSelf = self {
|
||||
if case let .standard(previewing) = strongSelf.presentationInterfaceState.mode, previewing {
|
||||
if case .standard(.previewing) = strongSelf.presentationInterfaceState.mode {
|
||||
strongSelf.chatDisplayNode.navigateButtons.mentionCount = 0
|
||||
strongSelf.chatDisplayNode.navigateButtons.reactionsCount = 0
|
||||
} else {
|
||||
@ -10979,7 +10999,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
} else if let peerId = self.chatLocation.peerId, let threadId = self.chatLocation.threadId {
|
||||
self.chatUnreadMentionCountDisposable = (self.context.account.viewTracker.unseenPersonalMessagesAndReactionCount(peerId: peerId, threadId: threadId) |> deliverOnMainQueue).startStrict(next: { [weak self] mentionCount, reactionCount in
|
||||
if let strongSelf = self {
|
||||
if case let .standard(previewing) = strongSelf.presentationInterfaceState.mode, previewing {
|
||||
if case .standard(.previewing) = strongSelf.presentationInterfaceState.mode {
|
||||
strongSelf.chatDisplayNode.navigateButtons.mentionCount = 0
|
||||
strongSelf.chatDisplayNode.navigateButtons.reactionsCount = 0
|
||||
} else {
|
||||
@ -11387,7 +11407,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
}
|
||||
|
||||
if case .standard(false) = self.presentationInterfaceState.mode, self.raiseToListen == nil {
|
||||
if case .standard(.default) = self.presentationInterfaceState.mode, self.raiseToListen == nil {
|
||||
self.raiseToListen = RaiseToListenManager(shouldActivate: { [weak self] in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded && strongSelf.canReadHistoryValue, strongSelf.presentationInterfaceState.interfaceState.editMessage == nil, strongSelf.playlistStateAndType == nil {
|
||||
if !strongSelf.context.sharedContext.currentMediaInputSettings.with({ $0.enableRaiseToSpeak }) {
|
||||
@ -16044,7 +16064,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})))
|
||||
}
|
||||
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .message(id: .timestamp(timestamp), highlight: nil, timecode: nil), botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .message(id: .timestamp(timestamp), highlight: nil, timecode: nil), botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
|
||||
|
@ -263,7 +263,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
private var isLoadingValue: Bool = false
|
||||
private var isLoadingEarlier: Bool = false
|
||||
private func updateIsLoading(isLoading: Bool, earlier: Bool, animated: Bool) {
|
||||
let useLoadingPlaceholder = self.chatLocation.peerId?.namespace != Namespaces.Peer.CloudUser
|
||||
var useLoadingPlaceholder = self.chatLocation.peerId?.namespace != Namespaces.Peer.CloudUser
|
||||
if case let .replyThread(message) = self.chatLocation, message.peerId == self.context.account.peerId {
|
||||
useLoadingPlaceholder = true
|
||||
}
|
||||
|
||||
let updated = isLoading != self.isLoadingValue || (isLoading && earlier && !self.isLoadingEarlier)
|
||||
|
||||
@ -1342,7 +1345,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
let previewing: Bool
|
||||
if case .standard(true) = self.chatPresentationInterfaceState.mode {
|
||||
if case .standard(.previewing) = self.chatPresentationInterfaceState.mode {
|
||||
previewing = true
|
||||
} else {
|
||||
previewing = false
|
||||
@ -1366,9 +1369,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
insets = layout.insets(options: [.input])
|
||||
}
|
||||
|
||||
if case .overlay = self.chatPresentationInterfaceState.mode {
|
||||
switch self.chatPresentationInterfaceState.mode {
|
||||
case .standard(.embedded):
|
||||
break
|
||||
case .overlay:
|
||||
insets.top = 44.0
|
||||
} else {
|
||||
default:
|
||||
insets.top += navigationBarHeight
|
||||
}
|
||||
|
||||
@ -1993,6 +1999,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
inputPanelUpdateTransition = .immediate
|
||||
}
|
||||
|
||||
if case .standard(.embedded) = self.chatPresentationInterfaceState.mode {
|
||||
self.inputPanelBackgroundNode.isHidden = true
|
||||
self.inputPanelBackgroundSeparatorNode.isHidden = true
|
||||
self.inputPanelBottomBackgroundSeparatorNode.isHidden = true
|
||||
}
|
||||
self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition, beginWithCurrentState: true)
|
||||
self.inputPanelBottomBackgroundSeparatorBaseOffset = intrinsicInputPanelBackgroundNodeSize.height
|
||||
inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: UIScreenPixel)), beginWithCurrentState: true)
|
||||
@ -3066,7 +3077,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
switch self.chatPresentationInterfaceState.mode {
|
||||
case .standard(previewing: true):
|
||||
case .standard(.previewing):
|
||||
if let subject = self.controller?.subject, case let .messageOptions(_, _, info) = subject, case .reply = info {
|
||||
if let controller = self.controller {
|
||||
if let result = controller.presentationContext.hitTest(view: self.view, point: point, with: event) {
|
||||
|
@ -616,6 +616,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
|
||||
public private(set) var loadState: ChatHistoryNodeLoadState?
|
||||
private var loadStateUpdated: ((ChatHistoryNodeLoadState, Bool) -> Void)?
|
||||
private var additionalLoadStateUpdated: [(ChatHistoryNodeLoadState, Bool) -> Void] = []
|
||||
|
||||
public private(set) var hasPlentyOfMessages: Bool = false
|
||||
public var hasPlentyOfMessagesUpdated: ((Bool) -> Void)?
|
||||
@ -1507,6 +1508,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
if strongSelf.loadState != loadState {
|
||||
strongSelf.loadState = loadState
|
||||
strongSelf.loadStateUpdated?(loadState, false)
|
||||
for f in strongSelf.additionalLoadStateUpdated {
|
||||
f(loadState, false)
|
||||
}
|
||||
}
|
||||
|
||||
let historyState: ChatHistoryNodeHistoryState = .loading
|
||||
@ -1949,6 +1953,10 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
self.loadStateUpdated = f
|
||||
}
|
||||
|
||||
public func addSetLoadStateUpdated(_ f: @escaping (ChatHistoryNodeLoadState, Bool) -> Void) {
|
||||
self.additionalLoadStateUpdated.append(f)
|
||||
}
|
||||
|
||||
private func maybeUpdateOverscrollAction(offset: CGFloat?) {
|
||||
if self.freezeOverscrollControl {
|
||||
return
|
||||
@ -2966,6 +2974,9 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
if self.loadState != loadState {
|
||||
self.loadState = loadState
|
||||
self.loadStateUpdated?(loadState, transition.options.contains(.AnimateInsertion))
|
||||
for f in self.additionalLoadStateUpdated {
|
||||
f(loadState, transition.options.contains(.AnimateInsertion))
|
||||
}
|
||||
}
|
||||
|
||||
let isEmpty = transition.historyView.originalView.entries.isEmpty || loadState == .empty(.botInfo)
|
||||
@ -3291,7 +3302,11 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
||||
}
|
||||
}
|
||||
strongSelf.loadState = loadState
|
||||
strongSelf.loadStateUpdated?(loadState, animated || transition.animateIn || animateIn)
|
||||
let isAnimated = animated || transition.animateIn || animateIn
|
||||
strongSelf.loadStateUpdated?(loadState, isAnimated)
|
||||
for f in strongSelf.additionalLoadStateUpdated {
|
||||
f(loadState, isAnimated)
|
||||
}
|
||||
}
|
||||
|
||||
var hasPlentyOfMessages = false
|
||||
|
@ -10,7 +10,7 @@ import ForwardAccessoryPanelNode
|
||||
import ReplyAccessoryPanelNode
|
||||
|
||||
func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: AccessoryPanelNode?, chatControllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> AccessoryPanelNode? {
|
||||
if case .standard(previewing: true) = chatPresentationInterfaceState.mode {
|
||||
if case .standard(.previewing) = chatPresentationInterfaceState.mode {
|
||||
return nil
|
||||
}
|
||||
if let _ = chatPresentationInterfaceState.interfaceState.selectionState {
|
||||
|
@ -267,6 +267,8 @@ func canReplyInChat(_ chatPresentationInterfaceState: ChatPresentationInterfaceS
|
||||
switch chatPresentationInterfaceState.mode {
|
||||
case .inline:
|
||||
return false
|
||||
case .standard(.embedded):
|
||||
return false
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -424,6 +426,11 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
return .single(ContextController.Items(content: .list([])))
|
||||
}
|
||||
|
||||
var isEmbeddedMode = false
|
||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||
isEmbeddedMode = true
|
||||
}
|
||||
|
||||
var hasExpandedAudioTranscription = false
|
||||
if let messageNode = messageNode as? ChatMessageBubbleItemNode {
|
||||
hasExpandedAudioTranscription = messageNode.hasExpandedAudioTranscription()
|
||||
@ -509,7 +516,6 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
actions.append(.separator)
|
||||
|
||||
if chatPresentationInterfaceState.copyProtectionEnabled {
|
||||
|
||||
} else {
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuCopy, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.actionSheet.primaryTextColor)
|
||||
@ -769,7 +775,20 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
loggingSettings = LoggingSettings.defaultSettings
|
||||
}
|
||||
|
||||
return (MessageContextMenuData(starStatus: stickerSaveStatus, canReply: canReply, canPin: canPin, canEdit: canEdit, canSelect: canSelect, resourceStatus: resourceStatus, messageActions: messageActions), updatingMessageMedia, infoSummaryData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList, accountPeer)
|
||||
return (MessageContextMenuData(
|
||||
starStatus: stickerSaveStatus,
|
||||
canReply: canReply && !isEmbeddedMode,
|
||||
canPin: canPin && !isEmbeddedMode,
|
||||
canEdit: canEdit && !isEmbeddedMode,
|
||||
canSelect: canSelect && !isEmbeddedMode,
|
||||
resourceStatus: resourceStatus,
|
||||
messageActions: isEmbeddedMode ? ChatAvailableMessageActions(
|
||||
options: [],
|
||||
banAuthor: nil,
|
||||
disableDelete: true,
|
||||
isCopyProtected: messageActions.isCopyProtected
|
||||
) : messageActions
|
||||
), updatingMessageMedia, infoSummaryData, appConfig, isMessageRead, messageViewsPrivacyTips, availableReactions, translationSettings, loggingSettings, notificationSoundList, accountPeer)
|
||||
}
|
||||
|
||||
return dataSignal
|
||||
|
@ -10,6 +10,10 @@ import ChatChannelSubscriberInputPanelNode
|
||||
import ChatMessageSelectionInputPanelNode
|
||||
|
||||
func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputPanelNode?, currentSecondaryPanel: ChatInputPanelNode?, textInputPanelNode: ChatTextInputPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> (primary: ChatInputPanelNode?, secondary: ChatInputPanelNode?) {
|
||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
if let renderedPeer = chatPresentationInterfaceState.renderedPeer, renderedPeer.peer?.restrictionText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) != nil {
|
||||
return (nil, nil)
|
||||
}
|
||||
@ -118,6 +122,16 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
||||
}
|
||||
|
||||
if case let .replyThread(message) = chatPresentationInterfaceState.chatLocation, message.peerId == context.account.peerId {
|
||||
if EnginePeer.Id(message.threadId).isAnonymousSavedMessages {
|
||||
if let currentPanel = (currentPanel as? ChatRestrictedInputPanelNode) ?? (currentSecondaryPanel as? ChatRestrictedInputPanelNode) {
|
||||
return (currentPanel, nil)
|
||||
} else {
|
||||
let panel = ChatRestrictedInputPanelNode()
|
||||
panel.context = context
|
||||
panel.interfaceInteraction = interfaceInteraction
|
||||
return (panel, nil)
|
||||
}
|
||||
} else {
|
||||
if let currentPanel = (currentPanel as? ChatChannelSubscriberInputPanelNode) ?? (currentSecondaryPanel as? ChatChannelSubscriberInputPanelNode) {
|
||||
return (currentPanel, nil)
|
||||
} else {
|
||||
@ -127,6 +141,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
||||
return (panel, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let secretChat = peer as? TelegramSecretChat {
|
||||
switch secretChat.embeddedState {
|
||||
|
@ -142,7 +142,7 @@ func rightNavigationButtonForChatInterfaceState(context: AccountContext, present
|
||||
return chatInfoNavigationButton
|
||||
}
|
||||
|
||||
if case .standard(true) = presentationInterfaceState.mode {
|
||||
if case .standard(.previewing) = presentationInterfaceState.mode {
|
||||
return chatInfoNavigationButton
|
||||
} else if let peer = presentationInterfaceState.renderedPeer?.peer {
|
||||
if presentationInterfaceState.accountPeerId == peer.id {
|
||||
|
@ -46,7 +46,10 @@ final class ChatRestrictedInputPanelNode: ChatInputPanelNode {
|
||||
|
||||
var iconImage: UIImage?
|
||||
|
||||
if let threadData = interfaceState.threadData, threadData.isClosed {
|
||||
if case let .replyThread(message) = interfaceState.chatLocation, message.peerId == self.context?.account.peerId {
|
||||
//TODO:localize
|
||||
self.textNode.attributedText = NSAttributedString(string: "Senders of these messages restricted to link\ntheir name when forwarding.", font: Font.regular(13.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
|
||||
} else if let threadData = interfaceState.threadData, threadData.isClosed {
|
||||
iconImage = PresentationResourcesChat.chatPanelLockIcon(interfaceState.theme)
|
||||
self.textNode.attributedText = NSAttributedString(string: interfaceState.strings.Chat_PanelTopicClosedText, font: Font.regular(15.0), textColor: interfaceState.theme.chat.inputPanel.secondaryTextColor)
|
||||
} else if let channel = interfaceState.renderedPeer?.peer as? TelegramChannel, channel.flags.contains(.isForum), case .peer = interfaceState.chatLocation {
|
||||
|
@ -251,7 +251,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
switch item.content {
|
||||
case let .peer(peerData):
|
||||
if let message = peerData.messages.first {
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerData.peer.peerId), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil), botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerData.peer.peerId), subject: .message(id: .id(message.id), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil), botStart: nil, mode: .standard(.previewing))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(ContextController.Items(content: .list([]))), gesture: gesture)
|
||||
presentInGlobalOverlay(contextController)
|
||||
|
@ -38,7 +38,7 @@ private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceh
|
||||
|
||||
init(context: AccountContext) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: context.account.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: context.account.peerId, mode: .standard(.default), chatLocation: .peer(id: context.account.peerId), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
|
||||
self.wallpaperBackgroundNode = createWallpaperBackgroundNode(context: context, forChatDisplay: true, useSharedAnimationPhase: true)
|
||||
self.emptyNode = ChatEmptyNode(context: context, interaction: nil)
|
||||
@ -51,7 +51,7 @@ private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceh
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.presentationInterfaceState.limitsConfiguration, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.presentationInterfaceState.accountPeerId, mode: .standard(previewing: false), chatLocation: self.presentationInterfaceState.chatLocation, subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.presentationInterfaceState.limitsConfiguration, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.presentationInterfaceState.accountPeerId, mode: .standard(.default), chatLocation: self.presentationInterfaceState.chatLocation, subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
|
||||
|
||||
self.wallpaperBackgroundNode.update(wallpaper: presentationData.chatWallpaper, animated: false)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user