mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Saved messages view as chats
This commit is contained in:
parent
ea9c9ae777
commit
4bd4884887
@ -881,7 +881,8 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
hasUnseenCloseFriends: stats.hasUnseenCloseFriends
|
hasUnseenCloseFriends: stats.hasUnseenCloseFriends
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
requiresPremiumForMessaging: requiresPremiumForMessaging
|
requiresPremiumForMessaging: requiresPremiumForMessaging,
|
||||||
|
displayAsTopicList: false
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: tagMask == nil ? header : nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
case let .addContact(phoneNumber, theme, strings):
|
case let .addContact(phoneNumber, theme, strings):
|
||||||
@ -3743,7 +3744,8 @@ public final class ChatListSearchShimmerNode: ASDisplayNode {
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||||
case .media:
|
case .media:
|
||||||
return nil
|
return nil
|
||||||
|
@ -208,7 +208,8 @@ public final class ChatListShimmerNode: ASDisplayNode {
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
)), editing: false, hasActiveRevealControls: false, selected: false, header: nil, enableContextActions: false, hiddenOffset: false, interaction: interaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +97,7 @@ public enum ChatListItemContent {
|
|||||||
public var autoremoveTimeout: Int32?
|
public var autoremoveTimeout: Int32?
|
||||||
public var storyState: StoryState?
|
public var storyState: StoryState?
|
||||||
public var requiresPremiumForMessaging: Bool
|
public var requiresPremiumForMessaging: Bool
|
||||||
|
public var displayAsTopicList: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
messages: [EngineMessage],
|
messages: [EngineMessage],
|
||||||
@ -117,7 +118,8 @@ public enum ChatListItemContent {
|
|||||||
topForumTopicItems: [EngineChatList.ForumTopicData],
|
topForumTopicItems: [EngineChatList.ForumTopicData],
|
||||||
autoremoveTimeout: Int32?,
|
autoremoveTimeout: Int32?,
|
||||||
storyState: StoryState?,
|
storyState: StoryState?,
|
||||||
requiresPremiumForMessaging: Bool
|
requiresPremiumForMessaging: Bool,
|
||||||
|
displayAsTopicList: Bool
|
||||||
) {
|
) {
|
||||||
self.messages = messages
|
self.messages = messages
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
@ -138,6 +140,7 @@ public enum ChatListItemContent {
|
|||||||
self.autoremoveTimeout = autoremoveTimeout
|
self.autoremoveTimeout = autoremoveTimeout
|
||||||
self.storyState = storyState
|
self.storyState = storyState
|
||||||
self.requiresPremiumForMessaging = requiresPremiumForMessaging
|
self.requiresPremiumForMessaging = requiresPremiumForMessaging
|
||||||
|
self.displayAsTopicList = displayAsTopicList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1417,11 +1420,17 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
} else if peer.isDeleted {
|
} else if peer.isDeleted {
|
||||||
overrideImage = .deletedIcon
|
overrideImage = .deletedIcon
|
||||||
}
|
}
|
||||||
var isForum = false
|
var isForumAvatar = false
|
||||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
if case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
||||||
isForum = true
|
isForumAvatar = true
|
||||||
}
|
}
|
||||||
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, clipStyle: isForum ? .roundedRect : .round, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0))
|
if case let .peer(data) = item.content {
|
||||||
|
if data.displayAsTopicList {
|
||||||
|
isForumAvatar = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, clipStyle: isForumAvatar ? .roundedRect : .round, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0))
|
||||||
|
|
||||||
if peer.isPremium && peer.id != item.context.account.peerId {
|
if peer.isPremium && peer.id != item.context.account.peerId {
|
||||||
let context = item.context
|
let context = item.context
|
||||||
|
@ -427,7 +427,8 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging
|
requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging,
|
||||||
|
displayAsTopicList: peerEntry.displayAsTopicList
|
||||||
)),
|
)),
|
||||||
editing: editing,
|
editing: editing,
|
||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
@ -796,7 +797,8 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
|||||||
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
hasUnseenCloseFriends: storyState.hasUnseenCloseFriends
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging
|
requiresPremiumForMessaging: peerEntry.requiresPremiumForMessaging,
|
||||||
|
displayAsTopicList: peerEntry.displayAsTopicList
|
||||||
)),
|
)),
|
||||||
editing: editing,
|
editing: editing,
|
||||||
hasActiveRevealControls: hasActiveRevealControls,
|
hasActiveRevealControls: hasActiveRevealControls,
|
||||||
@ -1278,6 +1280,8 @@ public final class ChatListNode: ListView {
|
|||||||
public let isMainTab = ValuePromise<Bool>(false, ignoreRepeated: true)
|
public let isMainTab = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||||
private let suggestedChatListNotice = Promise<ChatListNotice?>(nil)
|
private let suggestedChatListNotice = Promise<ChatListNotice?>(nil)
|
||||||
|
|
||||||
|
public var synchronousDrawingWhenNotAnimated: Bool = false
|
||||||
|
|
||||||
public init(context: AccountContext, location: ChatListControllerLocation, chatListFilter: ChatListFilter? = nil, previewing: Bool, fillPreloadItems: Bool, mode: ChatListNodeMode, isPeerEnabled: ((EnginePeer) -> Bool)? = nil, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, disableAnimations: Bool, isInlineMode: Bool, autoSetReady: Bool, isMainTab: Bool?) {
|
public init(context: AccountContext, location: ChatListControllerLocation, chatListFilter: ChatListFilter? = nil, previewing: Bool, fillPreloadItems: Bool, mode: ChatListNodeMode, isPeerEnabled: ((EnginePeer) -> Bool)? = nil, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, disableAnimations: Bool, isInlineMode: Bool, autoSetReady: Bool, isMainTab: Bool?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.location = location
|
self.location = location
|
||||||
@ -1977,39 +1981,6 @@ public final class ChatListNode: ListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currentPeerId: EnginePeer.Id = context.account.peerId
|
let currentPeerId: EnginePeer.Id = context.account.peerId
|
||||||
|
|
||||||
/*let contactList: Signal<EngineContactList?, NoError>
|
|
||||||
if case let .chatList(appendContacts) = mode, appendContacts {
|
|
||||||
contactList = self.context.engine.data.subscribe(TelegramEngine.EngineData.Item.Contacts.List(includePresences: true))
|
|
||||||
|> map(Optional.init)
|
|
||||||
} else {
|
|
||||||
contactList = .single(nil)
|
|
||||||
}
|
|
||||||
let _ = contactList*/
|
|
||||||
|
|
||||||
|
|
||||||
/*let emptyInitialView = ChatListNodeView(
|
|
||||||
originalList: EngineChatList(
|
|
||||||
items: [],
|
|
||||||
groupItems: [],
|
|
||||||
additionalItems: [],
|
|
||||||
hasEarlier: false,
|
|
||||||
hasLater: false,
|
|
||||||
isLoading: false
|
|
||||||
),
|
|
||||||
filteredEntries: [ChatListNodeEntry.HeaderEntry],
|
|
||||||
isLoading: false,
|
|
||||||
filter: nil
|
|
||||||
)
|
|
||||||
let _ = previousView.swap(emptyInitialView)
|
|
||||||
|
|
||||||
let _ = (preparedChatListNodeViewTransition(from: nil, to: emptyInitialView, reason: .initial, previewing: previewing, disableAnimations: disableAnimations, account: context.account, scrollPosition: nil, searchMode: false)
|
|
||||||
|> map { mappedChatListNodeViewListTransition(context: context, nodeInteraction: nodeInteraction, location: location, filterData: nil, mode: mode, isPeerEnabled: nil, transition: $0) }).start(next: { [weak self] value in
|
|
||||||
guard let self else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let _ = self.enqueueTransition(value).start()
|
|
||||||
})*/
|
|
||||||
|
|
||||||
let contacts: Signal<[ChatListContactPeer], NoError>
|
let contacts: Signal<[ChatListContactPeer], NoError>
|
||||||
if case .chatList(groupId: .root) = location, chatListFilter == nil, case .chatList = mode {
|
if case .chatList(groupId: .root) = location, chatListFilter == nil, case .chatList = mode {
|
||||||
@ -3414,7 +3385,7 @@ public final class ChatListNode: ListView {
|
|||||||
|
|
||||||
var options = transition.options
|
var options = transition.options
|
||||||
//options.insert(.Synchronous)
|
//options.insert(.Synchronous)
|
||||||
if self.view.window != nil {
|
if self.view.window != nil || self.synchronousDrawingWhenNotAnimated {
|
||||||
if !options.contains(.AnimateInsertion) {
|
if !options.contains(.AnimateInsertion) {
|
||||||
options.insert(.PreferSynchronousDrawing)
|
options.insert(.PreferSynchronousDrawing)
|
||||||
options.insert(.PreferSynchronousResourceLoading)
|
options.insert(.PreferSynchronousResourceLoading)
|
||||||
|
@ -115,6 +115,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
var revealed: Bool
|
var revealed: Bool
|
||||||
var storyState: ChatListNodeState.StoryState?
|
var storyState: ChatListNodeState.StoryState?
|
||||||
var requiresPremiumForMessaging: Bool
|
var requiresPremiumForMessaging: Bool
|
||||||
|
var displayAsTopicList: Bool
|
||||||
|
|
||||||
init(
|
init(
|
||||||
index: EngineChatList.Item.Index,
|
index: EngineChatList.Item.Index,
|
||||||
@ -140,7 +141,8 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
topForumTopicItems: [EngineChatList.ForumTopicData],
|
topForumTopicItems: [EngineChatList.ForumTopicData],
|
||||||
revealed: Bool,
|
revealed: Bool,
|
||||||
storyState: ChatListNodeState.StoryState?,
|
storyState: ChatListNodeState.StoryState?,
|
||||||
requiresPremiumForMessaging: Bool
|
requiresPremiumForMessaging: Bool,
|
||||||
|
displayAsTopicList: Bool
|
||||||
) {
|
) {
|
||||||
self.index = index
|
self.index = index
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
@ -166,6 +168,7 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
self.revealed = revealed
|
self.revealed = revealed
|
||||||
self.storyState = storyState
|
self.storyState = storyState
|
||||||
self.requiresPremiumForMessaging = requiresPremiumForMessaging
|
self.requiresPremiumForMessaging = requiresPremiumForMessaging
|
||||||
|
self.displayAsTopicList = displayAsTopicList
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: PeerEntryData, rhs: PeerEntryData) -> Bool {
|
static func ==(lhs: PeerEntryData, rhs: PeerEntryData) -> Bool {
|
||||||
@ -281,6 +284,9 @@ enum ChatListNodeEntry: Comparable, Identifiable {
|
|||||||
if lhs.requiresPremiumForMessaging != rhs.requiresPremiumForMessaging {
|
if lhs.requiresPremiumForMessaging != rhs.requiresPremiumForMessaging {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.displayAsTopicList != rhs.displayAsTopicList {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -708,7 +714,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
|||||||
hasUnseenCloseFriends: stats.hasUnseenCloseFriends
|
hasUnseenCloseFriends: stats.hasUnseenCloseFriends
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: entry.displayAsTopicList
|
||||||
))
|
))
|
||||||
|
|
||||||
if let threadInfo, threadInfo.isHidden {
|
if let threadInfo, threadInfo.isHidden {
|
||||||
@ -759,7 +766,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
revealed: false,
|
revealed: false,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)))
|
)))
|
||||||
if foundPinningIndex != 0 {
|
if foundPinningIndex != 0 {
|
||||||
foundPinningIndex -= 1
|
foundPinningIndex -= 1
|
||||||
@ -791,7 +799,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
revealed: false,
|
revealed: false,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
if !filteredAdditionalItemEntries.isEmpty {
|
if !filteredAdditionalItemEntries.isEmpty {
|
||||||
@ -843,7 +852,8 @@ func chatListNodeEntriesForView(view: EngineChatList, state: ChatListNodeState,
|
|||||||
topForumTopicItems: item.item.topForumTopicItems,
|
topForumTopicItems: item.item.topForumTopicItems,
|
||||||
revealed: state.hiddenItemShouldBeTemporaryRevealed || state.editing,
|
revealed: state.hiddenItemShouldBeTemporaryRevealed || state.editing,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)))
|
)))
|
||||||
if pinningIndex != 0 {
|
if pinningIndex != 0 {
|
||||||
pinningIndex -= 1
|
pinningIndex -= 1
|
||||||
|
@ -114,6 +114,8 @@ public func chatListFilterPredicate(filter: ChatListFilterData, accountPeerId: E
|
|||||||
}
|
}
|
||||||
|
|
||||||
func chatListViewForLocation(chatListLocation: ChatListControllerLocation, location: ChatListNodeLocation, account: Account) -> Signal<ChatListNodeViewUpdate, NoError> {
|
func chatListViewForLocation(chatListLocation: ChatListControllerLocation, location: ChatListNodeLocation, account: Account) -> Signal<ChatListNodeViewUpdate, NoError> {
|
||||||
|
let accountPeerId = account.peerId
|
||||||
|
|
||||||
switch chatListLocation {
|
switch chatListLocation {
|
||||||
case let .chatList(groupId):
|
case let .chatList(groupId):
|
||||||
let filterPredicate: ChatListFilterPredicate?
|
let filterPredicate: ChatListFilterPredicate?
|
||||||
@ -129,7 +131,7 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||||||
signal = account.viewTracker.tailChatListView(groupId: groupId._asGroup(), filterPredicate: filterPredicate, count: count)
|
signal = account.viewTracker.tailChatListView(groupId: groupId._asGroup(), filterPredicate: filterPredicate, count: count)
|
||||||
return signal
|
return signal
|
||||||
|> map { view, updateType -> ChatListNodeViewUpdate in
|
|> map { view, updateType -> ChatListNodeViewUpdate in
|
||||||
return ChatListNodeViewUpdate(list: EngineChatList(view), type: updateType, scrollPosition: nil)
|
return ChatListNodeViewUpdate(list: EngineChatList(view, accountPeerId: accountPeerId), type: updateType, scrollPosition: nil)
|
||||||
}
|
}
|
||||||
case let .navigation(index, _):
|
case let .navigation(index, _):
|
||||||
guard case let .chatList(index) = index else {
|
guard case let .chatList(index) = index else {
|
||||||
@ -145,7 +147,7 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||||||
} else {
|
} else {
|
||||||
genericType = updateType
|
genericType = updateType
|
||||||
}
|
}
|
||||||
return ChatListNodeViewUpdate(list: EngineChatList(view), type: genericType, scrollPosition: nil)
|
return ChatListNodeViewUpdate(list: EngineChatList(view, accountPeerId: accountPeerId), type: genericType, scrollPosition: nil)
|
||||||
}
|
}
|
||||||
case let .scroll(index, sourceIndex, scrollPosition, animated, _):
|
case let .scroll(index, sourceIndex, scrollPosition, animated, _):
|
||||||
guard case let .chatList(index) = index else {
|
guard case let .chatList(index) = index else {
|
||||||
@ -165,7 +167,7 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||||||
} else {
|
} else {
|
||||||
genericType = updateType
|
genericType = updateType
|
||||||
}
|
}
|
||||||
return ChatListNodeViewUpdate(list: EngineChatList(view), type: genericType, scrollPosition: scrollPosition)
|
return ChatListNodeViewUpdate(list: EngineChatList(view, accountPeerId: accountPeerId), type: genericType, scrollPosition: scrollPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .forum(peerId):
|
case let .forum(peerId):
|
||||||
@ -292,7 +294,8 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||||||
hasFailed: false,
|
hasFailed: false,
|
||||||
isContact: false,
|
isContact: false,
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyStats: nil
|
storyStats: nil,
|
||||||
|
displayAsTopicList: false
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +359,8 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||||||
hasFailed: false,
|
hasFailed: false,
|
||||||
isContact: false,
|
isContact: false,
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyStats: nil
|
storyStats: nil,
|
||||||
|
displayAsTopicList: false
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ public final class NavigationButtonNode: ContextControllerSourceNode {
|
|||||||
var totalHeight: CGFloat = 0.0
|
var totalHeight: CGFloat = 0.0
|
||||||
for i in 0 ..< self.nodes.count {
|
for i in 0 ..< self.nodes.count {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
nodeOrigin.x += 10.0
|
nodeOrigin.x += 15.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let node = self.nodes[i]
|
let node = self.nodes[i]
|
||||||
|
@ -566,6 +566,9 @@ final class MutableChatListView {
|
|||||||
|
|
||||||
private var currentHiddenPeerIds = Set<PeerId>()
|
private var currentHiddenPeerIds = Set<PeerId>()
|
||||||
|
|
||||||
|
private let displaySavedMessagesAsTopicListPreferencesKey: ValueBoxKey
|
||||||
|
private(set) var displaySavedMessagesAsTopicList: PreferencesEntry?
|
||||||
|
|
||||||
init(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, aroundIndex: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents) {
|
init(postbox: PostboxImpl, currentTransaction: Transaction, groupId: PeerGroupId, filterPredicate: ChatListFilterPredicate?, aroundIndex: ChatListIndex, count: Int, summaryComponents: ChatListEntrySummaryComponents) {
|
||||||
self.groupId = groupId
|
self.groupId = groupId
|
||||||
self.filterPredicate = filterPredicate
|
self.filterPredicate = filterPredicate
|
||||||
@ -574,6 +577,8 @@ final class MutableChatListView {
|
|||||||
|
|
||||||
self.currentHiddenPeerIds = postbox.hiddenChatIds
|
self.currentHiddenPeerIds = postbox.hiddenChatIds
|
||||||
|
|
||||||
|
self.displaySavedMessagesAsTopicListPreferencesKey = postbox.seedConfiguration.displaySavedMessagesAsTopicListPreferencesKey
|
||||||
|
|
||||||
var spaces: [ChatListViewSpace] = [
|
var spaces: [ChatListViewSpace] = [
|
||||||
.group(groupId: self.groupId, pinned: .notPinned, predicate: filterPredicate)
|
.group(groupId: self.groupId, pinned: .notPinned, predicate: filterPredicate)
|
||||||
]
|
]
|
||||||
@ -612,6 +617,8 @@ final class MutableChatListView {
|
|||||||
} else {
|
} else {
|
||||||
self.groupEntries = []
|
self.groupEntries = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.displaySavedMessagesAsTopicList = postbox.preferencesTable.get(key: self.displaySavedMessagesAsTopicListPreferencesKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func reloadGroups(postbox: PostboxImpl) {
|
private func reloadGroups(postbox: PostboxImpl) {
|
||||||
@ -689,6 +696,8 @@ final class MutableChatListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.displaySavedMessagesAsTopicList = postbox.preferencesTable.get(key: self.displaySavedMessagesAsTopicListPreferencesKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func refreshDueToExternalTransaction(postbox: PostboxImpl, currentTransaction: Transaction) -> Bool {
|
func refreshDueToExternalTransaction(postbox: PostboxImpl, currentTransaction: Transaction) -> Bool {
|
||||||
@ -699,12 +708,16 @@ final class MutableChatListView {
|
|||||||
updated = true
|
updated = true
|
||||||
|
|
||||||
let currentGroupEntries = self.groupEntries
|
let currentGroupEntries = self.groupEntries
|
||||||
|
let currentDisplaySavedMessagesAsTopicList = self.displaySavedMessagesAsTopicList
|
||||||
|
|
||||||
self.reloadGroups(postbox: postbox)
|
self.reloadGroups(postbox: postbox)
|
||||||
|
|
||||||
if self.groupEntries != currentGroupEntries {
|
if self.groupEntries != currentGroupEntries {
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
|
if self.displaySavedMessagesAsTopicList != currentDisplaySavedMessagesAsTopicList {
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
return updated
|
return updated
|
||||||
}
|
}
|
||||||
@ -734,6 +747,20 @@ final class MutableChatListView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !transaction.currentPreferencesOperations.isEmpty {
|
||||||
|
for operation in transaction.currentPreferencesOperations {
|
||||||
|
switch operation {
|
||||||
|
case let .update(key, value):
|
||||||
|
if key == self.displaySavedMessagesAsTopicListPreferencesKey {
|
||||||
|
if self.displaySavedMessagesAsTopicList != value {
|
||||||
|
self.displaySavedMessagesAsTopicList = value
|
||||||
|
hasChanges = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if case .root = self.groupId, self.filterPredicate == nil {
|
if case .root = self.groupId, self.filterPredicate == nil {
|
||||||
var invalidatedGroups = false
|
var invalidatedGroups = false
|
||||||
for (groupId, groupOperations) in operations {
|
for (groupId, groupOperations) in operations {
|
||||||
@ -938,6 +965,7 @@ public final class ChatListView {
|
|||||||
public let groupEntries: [ChatListGroupReferenceEntry]
|
public let groupEntries: [ChatListGroupReferenceEntry]
|
||||||
public let earlierIndex: ChatListIndex?
|
public let earlierIndex: ChatListIndex?
|
||||||
public let laterIndex: ChatListIndex?
|
public let laterIndex: ChatListIndex?
|
||||||
|
public let displaySavedMessagesAsTopicList: PreferencesEntry?
|
||||||
|
|
||||||
init(_ mutableView: MutableChatListView) {
|
init(_ mutableView: MutableChatListView) {
|
||||||
self.groupId = mutableView.groupId
|
self.groupId = mutableView.groupId
|
||||||
@ -1006,5 +1034,6 @@ public final class ChatListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.additionalItemEntries = additionalItemEntries
|
self.additionalItemEntries = additionalItemEntries
|
||||||
|
self.displaySavedMessagesAsTopicList = mutableView.displaySavedMessagesAsTopicList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ public final class SeedConfiguration {
|
|||||||
public let isPeerUpgradeMessage: (Message) -> Bool
|
public let isPeerUpgradeMessage: (Message) -> Bool
|
||||||
public let automaticThreadIndexInfo: (PeerId, Int64) -> StoredMessageHistoryThreadInfo?
|
public let automaticThreadIndexInfo: (PeerId, Int64) -> StoredMessageHistoryThreadInfo?
|
||||||
public let customTagsFromAttributes: ([MessageAttribute]) -> [MemoryBuffer]
|
public let customTagsFromAttributes: ([MessageAttribute]) -> [MemoryBuffer]
|
||||||
|
public let displaySavedMessagesAsTopicListPreferencesKey: ValueBoxKey
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
globalMessageIdsPeerIdNamespaces: Set<GlobalMessageIdsNamespace>,
|
globalMessageIdsPeerIdNamespaces: Set<GlobalMessageIdsNamespace>,
|
||||||
@ -109,7 +110,8 @@ public final class SeedConfiguration {
|
|||||||
decodeDisplayPeerAsRegularChat: @escaping (CachedPeerData) -> Bool,
|
decodeDisplayPeerAsRegularChat: @escaping (CachedPeerData) -> Bool,
|
||||||
isPeerUpgradeMessage: @escaping (Message) -> Bool,
|
isPeerUpgradeMessage: @escaping (Message) -> Bool,
|
||||||
automaticThreadIndexInfo: @escaping (PeerId, Int64) -> StoredMessageHistoryThreadInfo?,
|
automaticThreadIndexInfo: @escaping (PeerId, Int64) -> StoredMessageHistoryThreadInfo?,
|
||||||
customTagsFromAttributes: @escaping ([MessageAttribute]) -> [MemoryBuffer]
|
customTagsFromAttributes: @escaping ([MessageAttribute]) -> [MemoryBuffer],
|
||||||
|
displaySavedMessagesAsTopicListPreferencesKey: ValueBoxKey
|
||||||
) {
|
) {
|
||||||
self.globalMessageIdsPeerIdNamespaces = globalMessageIdsPeerIdNamespaces
|
self.globalMessageIdsPeerIdNamespaces = globalMessageIdsPeerIdNamespaces
|
||||||
self.initializeChatListWithHole = initializeChatListWithHole
|
self.initializeChatListWithHole = initializeChatListWithHole
|
||||||
@ -135,5 +137,6 @@ public final class SeedConfiguration {
|
|||||||
self.isPeerUpgradeMessage = isPeerUpgradeMessage
|
self.isPeerUpgradeMessage = isPeerUpgradeMessage
|
||||||
self.automaticThreadIndexInfo = automaticThreadIndexInfo
|
self.automaticThreadIndexInfo = automaticThreadIndexInfo
|
||||||
self.customTagsFromAttributes = customTagsFromAttributes
|
self.customTagsFromAttributes = customTagsFromAttributes
|
||||||
|
self.displaySavedMessagesAsTopicListPreferencesKey = displaySavedMessagesAsTopicListPreferencesKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)),
|
)),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
@ -442,7 +442,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)),
|
)),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
@ -1458,7 +1458,8 @@ private func threadList(accountPeerId: EnginePeer.Id, postbox: Postbox, peerId:
|
|||||||
hasFailed: false,
|
hasFailed: false,
|
||||||
isContact: false,
|
isContact: false,
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyStats: nil
|
storyStats: nil,
|
||||||
|
displayAsTopicList: false
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1136,7 +1136,8 @@ public func _internal_searchForumTopics(account: Account, peerId: EnginePeer.Id,
|
|||||||
hasFailed: false,
|
hasFailed: false,
|
||||||
isContact: false,
|
isContact: false,
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyStats: nil
|
storyStats: nil,
|
||||||
|
displayAsTopicList: false
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,6 +278,7 @@ private enum PreferencesKeyValues: Int32 {
|
|||||||
case storiesConfiguration = 32
|
case storiesConfiguration = 32
|
||||||
case audioTranscriptionTrialState = 33
|
case audioTranscriptionTrialState = 33
|
||||||
case didCacheSavedMessageTagsPrefix = 34
|
case didCacheSavedMessageTagsPrefix = 34
|
||||||
|
case displaySavedChatsAsTopics = 35
|
||||||
}
|
}
|
||||||
|
|
||||||
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
public func applicationSpecificPreferencesKey(_ value: Int32) -> ValueBoxKey {
|
||||||
@ -455,6 +456,12 @@ public struct PreferencesKeys {
|
|||||||
key.setInt64(4, value: threadId ?? 0)
|
key.setInt64(4, value: threadId ?? 0)
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func displaySavedChatsAsTopics() -> ValueBoxKey {
|
||||||
|
let key = ValueBoxKey(length: 4)
|
||||||
|
key.setInt32(0, value: PreferencesKeyValues.displaySavedChatsAsTopics.rawValue)
|
||||||
|
return key
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum SharedDataKeyValues: Int32 {
|
private enum SharedDataKeyValues: Int32 {
|
||||||
|
@ -235,7 +235,8 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
},
|
||||||
|
displaySavedMessagesAsTopicListPreferencesKey: PreferencesKeys.displaySavedChatsAsTopics()
|
||||||
)
|
)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -18,6 +18,14 @@ public enum EnginePeerCachedInfoItem<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct EngineDisplaySavedChatsAsTopics: Codable, Equatable {
|
||||||
|
public var value: Bool
|
||||||
|
|
||||||
|
public init(value: Bool) {
|
||||||
|
self.value = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension EnginePeerCachedInfoItem: Equatable where T: Equatable {
|
extension EnginePeerCachedInfoItem: Equatable where T: Equatable {
|
||||||
public static func ==(lhs: EnginePeerCachedInfoItem<T>, rhs: EnginePeerCachedInfoItem<T>) -> Bool {
|
public static func ==(lhs: EnginePeerCachedInfoItem<T>, rhs: EnginePeerCachedInfoItem<T>) -> Bool {
|
||||||
switch lhs {
|
switch lhs {
|
||||||
@ -1245,5 +1253,28 @@ public extension TelegramEngine.EngineData.Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct DisplaySavedChatsAsTopics: TelegramEngineDataItem, PostboxViewDataItem {
|
||||||
|
public typealias Result = Bool
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
var key: PostboxViewKey {
|
||||||
|
return .preferences(keys: Set([PreferencesKeys.displaySavedChatsAsTopics()]))
|
||||||
|
}
|
||||||
|
|
||||||
|
func extract(view: PostboxView) -> Result {
|
||||||
|
guard let view = view as? PreferencesView else {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let value = view.values[PreferencesKeys.displaySavedChatsAsTopics()]?.get(EngineDisplaySavedChatsAsTopics.self) {
|
||||||
|
return value.value
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,6 +129,7 @@ public final class EngineChatList: Equatable {
|
|||||||
public let isContact: Bool
|
public let isContact: Bool
|
||||||
public let autoremoveTimeout: Int32?
|
public let autoremoveTimeout: Int32?
|
||||||
public let storyStats: StoryStats?
|
public let storyStats: StoryStats?
|
||||||
|
public let displayAsTopicList: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
id: Id,
|
id: Id,
|
||||||
@ -147,7 +148,8 @@ public final class EngineChatList: Equatable {
|
|||||||
hasFailed: Bool,
|
hasFailed: Bool,
|
||||||
isContact: Bool,
|
isContact: Bool,
|
||||||
autoremoveTimeout: Int32?,
|
autoremoveTimeout: Int32?,
|
||||||
storyStats: StoryStats?
|
storyStats: StoryStats?,
|
||||||
|
displayAsTopicList: Bool
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.index = index
|
self.index = index
|
||||||
@ -166,6 +168,7 @@ public final class EngineChatList: Equatable {
|
|||||||
self.isContact = isContact
|
self.isContact = isContact
|
||||||
self.autoremoveTimeout = autoremoveTimeout
|
self.autoremoveTimeout = autoremoveTimeout
|
||||||
self.storyStats = storyStats
|
self.storyStats = storyStats
|
||||||
|
self.displayAsTopicList = displayAsTopicList
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||||
@ -220,6 +223,9 @@ public final class EngineChatList: Equatable {
|
|||||||
if lhs.storyStats != rhs.storyStats {
|
if lhs.storyStats != rhs.storyStats {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.displayAsTopicList != rhs.displayAsTopicList {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,7 +425,7 @@ public extension EngineChatList.RelativePosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extension EngineChatList.Item {
|
extension EngineChatList.Item {
|
||||||
convenience init?(_ entry: ChatListEntry) {
|
convenience init?(_ entry: ChatListEntry, displayAsTopicList: Bool) {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .MessageEntry(entryData):
|
case let .MessageEntry(entryData):
|
||||||
let index = entryData.index
|
let index = entryData.index
|
||||||
@ -504,7 +510,8 @@ extension EngineChatList.Item {
|
|||||||
hasFailed: hasFailed,
|
hasFailed: hasFailed,
|
||||||
isContact: isContact,
|
isContact: isContact,
|
||||||
autoremoveTimeout: autoremoveTimeout,
|
autoremoveTimeout: autoremoveTimeout,
|
||||||
storyStats: entryData.storyStats
|
storyStats: entryData.storyStats,
|
||||||
|
displayAsTopicList: displayAsTopicList
|
||||||
)
|
)
|
||||||
case .HoleEntry:
|
case .HoleEntry:
|
||||||
return nil
|
return nil
|
||||||
@ -544,7 +551,7 @@ extension EngineChatList.AdditionalItem.PromoInfo {
|
|||||||
|
|
||||||
extension EngineChatList.AdditionalItem {
|
extension EngineChatList.AdditionalItem {
|
||||||
convenience init?(_ entry: ChatListAdditionalItemEntry) {
|
convenience init?(_ entry: ChatListAdditionalItemEntry) {
|
||||||
guard let item = EngineChatList.Item(entry.entry) else {
|
guard let item = EngineChatList.Item(entry.entry, displayAsTopicList: false) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
guard let promoInfo = (entry.info as? PromoChatListItem).flatMap(EngineChatList.AdditionalItem.PromoInfo.init) else {
|
guard let promoInfo = (entry.info as? PromoChatListItem).flatMap(EngineChatList.AdditionalItem.PromoInfo.init) else {
|
||||||
@ -555,14 +562,19 @@ extension EngineChatList.AdditionalItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public extension EngineChatList {
|
public extension EngineChatList {
|
||||||
convenience init(_ view: ChatListView) {
|
convenience init(_ view: ChatListView, accountPeerId: PeerId) {
|
||||||
var isLoading = false
|
var isLoading = false
|
||||||
|
|
||||||
|
var displaySavedMessagesAsTopicList = false
|
||||||
|
if let value = view.displaySavedMessagesAsTopicList?.get(EngineDisplaySavedChatsAsTopics.self) {
|
||||||
|
displaySavedMessagesAsTopicList = value.value
|
||||||
|
}
|
||||||
|
|
||||||
var items: [EngineChatList.Item] = []
|
var items: [EngineChatList.Item] = []
|
||||||
loop: for entry in view.entries {
|
loop: for entry in view.entries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case .MessageEntry:
|
case .MessageEntry:
|
||||||
if let item = EngineChatList.Item(entry) {
|
if let item = EngineChatList.Item(entry, displayAsTopicList: entry.index.messageIndex.id.peerId == accountPeerId ? displaySavedMessagesAsTopicList : false) {
|
||||||
items.append(item)
|
items.append(item)
|
||||||
}
|
}
|
||||||
case .HoleEntry:
|
case .HoleEntry:
|
||||||
|
@ -328,9 +328,10 @@ public extension TelegramEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func chatList(group: EngineChatList.Group, count: Int) -> Signal<EngineChatList, NoError> {
|
public func chatList(group: EngineChatList.Group, count: Int) -> Signal<EngineChatList, NoError> {
|
||||||
|
let accountPeerId = self.account.peerId
|
||||||
return self.account.postbox.tailChatListView(groupId: group._asGroup(), count: count, summaryComponents: ChatListEntrySummaryComponents())
|
return self.account.postbox.tailChatListView(groupId: group._asGroup(), count: count, summaryComponents: ChatListEntrySummaryComponents())
|
||||||
|> map { view -> EngineChatList in
|
|> map { view -> EngineChatList in
|
||||||
return EngineChatList(view.0)
|
return EngineChatList(view.0, accountPeerId: accountPeerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1346,6 +1346,14 @@ public extension TelegramEngine {
|
|||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func updateSavedMessagesViewAsTopics(value: Bool) {
|
||||||
|
let _ = (self.account.postbox.transaction { transaction -> Void in
|
||||||
|
transaction.updatePreferencesEntry(key: PreferencesKeys.displaySavedChatsAsTopics(), { _ in
|
||||||
|
return PreferencesEntry(EngineDisplaySavedChatsAsTopics(value: value))
|
||||||
|
})
|
||||||
|
}).start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +52,10 @@ public final class MoreHeaderButton: HighlightableButtonNode {
|
|||||||
strongSelf.contextAction?(strongSelf.containerNode, gesture)
|
strongSelf.contextAction?(strongSelf.containerNode, gesture)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 26.0, height: 44.0))
|
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 30.0, height: 44.0))
|
||||||
self.referenceNode.frame = self.containerNode.bounds
|
self.referenceNode.frame = self.containerNode.bounds
|
||||||
|
|
||||||
self.iconNode.image = MoreHeaderButton.optionsCircleImage(color: color)
|
//self.iconNode.image = MoreHeaderButton.optionsCircleImage(color: color)
|
||||||
if let image = self.iconNode.image {
|
if let image = self.iconNode.image {
|
||||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size)
|
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size)
|
||||||
}
|
}
|
||||||
@ -72,11 +72,13 @@ public final class MoreHeaderButton: HighlightableButtonNode {
|
|||||||
private var content: Content?
|
private var content: Content?
|
||||||
public func setContent(_ content: Content, animated: Bool = false) {
|
public func setContent(_ content: Content, animated: Bool = false) {
|
||||||
if case .more = content {
|
if case .more = content {
|
||||||
let animationSize = CGSize(width: 22.0, height: 22.0)
|
let animationSize = CGSize(width: 30.0, height: 30.0)
|
||||||
let _ = self.animationView.update(
|
let _ = self.animationView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(LottieComponent(
|
component: AnyComponent(LottieComponent(
|
||||||
content: LottieComponent.AppBundleContent(name: "anim_profilemore"),
|
content: LottieComponent.AppBundleContent(
|
||||||
|
name: "anim_moredots"
|
||||||
|
),
|
||||||
color: self.color
|
color: self.color
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
@ -119,13 +121,13 @@ public final class MoreHeaderButton: HighlightableButtonNode {
|
|||||||
if let animationComponentView = self.animationView.view {
|
if let animationComponentView = self.animationView.view {
|
||||||
animationComponentView.isHidden = true
|
animationComponentView.isHidden = true
|
||||||
}
|
}
|
||||||
case let .more(image):
|
case .more:
|
||||||
if let image = image {
|
/*if let image = image {
|
||||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size)
|
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.iconNode.image = image
|
self.iconNode.image = image
|
||||||
self.iconNode.isHidden = false
|
self.iconNode.isHidden = false*/
|
||||||
if let animationComponentView = self.animationView.view {
|
if let animationComponentView = self.animationView.view {
|
||||||
animationComponentView.isHidden = false
|
animationComponentView.isHidden = false
|
||||||
}
|
}
|
||||||
@ -143,13 +145,13 @@ public final class MoreHeaderButton: HighlightableButtonNode {
|
|||||||
if let animationComponentView = self.animationView.view {
|
if let animationComponentView = self.animationView.view {
|
||||||
animationComponentView.isHidden = true
|
animationComponentView.isHidden = true
|
||||||
}
|
}
|
||||||
case let .more(image):
|
case .more:
|
||||||
if let image = image {
|
/*if let image = image {
|
||||||
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size)
|
self.iconNode.frame = CGRect(origin: CGPoint(x: floor((self.containerNode.bounds.width - image.size.width) / 2.0), y: floor((self.containerNode.bounds.height - image.size.height) / 2.0)), size: image.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.iconNode.image = image
|
self.iconNode.image = image
|
||||||
self.iconNode.isHidden = false
|
self.iconNode.isHidden = false*/
|
||||||
if let animationComponentView = self.animationView.view {
|
if let animationComponentView = self.animationView.view {
|
||||||
animationComponentView.isHidden = false
|
animationComponentView.isHidden = false
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,7 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
|||||||
autoSetReady: false,
|
autoSetReady: false,
|
||||||
isMainTab: nil
|
isMainTab: nil
|
||||||
)
|
)
|
||||||
|
self.chatListNode.synchronousDrawingWhenNotAnimated = true
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
@ -137,6 +137,7 @@ swift_library(
|
|||||||
"//submodules/MediaPickerUI",
|
"//submodules/MediaPickerUI",
|
||||||
"//submodules/AttachmentUI",
|
"//submodules/AttachmentUI",
|
||||||
"//submodules/TelegramUI/Components/Settings/BoostLevelIconComponent",
|
"//submodules/TelegramUI/Components/Settings/BoostLevelIconComponent",
|
||||||
|
"//submodules/Components/MultilineTextComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -860,13 +860,23 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||||||
|
|
||||||
let hasSavedMessageTags: Signal<Bool, NoError>
|
let hasSavedMessageTags: Signal<Bool, NoError>
|
||||||
if let peerId = chatLocation.peerId {
|
if let peerId = chatLocation.peerId {
|
||||||
hasSavedMessageTags = context.engine.data.subscribe(
|
if case .peer = chatLocation {
|
||||||
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId, threadId: peerId.toInt64())
|
hasSavedMessageTags = context.engine.data.subscribe(
|
||||||
)
|
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId, threadId: nil)
|
||||||
|> map { tags -> Bool in
|
)
|
||||||
return !tags.isEmpty
|
|> map { tags -> Bool in
|
||||||
|
return !tags.isEmpty
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
|
} else {
|
||||||
|
hasSavedMessageTags = context.engine.data.subscribe(
|
||||||
|
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId, threadId: peerId.toInt64())
|
||||||
|
)
|
||||||
|
|> map { tags -> Bool in
|
||||||
|
return !tags.isEmpty
|
||||||
|
}
|
||||||
|
|> distinctUntilChanged
|
||||||
}
|
}
|
||||||
|> distinctUntilChanged
|
|
||||||
} else {
|
} else {
|
||||||
hasSavedMessageTags = .single(false)
|
hasSavedMessageTags = .single(false)
|
||||||
}
|
}
|
||||||
|
@ -250,6 +250,10 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
|||||||
icon = nil
|
icon = nil
|
||||||
isAnimation = true
|
isAnimation = true
|
||||||
animationState = .search
|
animationState = .search
|
||||||
|
case .standaloneSearch:
|
||||||
|
text = ""
|
||||||
|
accessibilityText = presentationData.strings.Common_Search
|
||||||
|
icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
|
||||||
case .searchWithTags:
|
case .searchWithTags:
|
||||||
text = ""
|
text = ""
|
||||||
accessibilityText = presentationData.strings.Common_Search
|
accessibilityText = presentationData.strings.Common_Search
|
||||||
|
@ -14,6 +14,7 @@ enum PeerInfoHeaderNavigationButtonKey {
|
|||||||
case selectionDone
|
case selectionDone
|
||||||
case search
|
case search
|
||||||
case searchWithTags
|
case searchWithTags
|
||||||
|
case standaloneSearch
|
||||||
case editPhoto
|
case editPhoto
|
||||||
case editVideo
|
case editVideo
|
||||||
case more
|
case more
|
||||||
@ -52,11 +53,11 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||||||
}
|
}
|
||||||
for (_, button) in self.rightButtonNodes {
|
for (_, button) in self.rightButtonNodes {
|
||||||
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition)
|
button.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: canBeExpanded, transition: transition)
|
||||||
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: canBeExpanded ? 8.0 : 0.0, y: 0.0))
|
transition.updateSublayerTransformOffset(layer: button.layer, offset: CGPoint(x: canBeExpanded ? 16.0 : 0.0, y: 0.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(size: CGSize, presentationData: PresentationData, leftButtons: [PeerInfoHeaderNavigationButtonSpec], rightButtons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, transition: ContainedViewLayoutTransition) {
|
func update(size: CGSize, presentationData: PresentationData, leftButtons: [PeerInfoHeaderNavigationButtonSpec], rightButtons: [PeerInfoHeaderNavigationButtonSpec], expandFraction: CGFloat, shouldAnimateIn: Bool, transition: ContainedViewLayoutTransition) {
|
||||||
let sideInset: CGFloat = 24.0
|
let sideInset: CGFloat = 24.0
|
||||||
|
|
||||||
let maximumExpandOffset: CGFloat = 14.0
|
let maximumExpandOffset: CGFloat = 14.0
|
||||||
@ -201,7 +202,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||||||
if case .postStory = spec.key {
|
if case .postStory = spec.key {
|
||||||
buttonFrame.origin.x -= 12.0
|
buttonFrame.origin.x -= 12.0
|
||||||
}
|
}
|
||||||
nextButtonOrigin -= buttonSize.width + 4.0
|
nextButtonOrigin -= buttonSize.width + 15.0
|
||||||
if spec.isForExpandedView {
|
if spec.isForExpandedView {
|
||||||
nextExpandedButtonOrigin = nextButtonOrigin
|
nextExpandedButtonOrigin = nextButtonOrigin
|
||||||
} else {
|
} else {
|
||||||
@ -211,15 +212,17 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||||||
if wasAdded {
|
if wasAdded {
|
||||||
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate)
|
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate)
|
||||||
|
|
||||||
if key == .moreToSearch || key == .searchWithTags {
|
if shouldAnimateIn {
|
||||||
buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
|
if key == .moreToSearch || key == .searchWithTags || key == .standaloneSearch {
|
||||||
|
buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonNode.frame = buttonFrame
|
buttonNode.frame = buttonFrame
|
||||||
buttonNode.alpha = 0.0
|
buttonNode.alpha = 0.0
|
||||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||||
|
|
||||||
transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: canBeExpanded ? 8.0 : 0.0, y: 0.0))
|
transition.updateSublayerTransformOffset(layer: buttonNode.layer, offset: CGPoint(x: canBeExpanded ? 16.0 : 0.0, y: 0.0))
|
||||||
} else {
|
} else {
|
||||||
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
||||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||||
@ -237,7 +240,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||||||
}
|
}
|
||||||
for key in removeKeys {
|
for key in removeKeys {
|
||||||
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) {
|
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) {
|
||||||
if key == .moreToSearch || key == .searchWithTags {
|
if key == .moreToSearch || key == .searchWithTags || key == .standaloneSearch {
|
||||||
buttonNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in
|
buttonNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in
|
||||||
buttonNode?.removeFromSupernode()
|
buttonNode?.removeFromSupernode()
|
||||||
})
|
})
|
||||||
@ -264,7 +267,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
|||||||
if case .postStory = spec.key {
|
if case .postStory = spec.key {
|
||||||
buttonFrame.origin.x -= 12.0
|
buttonFrame.origin.x -= 12.0
|
||||||
}
|
}
|
||||||
nextButtonOrigin -= buttonSize.width + 4.0
|
nextButtonOrigin -= buttonSize.width + 15.0
|
||||||
if spec.isForExpandedView {
|
if spec.isForExpandedView {
|
||||||
nextExpandedButtonOrigin = nextButtonOrigin
|
nextExpandedButtonOrigin = nextButtonOrigin
|
||||||
} else {
|
} else {
|
||||||
|
@ -37,6 +37,7 @@ import ChatAvatarNavigationNode
|
|||||||
import MultiScaleTextNode
|
import MultiScaleTextNode
|
||||||
import PeerInfoCoverComponent
|
import PeerInfoCoverComponent
|
||||||
import PeerInfoPaneNode
|
import PeerInfoPaneNode
|
||||||
|
import MultilineTextComponent
|
||||||
|
|
||||||
final class PeerInfoHeaderNavigationTransition {
|
final class PeerInfoHeaderNavigationTransition {
|
||||||
let sourceNavigationBar: NavigationBar
|
let sourceNavigationBar: NavigationBar
|
||||||
@ -108,6 +109,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
let titleNodeContainer: ASDisplayNode
|
let titleNodeContainer: ASDisplayNode
|
||||||
let titleNodeRawContainer: ASDisplayNode
|
let titleNodeRawContainer: ASDisplayNode
|
||||||
let titleNode: MultiScaleTextNode
|
let titleNode: MultiScaleTextNode
|
||||||
|
var standardTitle: ComponentView<Empty>?
|
||||||
|
|
||||||
let titleCredibilityIconView: ComponentHostView<Empty>
|
let titleCredibilityIconView: ComponentHostView<Empty>
|
||||||
var credibilityIconSize: CGSize?
|
var credibilityIconSize: CGSize?
|
||||||
@ -991,12 +993,15 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
let titleShadowColor: UIColor? = nil
|
let titleShadowColor: UIColor? = nil
|
||||||
|
|
||||||
|
var displayStandardTitle = false
|
||||||
|
|
||||||
if let peer = peer {
|
if let peer = peer {
|
||||||
var title: String
|
var title: String
|
||||||
if peer.id == self.context.account.peerId && !self.isSettings {
|
if peer.id == self.context.account.peerId && !self.isSettings {
|
||||||
if case .replyThread = self.chatLocation {
|
if case .replyThread = self.chatLocation {
|
||||||
title = presentationData.strings.Conversation_MyNotes
|
title = presentationData.strings.Conversation_MyNotes
|
||||||
} else {
|
} else {
|
||||||
|
displayStandardTitle = true
|
||||||
title = presentationData.strings.Conversation_SavedMessages
|
title = presentationData.strings.Conversation_SavedMessages
|
||||||
}
|
}
|
||||||
} else if peer.id.isAnonymousSavedMessages {
|
} else if peer.id.isAnonymousSavedMessages {
|
||||||
@ -1789,6 +1794,41 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if displayStandardTitle {
|
||||||
|
self.titleNode.isHidden = true
|
||||||
|
|
||||||
|
let standardTitle: ComponentView<Empty>
|
||||||
|
if let current = self.standardTitle {
|
||||||
|
standardTitle = current
|
||||||
|
} else {
|
||||||
|
standardTitle = ComponentView()
|
||||||
|
self.standardTitle = standardTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
let titleSize = standardTitle.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(string: titleStringText, font: Font.semibold(17.0), textColor: navigationContentsPrimaryColor))
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: width, height: navigationHeight)
|
||||||
|
)
|
||||||
|
if let standardTitleView = standardTitle.view {
|
||||||
|
if standardTitleView.superview == nil {
|
||||||
|
self.regularContentNode.view.addSubview(standardTitleView)
|
||||||
|
}
|
||||||
|
let standardTitleFrame = titleSize.centered(in: self.titleNodeContainer.frame).offsetBy(dx: 2.0, dy: 0.0)
|
||||||
|
standardTitleView.frame = standardTitleFrame
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let standardTitle = self.standardTitle {
|
||||||
|
self.standardTitle = nil
|
||||||
|
standardTitle.view?.removeFromSuperview()
|
||||||
|
|
||||||
|
self.titleNode.isHidden = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let buttonsTransitionDistance: CGFloat = -min(0.0, apparentBackgroundHeight - backgroundHeight)
|
let buttonsTransitionDistance: CGFloat = -min(0.0, apparentBackgroundHeight - backgroundHeight)
|
||||||
let buttonsTransitionDistanceNorm: CGFloat = 40.0
|
let buttonsTransitionDistanceNorm: CGFloat = 40.0
|
||||||
|
|
||||||
|
@ -3758,11 +3758,17 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) }
|
strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) }
|
||||||
strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true)
|
strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true)
|
||||||
case .search, .searchWithTags:
|
case .search, .searchWithTags, .standaloneSearch:
|
||||||
strongSelf.activateSearch()
|
strongSelf.activateSearch()
|
||||||
case .more:
|
case .more:
|
||||||
if let source = source {
|
if let currentPaneKey = strongSelf.paneContainerNode.currentPaneKey, case .savedMessagesChats = currentPaneKey {
|
||||||
strongSelf.displayMediaGalleryContextMenu(source: source, gesture: gesture)
|
if let controller = strongSelf.controller, let source {
|
||||||
|
PeerInfoScreenImpl.openSavedMessagesMoreMenu(context: strongSelf.context, sourceController: controller, isViewingAsTopics: true, sourceView: source.view, gesture: gesture)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let source = source {
|
||||||
|
strongSelf.displayMediaGalleryContextMenu(source: source, gesture: gesture)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case .qrCode:
|
case .qrCode:
|
||||||
strongSelf.openQrCode()
|
strongSelf.openQrCode()
|
||||||
@ -10177,7 +10183,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.ignoreScrolling = false
|
self.ignoreScrolling = false
|
||||||
self.updateNavigation(transition: transition, additive: additive, animateHeader: true)
|
self.updateNavigation(transition: transition, additive: additive, animateHeader: self.controller?.didAppear ?? false)
|
||||||
|
|
||||||
if !self.didSetReady && self.data != nil {
|
if !self.didSetReady && self.data != nil {
|
||||||
self.didSetReady = true
|
self.didSetReady = true
|
||||||
@ -10287,8 +10293,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
if self.state.selectedMessageIds == nil {
|
if self.state.selectedMessageIds == nil {
|
||||||
if let currentPaneKey = self.paneContainerNode.currentPaneKey {
|
if let currentPaneKey = self.paneContainerNode.currentPaneKey {
|
||||||
switch currentPaneKey {
|
switch currentPaneKey {
|
||||||
case .files, .music, .links, .members, .savedMessagesChats:
|
case .files, .music, .links, .members:
|
||||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
||||||
|
case .savedMessagesChats:
|
||||||
|
if let data = self.data, data.hasSavedMessageTags {
|
||||||
|
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .searchWithTags, isForExpandedView: true))
|
||||||
|
} else {
|
||||||
|
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .standaloneSearch, isForExpandedView: true))
|
||||||
|
}
|
||||||
|
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true))
|
||||||
case .savedMessages:
|
case .savedMessages:
|
||||||
if let data = self.data, data.hasSavedMessageTags {
|
if let data = self.data, data.hasSavedMessageTags {
|
||||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .searchWithTags, isForExpandedView: true))
|
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .searchWithTags, isForExpandedView: true))
|
||||||
@ -10318,7 +10331,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .back, isForExpandedView: false))
|
leftNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .back, isForExpandedView: false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.headerNode.navigationButtonContainer.update(size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight), presentationData: self.presentationData, leftButtons: leftNavigationButtons, rightButtons: rightNavigationButtons, expandFraction: effectiveAreaExpansionFraction, transition: transition)
|
self.headerNode.navigationButtonContainer.update(size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight), presentationData: self.presentationData, leftButtons: leftNavigationButtons, rightButtons: rightNavigationButtons, expandFraction: effectiveAreaExpansionFraction, shouldAnimateIn: animateHeader, transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10622,6 +10635,8 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var didAppear: Bool = false
|
||||||
|
|
||||||
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
private var validLayout: (layout: ContainerViewLayout, navigationHeight: CGFloat)?
|
||||||
|
|
||||||
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil, switchToRecommendedChannels: Bool = false) {
|
public init(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peerId: PeerId, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, nearbyPeerDistance: Int32?, reactionSourceMessageId: MessageId?, callMessages: [Message], isSettings: Bool = false, hintGroupInCommon: PeerId? = nil, requestsContext: PeerInvitationImportersContext? = nil, forumTopicThread: ChatReplyThreadMessage? = nil, switchToRecommendedChannels: Bool = false) {
|
||||||
@ -11145,6 +11160,10 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||||||
override public func viewDidAppear(_ animated: Bool) {
|
override public func viewDidAppear(_ animated: Bool) {
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.didAppear = true
|
||||||
|
}
|
||||||
|
|
||||||
var chatNavigationStack: [ChatNavigationStackItem] = []
|
var chatNavigationStack: [ChatNavigationStackItem] = []
|
||||||
if !self.isSettings, let summary = self.customNavigationDataSummary as? ChatControllerNavigationDataSummary {
|
if !self.isSettings, let summary = self.customNavigationDataSummary as? ChatControllerNavigationDataSummary {
|
||||||
chatNavigationStack.removeAll()
|
chatNavigationStack.removeAll()
|
||||||
@ -11266,6 +11285,61 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func openSavedMessagesMoreMenu(context: AccountContext, sourceController: ViewController, isViewingAsTopics: Bool, sourceView: UIView, gesture: ContextGesture?) {
|
||||||
|
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId))
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { peer in
|
||||||
|
guard let peer else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let strings = context.sharedContext.currentPresentationData.with { $0 }.strings
|
||||||
|
|
||||||
|
var items: [ContextMenuItem] = []
|
||||||
|
|
||||||
|
//TODO:localize
|
||||||
|
items.append(.action(ContextMenuActionItem(text: "View as Chats", icon: { theme in
|
||||||
|
if !isViewingAsTopics {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
|
||||||
|
}, iconPosition: .left, action: { [weak sourceController] _, a in
|
||||||
|
a(.default)
|
||||||
|
|
||||||
|
guard let sourceController = sourceController, let navigationController = sourceController.navigationController as? NavigationController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
|
||||||
|
navigationController.replaceController(sourceController, with: infoController, animated: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
context.engine.peers.updateSavedMessagesViewAsTopics(value: true)
|
||||||
|
})))
|
||||||
|
items.append(.action(ContextMenuActionItem(text: strings.Chat_ContextViewAsMessages, icon: { theme in
|
||||||
|
if isViewingAsTopics {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
|
||||||
|
}, iconPosition: .left, action: { [weak sourceController] _, a in
|
||||||
|
a(.default)
|
||||||
|
|
||||||
|
guard let sourceController = sourceController, let navigationController = sourceController.navigationController as? NavigationController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(id: context.account.peerId), subject: nil, botStart: nil, mode: .standard(.default))
|
||||||
|
|
||||||
|
navigationController.replaceController(sourceController, with: chatController, animated: false)
|
||||||
|
|
||||||
|
context.engine.peers.updateSavedMessagesViewAsTopics(value: false)
|
||||||
|
})))
|
||||||
|
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
let contextController = ContextController(presentationData: presentationData, source: .reference(HeaderContextReferenceContentSource(controller: sourceController, sourceView: sourceView)), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||||
|
sourceController.presentInGlobalOverlay(contextController)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SettingsTabBarContextExtractedContentSource: ContextExtractedContentSource {
|
private final class SettingsTabBarContextExtractedContentSource: ContextExtractedContentSource {
|
||||||
@ -12432,3 +12506,17 @@ private final class PeerInfoControllerContextReferenceContentSource: ContextRefe
|
|||||||
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds.inset(by: self.insets), insets: self.contentInsets)
|
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds.inset(by: self.insets), insets: self.contentInsets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class HeaderContextReferenceContentSource: ContextReferenceContentSource {
|
||||||
|
private let controller: ViewController
|
||||||
|
private let sourceView: UIView
|
||||||
|
|
||||||
|
init(controller: ViewController, sourceView: UIView) {
|
||||||
|
self.controller = controller
|
||||||
|
self.sourceView = sourceView
|
||||||
|
}
|
||||||
|
|
||||||
|
func transitionInfo() -> ContextControllerReferenceViewInfo? {
|
||||||
|
return ContextControllerReferenceViewInfo(referenceView: self.sourceView, contentAreaInScreenSpace: UIScreen.main.bounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -937,7 +937,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)),
|
)),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
@ -452,23 +452,58 @@ func updateChatPresentationInterfaceStateImpl(
|
|||||||
selfController.leftNavigationButton = nil
|
selfController.leftNavigationButton = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var buttonsAnimated = transition.isAnimated
|
||||||
if let button = rightNavigationButtonForChatInterfaceState(context: selfController.context, presentationInterfaceState: updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: selfController.rightNavigationButton, target: selfController, selector: #selector(selfController.rightNavigationButtonAction), chatInfoNavigationButton: selfController.chatInfoNavigationButton, moreInfoNavigationButton: selfController.moreInfoNavigationButton) {
|
if let button = rightNavigationButtonForChatInterfaceState(context: selfController.context, presentationInterfaceState: updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: selfController.rightNavigationButton, target: selfController, selector: #selector(selfController.rightNavigationButtonAction), chatInfoNavigationButton: selfController.chatInfoNavigationButton, moreInfoNavigationButton: selfController.moreInfoNavigationButton) {
|
||||||
if selfController.rightNavigationButton != button {
|
if selfController.rightNavigationButton != button {
|
||||||
var animated = transition.isAnimated
|
|
||||||
if let currentButton = selfController.rightNavigationButton?.action, currentButton == button.action {
|
if let currentButton = selfController.rightNavigationButton?.action, currentButton == button.action {
|
||||||
animated = false
|
buttonsAnimated = false
|
||||||
}
|
}
|
||||||
if case .replyThread = selfController.chatLocation {
|
if case .replyThread = selfController.chatLocation {
|
||||||
animated = false
|
buttonsAnimated = false
|
||||||
}
|
}
|
||||||
selfController.navigationItem.setRightBarButton(button.buttonItem, animated: animated)
|
|
||||||
selfController.rightNavigationButton = button
|
selfController.rightNavigationButton = button
|
||||||
}
|
}
|
||||||
} else if let _ = selfController.rightNavigationButton {
|
} else if let _ = selfController.rightNavigationButton {
|
||||||
selfController.navigationItem.setRightBarButton(nil, animated: transition.isAnimated)
|
|
||||||
selfController.rightNavigationButton = nil
|
selfController.rightNavigationButton = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let button = secondaryRightNavigationButtonForChatInterfaceState(context: selfController.context, presentationInterfaceState: updatedChatPresentationInterfaceState, strings: updatedChatPresentationInterfaceState.strings, currentButton: selfController.secondaryRightNavigationButton, target: selfController, selector: #selector(selfController.secondaryRightNavigationButtonAction), chatInfoNavigationButton: selfController.chatInfoNavigationButton, moreInfoNavigationButton: selfController.moreInfoNavigationButton) {
|
||||||
|
if selfController.secondaryRightNavigationButton != button {
|
||||||
|
if let currentButton = selfController.secondaryRightNavigationButton?.action, currentButton == button.action {
|
||||||
|
buttonsAnimated = false
|
||||||
|
}
|
||||||
|
if case .replyThread = selfController.chatLocation {
|
||||||
|
buttonsAnimated = false
|
||||||
|
}
|
||||||
|
selfController.secondaryRightNavigationButton = button
|
||||||
|
}
|
||||||
|
} else if let _ = selfController.secondaryRightNavigationButton {
|
||||||
|
selfController.secondaryRightNavigationButton = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var rightBarButtons: [UIBarButtonItem] = []
|
||||||
|
if let rightNavigationButton = selfController.rightNavigationButton {
|
||||||
|
rightBarButtons.append(rightNavigationButton.buttonItem)
|
||||||
|
}
|
||||||
|
if let secondaryRightNavigationButton = selfController.secondaryRightNavigationButton {
|
||||||
|
rightBarButtons.append(secondaryRightNavigationButton.buttonItem)
|
||||||
|
}
|
||||||
|
var rightBarButtonsUpdated = false
|
||||||
|
let currentRightBarButtons = selfController.navigationItem.rightBarButtonItems ?? []
|
||||||
|
if rightBarButtons.count != currentRightBarButtons.count {
|
||||||
|
rightBarButtonsUpdated = true
|
||||||
|
} else {
|
||||||
|
for i in 0 ..< rightBarButtons.count {
|
||||||
|
if rightBarButtons[i] !== currentRightBarButtons[i] {
|
||||||
|
rightBarButtonsUpdated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rightBarButtonsUpdated {
|
||||||
|
selfController.navigationItem.setRightBarButtonItems(rightBarButtons, animated: buttonsAnimated)
|
||||||
|
}
|
||||||
|
|
||||||
if let controllerInteraction = selfController.controllerInteraction {
|
if let controllerInteraction = selfController.controllerInteraction {
|
||||||
if updatedChatPresentationInterfaceState.interfaceState.selectionState != controllerInteraction.selectionState {
|
if updatedChatPresentationInterfaceState.interfaceState.selectionState != controllerInteraction.selectionState {
|
||||||
controllerInteraction.selectionState = updatedChatPresentationInterfaceState.interfaceState.selectionState
|
controllerInteraction.selectionState = updatedChatPresentationInterfaceState.interfaceState.selectionState
|
||||||
|
@ -122,6 +122,7 @@ import WallpaperGalleryScreen
|
|||||||
import WallpaperGridScreen
|
import WallpaperGridScreen
|
||||||
import VideoMessageCameraScreen
|
import VideoMessageCameraScreen
|
||||||
import TopMessageReactions
|
import TopMessageReactions
|
||||||
|
import PeerInfoScreen
|
||||||
|
|
||||||
public enum ChatControllerPeekActions {
|
public enum ChatControllerPeekActions {
|
||||||
case standard
|
case standard
|
||||||
@ -267,6 +268,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var chatTitleView: ChatTitleView?
|
var chatTitleView: ChatTitleView?
|
||||||
var leftNavigationButton: ChatNavigationButton?
|
var leftNavigationButton: ChatNavigationButton?
|
||||||
var rightNavigationButton: ChatNavigationButton?
|
var rightNavigationButton: ChatNavigationButton?
|
||||||
|
var secondaryRightNavigationButton: ChatNavigationButton?
|
||||||
var chatInfoNavigationButton: ChatNavigationButton?
|
var chatInfoNavigationButton: ChatNavigationButton?
|
||||||
|
|
||||||
var moreBarButton: MoreHeaderButton
|
var moreBarButton: MoreHeaderButton
|
||||||
@ -4725,13 +4727,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.moreBarButton.setContent(.more(MoreHeaderButton.optionsCircleImage(color: self.presentationData.theme.rootController.navigationBar.buttonColor)))
|
self.moreBarButton.setContent(.more(MoreHeaderButton.optionsCircleImage(color: self.presentationData.theme.rootController.navigationBar.buttonColor)))
|
||||||
self.moreInfoNavigationButton = ChatNavigationButton(action: .toggleInfoPanel, buttonItem: UIBarButtonItem(customDisplayNode: self.moreBarButton)!)
|
self.moreInfoNavigationButton = ChatNavigationButton(action: .toggleInfoPanel, buttonItem: UIBarButtonItem(customDisplayNode: self.moreBarButton)!)
|
||||||
self.moreBarButton.contextAction = { [weak self] sourceNode, gesture in
|
self.moreBarButton.contextAction = { [weak self] sourceNode, gesture in
|
||||||
guard let self = self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard case let .peer(peerId) = self.chatLocation else {
|
guard case let .peer(peerId) = self.chatLocation else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ChatListControllerImpl.openMoreMenu(context: self.context, peerId: peerId, sourceController: self, isViewingAsTopics: false, sourceView: sourceNode.view, gesture: gesture)
|
|
||||||
|
if peerId == self.context.account.peerId {
|
||||||
|
PeerInfoScreenImpl.openSavedMessagesMoreMenu(context: self.context, sourceController: self, isViewingAsTopics: false, sourceView: sourceNode.view, gesture: gesture)
|
||||||
|
} else {
|
||||||
|
ChatListControllerImpl.openMoreMenu(context: self.context, peerId: peerId, sourceController: self, isViewingAsTopics: false, sourceView: sourceNode.view, gesture: gesture)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.moreBarButton.addTarget(self, action: #selector(self.moreButtonPressed), forControlEvents: .touchUpInside)
|
self.moreBarButton.addTarget(self, action: #selector(self.moreButtonPressed), forControlEvents: .touchUpInside)
|
||||||
|
|
||||||
@ -12087,6 +12094,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func secondaryRightNavigationButtonAction() {
|
||||||
|
if let button = self.secondaryRightNavigationButton {
|
||||||
|
self.navigationButtonAction(button.action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc func moreButtonPressed() {
|
@objc func moreButtonPressed() {
|
||||||
self.moreBarButton.play()
|
self.moreBarButton.play()
|
||||||
self.moreBarButton.contextAction?(self.moreBarButton.containerNode, nil)
|
self.moreBarButton.contextAction?(self.moreBarButton.containerNode, nil)
|
||||||
|
@ -182,3 +182,11 @@ func rightNavigationButtonForChatInterfaceState(context: AccountContext, present
|
|||||||
|
|
||||||
return chatInfoNavigationButton
|
return chatInfoNavigationButton
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func secondaryRightNavigationButtonForChatInterfaceState(context: AccountContext, presentationInterfaceState: ChatPresentationInterfaceState, strings: PresentationStrings, currentButton: ChatNavigationButton?, target: Any?, selector: Selector?, chatInfoNavigationButton: ChatNavigationButton?, moreInfoNavigationButton: ChatNavigationButton?) -> ChatNavigationButton? {
|
||||||
|
if case .peer(context.account.peerId) = presentationInterfaceState.chatLocation {
|
||||||
|
return moreInfoNavigationButton
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -104,7 +104,8 @@ private enum ChatListSearchEntry: Comparable, Identifiable {
|
|||||||
topForumTopicItems: [],
|
topForumTopicItems: [],
|
||||||
autoremoveTimeout: nil,
|
autoremoveTimeout: nil,
|
||||||
storyState: nil,
|
storyState: nil,
|
||||||
requiresPremiumForMessaging: false
|
requiresPremiumForMessaging: false,
|
||||||
|
displayAsTopicList: false
|
||||||
)),
|
)),
|
||||||
editing: false,
|
editing: false,
|
||||||
hasActiveRevealControls: false,
|
hasActiveRevealControls: false,
|
||||||
|
@ -41,6 +41,13 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if case let .peer(peer) = params.chatLocation, peer.id == params.context.account.peerId {
|
||||||
|
viewForumAsMessages = params.context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Peer.DisplaySavedChatsAsTopics()
|
||||||
|
)
|
||||||
|
|> map { value in
|
||||||
|
return !value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = (viewForumAsMessages
|
let _ = (viewForumAsMessages
|
||||||
@ -93,6 +100,14 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !viewForumAsMessages, params.subject == nil, case let .peer(peer) = params.chatLocation, peer.id == params.context.account.peerId {
|
||||||
|
if let controller = params.context.sharedContext.makePeerInfoController(context: params.context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
|
||||||
|
params.navigationController.pushViewController(controller, animated: params.animated, completion: {
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var found = false
|
var found = false
|
||||||
var isFirst = true
|
var isFirst = true
|
||||||
if params.useExisting {
|
if params.useExisting {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user