mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
General UI bug fixes
This commit is contained in:
parent
9c09a61e47
commit
3b93037be9
@ -373,6 +373,17 @@ public enum ChatLocation: Equatable {
|
|||||||
case feed(id: Int32)
|
case feed(id: Int32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public extension ChatLocation {
|
||||||
|
var normalized: ChatLocation {
|
||||||
|
switch self {
|
||||||
|
case .peer, .feed:
|
||||||
|
return self
|
||||||
|
case let .replyThread(message):
|
||||||
|
return .replyThread(message: message.normalized)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum ChatControllerActivateInput {
|
public enum ChatControllerActivateInput {
|
||||||
case text
|
case text
|
||||||
case entityInput
|
case entityInput
|
||||||
|
@ -1254,7 +1254,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
chatController.canReadHistory.set(false)
|
chatController.canReadHistory.set(false)
|
||||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||||
|
|
||||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: source, items: chatForumTopicMenuItems(context: strongSelf.context, peerId: peer.peerId, threadId: threadId, isPinned: nil, isClosed: nil, chatListController: strongSelf, joined: joined, canSelect: true) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: source, items: chatForumTopicMenuItems(context: strongSelf.context, peerId: peer.peerId, threadId: threadId, isPinned: nil, isClosed: nil, chatListController: strongSelf, joined: joined, canSelect: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
||||||
strongSelf.presentInGlobalOverlay(contextController)
|
strongSelf.presentInGlobalOverlay(contextController)
|
||||||
} else {
|
} else {
|
||||||
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .forum(peerId: channel.id), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
|
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .forum(peerId: channel.id), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
|
||||||
@ -1302,21 +1302,28 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let contextContentSource: ContextContentSource
|
if case let .channel(channel) = peer, channel.flags.contains(.isForum) {
|
||||||
if peer.id.namespace == Namespaces.Peer.SecretChat, let node = node.subnodes?.first as? ContextExtractedContentContainingNode {
|
let chatListController = ChatListControllerImpl(context: strongSelf.context, location: .forum(peerId: channel.id), controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false)
|
||||||
contextContentSource = .extracted(ChatListHeaderBarContextExtractedContentSource(controller: strongSelf, sourceNode: node, keepInPlace: false))
|
chatListController.navigationPresentation = .master
|
||||||
|
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
||||||
|
strongSelf.presentInGlobalOverlay(contextController)
|
||||||
} else {
|
} else {
|
||||||
var subject: ChatControllerSubject?
|
let contextContentSource: ContextContentSource
|
||||||
if case let .search(messageId) = source, let id = messageId {
|
if peer.id.namespace == Namespaces.Peer.SecretChat, let node = node.subnodes?.first as? ContextExtractedContentContainingNode {
|
||||||
subject = .message(id: .id(id), highlight: false, timecode: nil)
|
contextContentSource = .extracted(ChatListHeaderBarContextExtractedContentSource(controller: strongSelf, sourceNode: node, keepInPlace: false))
|
||||||
|
} else {
|
||||||
|
var subject: ChatControllerSubject?
|
||||||
|
if case let .search(messageId) = source, let id = messageId {
|
||||||
|
subject = .message(id: .id(id), highlight: false, timecode: nil)
|
||||||
|
}
|
||||||
|
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, botStart: nil, mode: .standard(previewing: true))
|
||||||
|
chatController.canReadHistory.set(false)
|
||||||
|
contextContentSource = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||||
}
|
}
|
||||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peer.id), subject: subject, botStart: nil, mode: .standard(previewing: true))
|
|
||||||
chatController.canReadHistory.set(false)
|
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: contextContentSource, items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
||||||
contextContentSource = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
strongSelf.presentInGlobalOverlay(contextController)
|
||||||
}
|
}
|
||||||
|
|
||||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: contextContentSource, items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(content: .list($0)) }, gesture: gesture)
|
|
||||||
strongSelf.presentInGlobalOverlay(contextController)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.tabContainerNode.tabSelected = { [weak self] id, isDisabled in
|
self.tabContainerNode.tabSelected = { [weak self] id, isDisabled in
|
||||||
@ -2048,8 +2055,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|
|
||||||
let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0
|
let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0
|
||||||
|
|
||||||
transition.updateAlpha(node: self.tabContainerNode, alpha: self.chatListDisplayNode.inlineStackContainerTransitionFraction * 0.5 + (1.0 - self.chatListDisplayNode.inlineStackContainerTransitionFraction) * 1.0)
|
//transition.updateAlpha(node: self.tabContainerNode, alpha: self.chatListDisplayNode.inlineStackContainerTransitionFraction * 0.5 + (1.0 - self.chatListDisplayNode.inlineStackContainerTransitionFraction) * 1.0)
|
||||||
self.tabContainerNode.isUserInteractionEnabled = self.chatListDisplayNode.inlineStackContainerNode == nil
|
//self.tabContainerNode.isUserInteractionEnabled = self.chatListDisplayNode.inlineStackContainerNode == nil
|
||||||
|
|
||||||
transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0)))
|
transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0)))
|
||||||
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.mainContainerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.effectiveContainerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
|
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.mainContainerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.effectiveContainerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.effectiveContainerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
|
||||||
@ -4689,12 +4696,6 @@ private final class ChatListLocationContext {
|
|||||||
longTapped: {
|
longTapped: {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.rightButton = AnyComponentWithIdentity(id: "done", component: AnyComponent(NavigationButtonComponent(
|
|
||||||
content: .text(title: presentationData.strings.Common_Done, isBold: true),
|
|
||||||
pressed: { [weak self] _ in
|
|
||||||
self?.parentController?.donePressed()
|
|
||||||
}
|
|
||||||
)))
|
|
||||||
} else {
|
} else {
|
||||||
self.chatTitleComponent = ChatTitleComponent(
|
self.chatTitleComponent = ChatTitleComponent(
|
||||||
context: self.context,
|
context: self.context,
|
||||||
@ -4724,7 +4725,16 @@ private final class ChatListLocationContext {
|
|||||||
self.parentController?.activateSearch()
|
self.parentController?.activateSearch()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stateAndFilterId.state.editing {
|
||||||
|
self.rightButton = AnyComponentWithIdentity(id: "done", component: AnyComponent(NavigationButtonComponent(
|
||||||
|
content: .text(title: presentationData.strings.Common_Done, isBold: true),
|
||||||
|
pressed: { [weak self] _ in
|
||||||
|
self?.parentController?.donePressed()
|
||||||
|
}
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
self.rightButton = AnyComponentWithIdentity(id: "more", component: AnyComponent(NavigationButtonComponent(
|
self.rightButton = AnyComponentWithIdentity(id: "more", component: AnyComponent(NavigationButtonComponent(
|
||||||
content: .more,
|
content: .more,
|
||||||
pressed: { [weak self] sourceView in
|
pressed: { [weak self] sourceView in
|
||||||
|
@ -1510,7 +1510,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
})
|
})
|
||||||
|
|
||||||
let foundThreads: Signal<[EngineChatList.Item], NoError>
|
let foundThreads: Signal<[EngineChatList.Item], NoError>
|
||||||
if case .forum = location {
|
if case .forum = location, (key == .topics || key == .chats) {
|
||||||
foundThreads = chatListViewForLocation(chatListLocation: location, location: .initial(count: 1000, filter: nil), account: context.account)
|
foundThreads = chatListViewForLocation(chatListLocation: location, location: .initial(count: 1000, filter: nil), account: context.account)
|
||||||
|> map { view -> [EngineChatList.Item] in
|
|> map { view -> [EngineChatList.Item] in
|
||||||
var filteredItems: [EngineChatList.Item] = []
|
var filteredItems: [EngineChatList.Item] = []
|
||||||
|
@ -1142,7 +1142,12 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.contextContainer.additionalActivationProgressLayer = nil
|
strongSelf.contextContainer.additionalActivationProgressLayer = nil
|
||||||
if item.interaction.inlineNavigationLocation != nil {
|
if let inlineNavigationLocation = item.interaction.inlineNavigationLocation {
|
||||||
|
if case let .peer(peerId) = inlineNavigationLocation.location {
|
||||||
|
if case let .chatList(index) = item.index, index.messageIndex.id.peerId == peerId {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
strongSelf.contextContainer.targetNodeForActivationProgress = strongSelf.avatarContainerNode
|
strongSelf.contextContainer.targetNodeForActivationProgress = strongSelf.avatarContainerNode
|
||||||
} else if let value = strongSelf.hitTest(location, with: nil), value === strongSelf.compoundTextButtonNode?.view {
|
} else if let value = strongSelf.hitTest(location, with: nil), value === strongSelf.compoundTextButtonNode?.view {
|
||||||
strongSelf.contextContainer.targetNodeForActivationProgress = strongSelf.compoundTextButtonNode
|
strongSelf.contextContainer.targetNodeForActivationProgress = strongSelf.compoundTextButtonNode
|
||||||
@ -1313,9 +1318,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
reallyHighlighted = true
|
reallyHighlighted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if item.interaction.inlineNavigationLocation != nil {
|
|
||||||
reallyHighlighted = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return reallyHighlighted
|
return reallyHighlighted
|
||||||
}
|
}
|
||||||
@ -1403,7 +1405,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let textFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
let textFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||||
let dateFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
let dateFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||||
let badgeFont = Font.with(size: floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0), design: .regular, weight: .regular, traits: [.monospacedNumbers])
|
let badgeFont = Font.with(size: floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0), design: .regular, weight: .regular, traits: [.monospacedNumbers])
|
||||||
let avatarBadgeFont = Font.with(size: 16.0, design: .regular, weight: .regular, traits: [.monospacedNumbers])
|
let avatarBadgeFont = Font.with(size: floor(item.presentationData.fontSize.itemListBaseFontSize * 16.0 / 17.0), design: .regular, weight: .regular, traits: [.monospacedNumbers])
|
||||||
|
|
||||||
let account = item.context.account
|
let account = item.context.account
|
||||||
var messages: [EngineMessage]
|
var messages: [EngineMessage]
|
||||||
@ -1579,7 +1581,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let badgeDiameter = floor(item.presentationData.fontSize.baseDisplaySize * 20.0 / 17.0)
|
let badgeDiameter = floor(item.presentationData.fontSize.baseDisplaySize * 20.0 / 17.0)
|
||||||
let avatarBadgeDiameter: CGFloat = 22.0
|
let avatarBadgeDiameter: CGFloat = floor(floor(item.presentationData.fontSize.itemListBaseFontSize * 22.0 / 17.0))
|
||||||
|
|
||||||
let currentAvatarBadgeCleanBackgroundImage: UIImage? = PresentationResourcesChatList.badgeBackgroundBorder(item.presentationData.theme, diameter: avatarBadgeDiameter + 4.0)
|
let currentAvatarBadgeCleanBackgroundImage: UIImage? = PresentationResourcesChatList.badgeBackgroundBorder(item.presentationData.theme, diameter: avatarBadgeDiameter + 4.0)
|
||||||
|
|
||||||
@ -2354,7 +2356,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
itemHeight += titleSpacing
|
itemHeight += titleSpacing
|
||||||
itemHeight += authorSpacing
|
itemHeight += authorSpacing
|
||||||
|
|
||||||
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + 8.0), size: CGSize(width: rawContentWidth, height: itemHeight - 12.0 - 9.0))
|
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + floor(item.presentationData.fontSize.itemListBaseFontSize * 8.0 / 17.0)), size: CGSize(width: rawContentWidth, height: itemHeight - 12.0 - 9.0))
|
||||||
|
|
||||||
let insets = ChatListItemNode.insets(first: first, last: last, firstWithHeader: firstWithHeader)
|
let insets = ChatListItemNode.insets(first: first, last: last, firstWithHeader: firstWithHeader)
|
||||||
var heightOffset: CGFloat = 0.0
|
var heightOffset: CGFloat = 0.0
|
||||||
@ -2407,7 +2409,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
var mainContentAlpha: CGFloat = 1.0
|
var mainContentAlpha: CGFloat = 1.0
|
||||||
|
|
||||||
if case .chatList = item.chatListLocation {
|
if case .chatList = item.chatListLocation {
|
||||||
mainContentFrame = CGRect(origin: CGPoint(x: params.leftInset + 72.0, y: 0.0), size: CGSize(width: layout.contentSize.width, height: layout.contentSize.height))
|
mainContentFrame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: layout.contentSize.width, height: layout.contentSize.height))
|
||||||
mainContentBoundsOffset = mainContentFrame.origin.x
|
mainContentBoundsOffset = mainContentFrame.origin.x
|
||||||
|
|
||||||
if let inlineNavigationLocation = item.interaction.inlineNavigationLocation {
|
if let inlineNavigationLocation = item.interaction.inlineNavigationLocation {
|
||||||
@ -2497,7 +2499,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
var avatarScaleOffset: CGFloat = 0.0
|
var avatarScaleOffset: CGFloat = 0.0
|
||||||
var avatarScale: CGFloat = 1.0
|
var avatarScale: CGFloat = 1.0
|
||||||
if let inlineNavigationLocation = item.interaction.inlineNavigationLocation {
|
if let inlineNavigationLocation = item.interaction.inlineNavigationLocation {
|
||||||
let targetAvatarScale: CGFloat = 54.0 / avatarFrame.width
|
let targetAvatarScale: CGFloat = floor(item.presentationData.fontSize.itemListBaseFontSize * 54.0 / 17.0) / avatarFrame.width
|
||||||
avatarScale = targetAvatarScale * inlineNavigationLocation.progress + 1.0 * (1.0 - inlineNavigationLocation.progress)
|
avatarScale = targetAvatarScale * inlineNavigationLocation.progress + 1.0 * (1.0 - inlineNavigationLocation.progress)
|
||||||
|
|
||||||
let targetAvatarScaleOffset: CGFloat = -(avatarFrame.width - avatarFrame.width * avatarScale) * 0.5
|
let targetAvatarScaleOffset: CGFloat = -(avatarFrame.width - avatarFrame.width * avatarScale) * 0.5
|
||||||
@ -2863,7 +2865,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
finalBottomRect
|
finalBottomRect
|
||||||
], color: theme.pinnedItemBackgroundColor.mixedWith(theme.unreadBadgeInactiveBackgroundColor, alpha: 0.1))
|
], color: theme.pinnedItemBackgroundColor.mixedWith(theme.unreadBadgeInactiveBackgroundColor, alpha: 0.1))
|
||||||
|
|
||||||
compoundTextButtonNode.frame = compoundHighlightingNode.frame
|
transition.updateFrame(node: compoundTextButtonNode, frame: compoundHighlightingNode.frame)
|
||||||
|
|
||||||
if let textArrowImage = textArrowImage {
|
if let textArrowImage = textArrowImage {
|
||||||
let textArrowNode: ASImageNode
|
let textArrowNode: ASImageNode
|
||||||
@ -2903,8 +2905,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
if let dustNode = strongSelf.dustNode {
|
if let dustNode = strongSelf.dustNode {
|
||||||
compoundTextButtonNode.addSubnode(dustNode)
|
compoundTextButtonNode.addSubnode(dustNode)
|
||||||
}
|
}
|
||||||
|
strongSelf.textNode.textNode.frame = textNodeFrame.offsetBy(dx: -compoundTextButtonNode.frame.minX, dy: -compoundTextButtonNode.frame.minY)
|
||||||
}
|
}
|
||||||
strongSelf.textNode.textNode.frame = textNodeFrame.offsetBy(dx: -compoundTextButtonNode.frame.minX, dy: -compoundTextButtonNode.frame.minY)
|
|
||||||
|
|
||||||
strongSelf.authorNode.assignParentNode(parentNode: compoundTextButtonNode)
|
strongSelf.authorNode.assignParentNode(parentNode: compoundTextButtonNode)
|
||||||
} else {
|
} else {
|
||||||
@ -2913,8 +2915,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
if let dustNode = strongSelf.dustNode {
|
if let dustNode = strongSelf.dustNode {
|
||||||
strongSelf.mainContentContainerNode.addSubnode(dustNode)
|
strongSelf.mainContentContainerNode.addSubnode(dustNode)
|
||||||
}
|
}
|
||||||
|
strongSelf.textNode.textNode.frame = textNodeFrame
|
||||||
}
|
}
|
||||||
strongSelf.textNode.textNode.frame = textNodeFrame
|
|
||||||
|
|
||||||
strongSelf.authorNode.assignParentNode(parentNode: nil)
|
strongSelf.authorNode.assignParentNode(parentNode: nil)
|
||||||
}
|
}
|
||||||
@ -3043,9 +3045,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let titlePosition = strongSelf.titleNode.position
|
let titlePosition = strongSelf.titleNode.position
|
||||||
transition.animatePosition(node: strongSelf.titleNode, from: CGPoint(x: titlePosition.x - contentDelta.x, y: titlePosition.y - contentDelta.y))
|
transition.animatePosition(node: strongSelf.titleNode, from: CGPoint(x: titlePosition.x - contentDelta.x, y: titlePosition.y - contentDelta.y))
|
||||||
|
|
||||||
transition.animatePositionAdditive(node: strongSelf.textNode.textNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y))
|
if strongSelf.textNode.textNode.supernode === strongSelf.mainContentContainerNode {
|
||||||
if let dustNode = strongSelf.dustNode {
|
transition.animatePositionAdditive(node: strongSelf.textNode.textNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y))
|
||||||
transition.animatePositionAdditive(node: dustNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y))
|
if let dustNode = strongSelf.dustNode {
|
||||||
|
transition.animatePositionAdditive(node: dustNode, offset: CGPoint(x: -contentDelta.x, y: -contentDelta.y))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let authorPosition = strongSelf.authorNode.position
|
let authorPosition = strongSelf.authorNode.position
|
||||||
|
@ -659,10 +659,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
|
|||||||
hasTimer = true
|
hasTimer = true
|
||||||
}
|
}
|
||||||
|
|
||||||
var hasSchedule = true
|
let hasSchedule = true
|
||||||
if controller.chatLocation?.threadId != nil {
|
|
||||||
hasSchedule = false
|
|
||||||
}
|
|
||||||
|
|
||||||
self.openingMedia = true
|
self.openingMedia = true
|
||||||
|
|
||||||
|
@ -1,23 +1,58 @@
|
|||||||
|
|
||||||
final class MutableInvalidatedMessageHistoryTagSummariesView: MutablePostboxView {
|
final class MutableInvalidatedMessageHistoryTagSummariesView: MutablePostboxView {
|
||||||
|
private let peerId: PeerId?
|
||||||
|
private let threadId: Int64?
|
||||||
private let namespace: MessageId.Namespace
|
private let namespace: MessageId.Namespace
|
||||||
private let tagMask: MessageTags
|
private let tagMask: MessageTags
|
||||||
|
|
||||||
var entries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
var entries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
||||||
|
|
||||||
init(postbox: PostboxImpl, tagMask: MessageTags, namespace: MessageId.Namespace) {
|
init(postbox: PostboxImpl, peerId: PeerId?, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace) {
|
||||||
|
self.peerId = peerId
|
||||||
|
self.threadId = threadId
|
||||||
self.tagMask = tagMask
|
self.tagMask = tagMask
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
|
|
||||||
for entry in postbox.invalidatedMessageHistoryTagsSummaryTable.get(tagMask: tagMask, namespace: namespace) {
|
if let peerId = self.peerId {
|
||||||
self.entries.insert(entry)
|
if let entry = postbox.invalidatedMessageHistoryTagsSummaryTable.get(peerId: peerId, threadId: self.threadId, tagMask: self.tagMask, namespace: self.namespace) {
|
||||||
|
self.entries.insert(entry)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for entry in postbox.invalidatedMessageHistoryTagsSummaryTable.get(tagMask: tagMask, namespace: namespace) {
|
||||||
|
self.entries.insert(entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
|
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
|
||||||
var updated = false
|
var updated = false
|
||||||
for operation in transaction.currentInvalidateMessageTagSummaries {
|
|
||||||
switch operation {
|
if let peerId = self.peerId {
|
||||||
|
var maybeUpdated = false
|
||||||
|
loop: for operation in transaction.currentInvalidateMessageTagSummaries {
|
||||||
|
switch operation {
|
||||||
|
case let .add(entry):
|
||||||
|
if entry.key.peerId == peerId && entry.key.threadId == self.threadId {
|
||||||
|
maybeUpdated = true
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
case let .remove(key):
|
||||||
|
if key.peerId == peerId && key.threadId == self.threadId {
|
||||||
|
maybeUpdated = true
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if maybeUpdated {
|
||||||
|
self.entries.removeAll()
|
||||||
|
if let entry = postbox.invalidatedMessageHistoryTagsSummaryTable.get(peerId: peerId, threadId: self.threadId, tagMask: self.tagMask, namespace: self.namespace) {
|
||||||
|
self.entries.insert(entry)
|
||||||
|
}
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for operation in transaction.currentInvalidateMessageTagSummaries {
|
||||||
|
switch operation {
|
||||||
case let .add(entry):
|
case let .add(entry):
|
||||||
if entry.key.namespace == self.namespace && entry.key.tagMask == self.tagMask {
|
if entry.key.namespace == self.namespace && entry.key.tagMask == self.tagMask {
|
||||||
self.entries.insert(entry)
|
self.entries.insert(entry)
|
||||||
@ -33,8 +68,10 @@ final class MutableInvalidatedMessageHistoryTagSummariesView: MutablePostboxView
|
|||||||
}
|
}
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated
|
return updated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +74,10 @@ final class InvalidatedMessageHistoryTagsSummaryTable: Table {
|
|||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func get(peerId: PeerId, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace) -> InvalidatedMessageHistoryTagsSummaryEntry? {
|
||||||
|
return self.get(InvalidatedMessageHistoryTagsSummaryKey(peerId: peerId, namespace: namespace, tagMask: tagMask, threadId: threadId))
|
||||||
|
}
|
||||||
|
|
||||||
private func get(_ key: InvalidatedMessageHistoryTagsSummaryKey) -> InvalidatedMessageHistoryTagsSummaryEntry? {
|
private func get(_ key: InvalidatedMessageHistoryTagsSummaryKey) -> InvalidatedMessageHistoryTagsSummaryEntry? {
|
||||||
if let value = self.valueBox.get(self.table, key: self.key(key)) {
|
if let value = self.valueBox.get(self.table, key: self.key(key)) {
|
||||||
var version: Int32 = 0
|
var version: Int32 = 0
|
||||||
|
@ -10,7 +10,7 @@ public enum PostboxViewKey: Hashable {
|
|||||||
case globalMessageTags(globalTag: GlobalMessageTags, position: MessageIndex, count: Int, groupingPredicate: ((Message, Message) -> Bool)?)
|
case globalMessageTags(globalTag: GlobalMessageTags, position: MessageIndex, count: Int, groupingPredicate: ((Message, Message) -> Bool)?)
|
||||||
case peer(peerId: PeerId, components: PeerViewComponents)
|
case peer(peerId: PeerId, components: PeerViewComponents)
|
||||||
case pendingMessageActions(type: PendingMessageActionType)
|
case pendingMessageActions(type: PendingMessageActionType)
|
||||||
case invalidatedMessageHistoryTagSummaries(tagMask: MessageTags, namespace: MessageId.Namespace)
|
case invalidatedMessageHistoryTagSummaries(peerId: PeerId?, threadId: Int64?, tagMask: MessageTags, namespace: MessageId.Namespace)
|
||||||
case pendingMessageActionsSummary(type: PendingMessageActionType, peerId: PeerId, namespace: MessageId.Namespace)
|
case pendingMessageActionsSummary(type: PendingMessageActionType, peerId: PeerId, namespace: MessageId.Namespace)
|
||||||
case historyTagSummaryView(tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace)
|
case historyTagSummaryView(tag: MessageTags, peerId: PeerId, threadId: Int64?, namespace: MessageId.Namespace)
|
||||||
case cachedPeerData(peerId: PeerId)
|
case cachedPeerData(peerId: PeerId)
|
||||||
@ -61,7 +61,9 @@ public enum PostboxViewKey: Hashable {
|
|||||||
hasher.combine(peerId)
|
hasher.combine(peerId)
|
||||||
case let .pendingMessageActions(type):
|
case let .pendingMessageActions(type):
|
||||||
hasher.combine(type)
|
hasher.combine(type)
|
||||||
case let .invalidatedMessageHistoryTagSummaries(tagMask, namespace):
|
case let .invalidatedMessageHistoryTagSummaries(peerId, threadId, tagMask, namespace):
|
||||||
|
hasher.combine(peerId)
|
||||||
|
hasher.combine(threadId)
|
||||||
hasher.combine(tagMask)
|
hasher.combine(tagMask)
|
||||||
hasher.combine(namespace)
|
hasher.combine(namespace)
|
||||||
case let .pendingMessageActionsSummary(type, peerId, namespace):
|
case let .pendingMessageActionsSummary(type, peerId, namespace):
|
||||||
@ -191,8 +193,8 @@ public enum PostboxViewKey: Hashable {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case .invalidatedMessageHistoryTagSummaries:
|
case let .invalidatedMessageHistoryTagSummaries(peerId, threadId, tagMask, namespace):
|
||||||
if case .invalidatedMessageHistoryTagSummaries = rhs {
|
if case .invalidatedMessageHistoryTagSummaries(peerId, threadId, tagMask, namespace) = rhs {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@ -395,8 +397,8 @@ func postboxViewForKey(postbox: PostboxImpl, key: PostboxViewKey) -> MutablePost
|
|||||||
return MutablePeerView(postbox: postbox, peerId: peerId, components: components)
|
return MutablePeerView(postbox: postbox, peerId: peerId, components: components)
|
||||||
case let .pendingMessageActions(type):
|
case let .pendingMessageActions(type):
|
||||||
return MutablePendingMessageActionsView(postbox: postbox, type: type)
|
return MutablePendingMessageActionsView(postbox: postbox, type: type)
|
||||||
case let .invalidatedMessageHistoryTagSummaries(tagMask, namespace):
|
case let .invalidatedMessageHistoryTagSummaries(peerId, threadId, tagMask, namespace):
|
||||||
return MutableInvalidatedMessageHistoryTagSummariesView(postbox: postbox, tagMask: tagMask, namespace: namespace)
|
return MutableInvalidatedMessageHistoryTagSummariesView(postbox: postbox, peerId: peerId, threadId: threadId, tagMask: tagMask, namespace: namespace)
|
||||||
case let .pendingMessageActionsSummary(type, peerId, namespace):
|
case let .pendingMessageActionsSummary(type, peerId, namespace):
|
||||||
return MutablePendingMessageActionsSummaryView(postbox: postbox, type: type, peerId: peerId, namespace: namespace)
|
return MutablePendingMessageActionsSummaryView(postbox: postbox, type: type, peerId: peerId, namespace: namespace)
|
||||||
case let .historyTagSummaryView(tag, peerId, threadId, namespace):
|
case let .historyTagSummaryView(tag, peerId, threadId, namespace):
|
||||||
|
@ -1091,7 +1091,6 @@ public class Account {
|
|||||||
self.managedOperationsDisposable.add(managedSynchronizeConsumeMessageContentOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedSynchronizeConsumeMessageContentOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedConsumePersonalMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedConsumePersonalMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedReadReactionActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedReadReactionActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedSynchronizeMessageHistoryTagSummaries(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
|
||||||
self.managedOperationsDisposable.add(managedSynchronizeMarkAllUnseenPersonalMessagesOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedSynchronizeMarkAllUnseenPersonalMessagesOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedSynchronizeMarkAllUnseenReactionsOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedSynchronizeMarkAllUnseenReactionsOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
|
@ -93,7 +93,7 @@ func managedConsumePersonalMessagesActions(postbox: Postbox, network: Network, s
|
|||||||
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
|
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
|
||||||
|
|
||||||
let actionsKey = PostboxViewKey.pendingMessageActions(type: .consumeUnseenPersonalMessage)
|
let actionsKey = PostboxViewKey.pendingMessageActions(type: .consumeUnseenPersonalMessage)
|
||||||
let invalidateKey = PostboxViewKey.invalidatedMessageHistoryTagSummaries(tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud)
|
let invalidateKey = PostboxViewKey.invalidatedMessageHistoryTagSummaries(peerId: nil, threadId: nil, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud)
|
||||||
let disposable = postbox.combinedView(keys: [actionsKey, invalidateKey]).start(next: { view in
|
let disposable = postbox.combinedView(keys: [actionsKey, invalidateKey]).start(next: { view in
|
||||||
var entries: [PendingMessageActionsEntry] = []
|
var entries: [PendingMessageActionsEntry] = []
|
||||||
var invalidateEntries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
var invalidateEntries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
||||||
@ -156,7 +156,7 @@ func managedReadReactionActions(postbox: Postbox, network: Network, stateManager
|
|||||||
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
|
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
|
||||||
|
|
||||||
let actionsKey = PostboxViewKey.pendingMessageActions(type: .readReaction)
|
let actionsKey = PostboxViewKey.pendingMessageActions(type: .readReaction)
|
||||||
let invalidateKey = PostboxViewKey.invalidatedMessageHistoryTagSummaries(tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud)
|
let invalidateKey = PostboxViewKey.invalidatedMessageHistoryTagSummaries(peerId: nil, threadId: nil, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud)
|
||||||
let disposable = postbox.combinedView(keys: [actionsKey, invalidateKey]).start(next: { view in
|
let disposable = postbox.combinedView(keys: [actionsKey, invalidateKey]).start(next: { view in
|
||||||
var entries: [PendingMessageActionsEntry] = []
|
var entries: [PendingMessageActionsEntry] = []
|
||||||
var invalidateEntries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
var invalidateEntries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
||||||
@ -435,11 +435,11 @@ private func synchronizeUnseenReactionsTag(postbox: Postbox, network: Network, e
|
|||||||
} |> switchToLatest
|
} |> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
func managedSynchronizeMessageHistoryTagSummaries(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
func managedSynchronizeMessageHistoryTagSummaries(postbox: Postbox, network: Network, stateManager: AccountStateManager, peerId: PeerId, threadId: Int64) -> Signal<Void, NoError> {
|
||||||
return Signal { _ in
|
return Signal { _ in
|
||||||
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
|
let helper = Atomic<ManagedConsumePersonalMessagesActionsHelper>(value: ManagedConsumePersonalMessagesActionsHelper())
|
||||||
|
|
||||||
let invalidateKey = PostboxViewKey.invalidatedMessageHistoryTagSummaries(tagMask: MessageTags(rawValue: 0), namespace: Namespaces.Message.Cloud)
|
let invalidateKey = PostboxViewKey.invalidatedMessageHistoryTagSummaries(peerId: peerId, threadId: threadId, tagMask: MessageTags(rawValue: 0), namespace: Namespaces.Message.Cloud)
|
||||||
let disposable = postbox.combinedView(keys: [invalidateKey]).start(next: { view in
|
let disposable = postbox.combinedView(keys: [invalidateKey]).start(next: { view in
|
||||||
var invalidateEntries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
var invalidateEntries = Set<InvalidatedMessageHistoryTagsSummaryEntry>()
|
||||||
if let v = view.views[invalidateKey] as? InvalidatedMessageHistoryTagSummariesView {
|
if let v = view.views[invalidateKey] as? InvalidatedMessageHistoryTagSummariesView {
|
||||||
@ -480,7 +480,7 @@ private func synchronizeMessageHistoryTagSummary(postbox: Postbox, network: Netw
|
|||||||
guard let threadId = entry.key.threadId else {
|
guard let threadId = entry.key.threadId else {
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
if let peer = transaction.getPeer(entry.key.peerId), let inputPeer = apiInputPeer(peer) {
|
if let peer = transaction.getPeer(entry.key.peerId) as? TelegramChannel, peer.flags.contains(.isForum), let inputPeer = apiInputPeer(peer) {
|
||||||
return network.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: Int32(clamping: threadId), offsetId: 0, offsetDate: 0, addOffset: 0, limit: 1, maxId: 0, minId: 0, hash: 0))
|
return network.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: Int32(clamping: threadId), offsetId: 0, offsetDate: 0, addOffset: 0, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||||
|
@ -590,6 +590,14 @@ public struct ChatReplyThreadMessage: Equatable {
|
|||||||
self.initialAnchor = initialAnchor
|
self.initialAnchor = initialAnchor
|
||||||
self.isNotAvailable = isNotAvailable
|
self.isNotAvailable = isNotAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var normalized: ChatReplyThreadMessage {
|
||||||
|
if self.isForumPost {
|
||||||
|
return ChatReplyThreadMessage(messageId: self.messageId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||||
|
} else {
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum FetchChannelReplyThreadMessageError {
|
public enum FetchChannelReplyThreadMessageError {
|
||||||
|
@ -494,5 +494,10 @@ public extension TelegramEngine {
|
|||||||
}
|
}
|
||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func keepMessageCountersSyncrhonized(peerId: EnginePeer.Id, threadId: Int64) -> Signal<Never, NoError> {
|
||||||
|
return managedSynchronizeMessageHistoryTagSummaries(postbox: self.account.postbox, network: self.account.network, stateManager: self.account.stateManager, peerId: peerId, threadId: threadId)
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ public func stringForFullAuthorName(message: EngineMessage, strings: Presentatio
|
|||||||
var authorName = ""
|
var authorName = ""
|
||||||
if author.id == accountPeerId {
|
if author.id == accountPeerId {
|
||||||
authorName = strings.DialogList_You
|
authorName = strings.DialogList_You
|
||||||
|
} else if author.isDeleted {
|
||||||
|
authorName = strings.User_DeletedAccount
|
||||||
} else {
|
} else {
|
||||||
authorName = author.compactDisplayTitle
|
authorName = author.compactDisplayTitle
|
||||||
}
|
}
|
||||||
|
@ -317,7 +317,7 @@ final class AuthorizedApplicationContext {
|
|||||||
if let _ = threadData, let threadId = firstMessage.threadId {
|
if let _ = threadData, let threadId = firstMessage.threadId {
|
||||||
chatLocation = .replyThread(ChatReplyThreadMessage(
|
chatLocation = .replyThread(ChatReplyThreadMessage(
|
||||||
messageId: MessageId(peerId: firstMessage.id.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
messageId: MessageId(peerId: firstMessage.id.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||||
))
|
).normalized)
|
||||||
} else {
|
} else {
|
||||||
guard let peer = firstMessage.peers[firstMessage.id.peerId] else {
|
guard let peer = firstMessage.peers[firstMessage.id.peerId] else {
|
||||||
return
|
return
|
||||||
|
@ -295,6 +295,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
private var hasActiveGroupCallDisposable: Disposable?
|
private var hasActiveGroupCallDisposable: Disposable?
|
||||||
private var sendAsPeersDisposable: Disposable?
|
private var sendAsPeersDisposable: Disposable?
|
||||||
private var preloadAttachBotIconsDisposables: DisposableSet?
|
private var preloadAttachBotIconsDisposables: DisposableSet?
|
||||||
|
private var keepMessageCountersSyncrhonizedDisposable: Disposable?
|
||||||
|
|
||||||
private let editingMessage = ValuePromise<Float?>(nil, ignoreRepeated: true)
|
private let editingMessage = ValuePromise<Float?>(nil, ignoreRepeated: true)
|
||||||
private let startingBot = ValuePromise<Bool>(false, ignoreRepeated: true)
|
private let startingBot = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||||
@ -5663,6 +5664,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.inviteRequestsDisposable.dispose()
|
self.inviteRequestsDisposable.dispose()
|
||||||
self.sendAsPeersDisposable?.dispose()
|
self.sendAsPeersDisposable?.dispose()
|
||||||
self.preloadAttachBotIconsDisposables?.dispose()
|
self.preloadAttachBotIconsDisposables?.dispose()
|
||||||
|
self.keepMessageCountersSyncrhonizedDisposable?.dispose()
|
||||||
}
|
}
|
||||||
deallocate()
|
deallocate()
|
||||||
}
|
}
|
||||||
@ -9326,7 +9328,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard case let .peer(peerId) = strongSelf.chatLocation else {
|
guard let peerId = strongSelf.chatLocation.peerId else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let pinnedMessage = strongSelf.presentationInterfaceState.pinnedMessage else {
|
guard let pinnedMessage = strongSelf.presentationInterfaceState.pinnedMessage else {
|
||||||
@ -9370,7 +9372,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .pinnedMessages(id: pinnedMessage.message.id), botStart: nil, mode: .standard(previewing: true))
|
let chatLocation: ChatLocation
|
||||||
|
if let _ = strongSelf.chatLocation.threadId {
|
||||||
|
chatLocation = strongSelf.chatLocation
|
||||||
|
} else {
|
||||||
|
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))
|
||||||
chatController.canReadHistory.set(false)
|
chatController.canReadHistory.set(false)
|
||||||
|
|
||||||
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
|
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
|
||||||
@ -9986,6 +9995,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if case let .replyThread(message) = self.chatLocation, message.isForumPost {
|
||||||
|
if self.keepMessageCountersSyncrhonizedDisposable == nil {
|
||||||
|
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: message.messageId.peerId, threadId: Int64(message.messageId.id)).start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let scheduledActivateInput = scheduledActivateInput, case .text = scheduledActivateInput {
|
if let scheduledActivateInput = scheduledActivateInput, case .text = scheduledActivateInput {
|
||||||
self.scheduledActivateInput = nil
|
self.scheduledActivateInput = nil
|
||||||
|
|
||||||
@ -14964,16 +14979,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isPinnedMessages, let messageId = messageLocation.messageId {
|
if isPinnedMessages, let messageId = messageLocation.messageId {
|
||||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId))
|
let _ = (combineLatest(
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] peer in
|
self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: messageId.peerId)),
|
||||||
|
self.context.engine.messages.getMessagesLoadIfNecessary([messageId], strategy: .local)
|
||||||
|
)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] peer, messages in
|
||||||
guard let self, let peer = peer else {
|
guard let self, let peer = peer else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
guard let navigationController = self.effectiveNavigationController else {
|
||||||
if let navigationController = self.effectiveNavigationController {
|
return
|
||||||
self.dismiss()
|
|
||||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.dismiss()
|
||||||
|
|
||||||
|
let navigateToLocation: NavigateToChatControllerParams.Location
|
||||||
|
if let threadId = messages.first?.threadId {
|
||||||
|
navigateToLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||||
|
} else {
|
||||||
|
navigateToLocation = .peer(peer)
|
||||||
|
}
|
||||||
|
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: navigateToLocation, subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always))
|
||||||
})
|
})
|
||||||
} 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)) {
|
} 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(
|
let _ = (self.context.engine.data.get(
|
||||||
|
@ -2368,24 +2368,57 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if let loaded = displayedRange.visibleRange, let firstEntry = historyView.filteredEntries.first, let lastEntry = historyView.filteredEntries.last {
|
if let loaded = displayedRange.visibleRange, let firstEntry = historyView.filteredEntries.first, let lastEntry = historyView.filteredEntries.last {
|
||||||
if loaded.firstIndex < 5 && historyView.originalView.laterId != nil {
|
|
||||||
if !"".isEmpty {
|
var mathesFirst = false
|
||||||
print("load next")
|
if loaded.firstIndex <= 5 {
|
||||||
return
|
var firstHasGroups = false
|
||||||
|
for index in (max(0, historyView.filteredEntries.count - 5) ..< historyView.filteredEntries.count).reversed() {
|
||||||
|
switch historyView.filteredEntries[index] {
|
||||||
|
case .MessageEntry:
|
||||||
|
break
|
||||||
|
case .MessageGroupEntry:
|
||||||
|
firstHasGroups = true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if firstHasGroups {
|
||||||
|
mathesFirst = loaded.firstIndex <= 1
|
||||||
|
} else {
|
||||||
|
mathesFirst = loaded.firstIndex <= 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mathesLast = false
|
||||||
|
if loaded.lastIndex >= historyView.filteredEntries.count - 5 {
|
||||||
|
var lastHasGroups = false
|
||||||
|
for index in 0 ..< min(5, historyView.filteredEntries.count) {
|
||||||
|
switch historyView.filteredEntries[index] {
|
||||||
|
case .MessageEntry:
|
||||||
|
break
|
||||||
|
case .MessageGroupEntry:
|
||||||
|
lastHasGroups = true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if lastHasGroups {
|
||||||
|
mathesLast = loaded.lastIndex >= historyView.filteredEntries.count - 1
|
||||||
|
} else {
|
||||||
|
mathesLast = loaded.lastIndex >= historyView.filteredEntries.count - 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if mathesFirst && historyView.originalView.laterId != nil {
|
||||||
let locationInput: ChatHistoryLocation = .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount, highlight: false)
|
let locationInput: ChatHistoryLocation = .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount, highlight: false)
|
||||||
if self.chatHistoryLocationValue?.content != locationInput {
|
if self.chatHistoryLocationValue?.content != locationInput {
|
||||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())
|
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())
|
||||||
}
|
}
|
||||||
} else if loaded.firstIndex < 5, historyView.originalView.laterId == nil, !historyView.originalView.holeLater, let chatHistoryLocationValue = self.chatHistoryLocationValue, !chatHistoryLocationValue.isAtUpperBound, historyView.originalView.anchorIndex != .upperBound {
|
} else if mathesFirst, historyView.originalView.laterId == nil, !historyView.originalView.holeLater, let chatHistoryLocationValue = self.chatHistoryLocationValue, !chatHistoryLocationValue.isAtUpperBound, historyView.originalView.anchorIndex != .upperBound {
|
||||||
if self.chatHistoryLocationValue == historyView.locationInput {
|
if self.chatHistoryLocationValue == historyView.locationInput {
|
||||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .upperBound, anchorIndex: .upperBound, count: historyMessageCount, highlight: false), id: self.takeNextHistoryLocationId())
|
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .upperBound, anchorIndex: .upperBound, count: historyMessageCount, highlight: false), id: self.takeNextHistoryLocationId())
|
||||||
}
|
}
|
||||||
} else if loaded.lastIndex >= historyView.filteredEntries.count - 5 && historyView.originalView.earlierId != nil {
|
} else if mathesLast && historyView.originalView.earlierId != nil {
|
||||||
if !"".isEmpty {
|
|
||||||
print("load previous")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let locationInput: ChatHistoryLocation = .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount, highlight: false)
|
let locationInput: ChatHistoryLocation = .Navigation(index: .message(firstEntry.index), anchorIndex: .message(firstEntry.index), count: historyMessageCount, highlight: false)
|
||||||
if self.chatHistoryLocationValue?.content != locationInput {
|
if self.chatHistoryLocationValue?.content != locationInput {
|
||||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())
|
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: locationInput, id: self.takeNextHistoryLocationId())
|
||||||
|
@ -93,7 +93,10 @@ func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Ch
|
|||||||
if let channel = presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.flags.contains(.isForum), let moreInfoNavigationButton = moreInfoNavigationButton {
|
if let channel = presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.flags.contains(.isForum), let moreInfoNavigationButton = moreInfoNavigationButton {
|
||||||
if case .replyThread = presentationInterfaceState.chatLocation {
|
if case .replyThread = presentationInterfaceState.chatLocation {
|
||||||
} else {
|
} else {
|
||||||
return moreInfoNavigationButton
|
if case .pinnedMessages = presentationInterfaceState.subject {
|
||||||
|
} else {
|
||||||
|
return moreInfoNavigationButton
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,11 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
var isFirst = true
|
var isFirst = true
|
||||||
if params.useExisting {
|
if params.useExisting {
|
||||||
for controller in params.navigationController.viewControllers.reversed() {
|
for controller in params.navigationController.viewControllers.reversed() {
|
||||||
if let controller = controller as? ChatControllerImpl, controller.chatLocation == params.chatLocation.asChatLocation && (controller.subject != .scheduledMessages || controller.subject == params.subject) {
|
guard let controller = controller as? ChatControllerImpl else {
|
||||||
|
isFirst = false
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if controller.chatLocation.peerId == params.chatLocation.asChatLocation.peerId && controller.chatLocation.threadId == params.chatLocation.asChatLocation.threadId && (controller.subject != .scheduledMessages || controller.subject == params.subject) {
|
||||||
if let updateTextInputState = params.updateTextInputState {
|
if let updateTextInputState = params.updateTextInputState {
|
||||||
controller.updateTextInputState(updateTextInputState)
|
controller.updateTextInputState(updateTextInputState)
|
||||||
}
|
}
|
||||||
|
@ -2180,7 +2180,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self.usernameNode.displaysAsynchronously = false
|
self.usernameNode.displaysAsynchronously = false
|
||||||
|
|
||||||
self.buttonsContainerNode = SparseNode()
|
self.buttonsContainerNode = SparseNode()
|
||||||
self.buttonsContainerNode.clipsToBounds = false
|
self.buttonsContainerNode.clipsToBounds = true
|
||||||
|
|
||||||
self.regularContentNode = PeerInfoHeaderRegularContentNode()
|
self.regularContentNode = PeerInfoHeaderRegularContentNode()
|
||||||
var requestUpdateLayoutImpl: (() -> Void)?
|
var requestUpdateLayoutImpl: (() -> Void)?
|
||||||
@ -2930,10 +2930,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if subtitleIsButton {
|
|
||||||
subtitleFrame.origin.y += 11.0
|
|
||||||
}
|
|
||||||
|
|
||||||
let singleTitleLockOffset: CGFloat = (peer?.id == self.context.account.peerId || subtitleSize.height.isZero) ? 8.0 : 0.0
|
let singleTitleLockOffset: CGFloat = (peer?.id == self.context.account.peerId || subtitleSize.height.isZero) ? 8.0 : 0.0
|
||||||
|
|
||||||
let titleLockOffset: CGFloat = 7.0 + singleTitleLockOffset
|
let titleLockOffset: CGFloat = 7.0 + singleTitleLockOffset
|
||||||
@ -3028,6 +3024,19 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction
|
avatarOffset = apparentTitleLockOffset + 0.0 * (1.0 - titleCollapseFraction) + 10.0 * titleCollapseFraction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if subtitleIsButton {
|
||||||
|
subtitleFrame.origin.y += 11.0 * (1.0 - titleCollapseFraction)
|
||||||
|
if let subtitleBackgroundButton = self.subtitleBackgroundButton {
|
||||||
|
transition.updateAlpha(node: subtitleBackgroundButton, alpha: (1.0 - titleCollapseFraction))
|
||||||
|
}
|
||||||
|
if let subtitleBackgroundNode = self.subtitleBackgroundNode {
|
||||||
|
transition.updateAlpha(node: subtitleBackgroundNode, alpha: (1.0 - titleCollapseFraction))
|
||||||
|
}
|
||||||
|
if let subtitleArrowNode = self.subtitleArrowNode {
|
||||||
|
transition.updateAlpha(node: subtitleArrowNode, alpha: (1.0 - titleCollapseFraction))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let avatarCornerRadius: CGFloat
|
let avatarCornerRadius: CGFloat
|
||||||
if let channel = peer as? TelegramChannel, channel.flags.contains(.isForum) {
|
if let channel = peer as? TelegramChannel, channel.flags.contains(.isForum) {
|
||||||
avatarCornerRadius = floor(avatarSize * 0.25)
|
avatarCornerRadius = floor(avatarSize * 0.25)
|
||||||
|
@ -678,12 +678,27 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return context.engine.peers.fetchForumChannelTopic(id: channel.id, threadId: Int64(messageId.id))
|
return context.engine.messages.getMessagesLoadIfNecessary([messageId], strategy: .cloud(skipLocal: false))
|
||||||
|> map { info -> ResolvedUrl? in
|
|> take(1)
|
||||||
if let _ = info {
|
|> mapToSignal { messages -> Signal<ResolvedUrl?, NoError> in
|
||||||
return .replyThread(messageId: messageId)
|
if let threadId = messages.first?.threadId {
|
||||||
|
return context.engine.peers.fetchForumChannelTopic(id: channel.id, threadId: threadId)
|
||||||
|
|> map { info -> ResolvedUrl? in
|
||||||
|
if let _ = info {
|
||||||
|
return .replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId)
|
||||||
|
} else {
|
||||||
|
return .peer(peer?._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return .peer(foundPeer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil))
|
return context.engine.peers.fetchForumChannelTopic(id: channel.id, threadId: Int64(messageId.id))
|
||||||
|
|> map { info -> ResolvedUrl? in
|
||||||
|
if let _ = info {
|
||||||
|
return .replyThread(messageId: messageId)
|
||||||
|
} else {
|
||||||
|
return .peer(foundPeer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user