[WIP] Stories

This commit is contained in:
Ali 2023-05-26 22:13:22 +04:00
parent d12758ddb0
commit ebd414691c
92 changed files with 1788 additions and 699 deletions

View File

@ -1,6 +1,7 @@
import Foundation
import UIKit
import TelegramCore
import Postbox
import TextFormat
import AsyncDisplayKit
import Display
@ -666,5 +667,6 @@ public enum FileMediaResourceMediaStatus: Equatable {
public protocol ChatMessageItemNodeProtocol: ListViewItemNode {
func targetReactionView(value: MessageReaction.Reaction) -> UIView?
func targetForStoryTransition(id: StoryId) -> UIView?
func contentFrame() -> CGRect
}

View File

@ -54,7 +54,63 @@ private func fixListNodeScrolling(_ listNode: ListView, searchNode: NavigationBa
return false
}
let storiesFraction = 94.0 / (navigationBarSearchContentHeight + 94.0)
let visibleStoriesProgress: CGFloat
do {
let fraction = navigationBarSearchContentHeight / searchNode.nominalHeight
let fromLow: CGFloat = fraction
let toLow: CGFloat = 0.0
let fromHigh: CGFloat = 1.0
let toHigh: CGFloat = 1.0
let visibleProgress: CGFloat = toLow + (searchNode.expansionProgress - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
visibleStoriesProgress = max(0.0, min(1.0, visibleProgress))
}
let visibleSearchProgress: CGFloat
do {
let fieldHeight: CGFloat = 36.0
let fraction = fieldHeight / searchNode.nominalHeight
let fullFraction = navigationBarSearchContentHeight / searchNode.nominalHeight
let fromLow: CGFloat = fullFraction - fraction
let toLow: CGFloat = 0.0
let fromHigh: CGFloat = fullFraction
let toHigh: CGFloat = 1.0
let visibleProgress: CGFloat = toLow + (searchNode.expansionProgress - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
visibleSearchProgress = max(0.0, min(1.0, visibleProgress))
}
//print("visibleStoriesProgress = \(visibleStoriesProgress)")
//print("visibleSearchProgress = \(visibleSearchProgress)")
if visibleStoriesProgress > 0.0 && visibleStoriesProgress < 1.0 {
let offset: CGFloat
if visibleStoriesProgress < 0.6 {
offset = 94.0
} else {
offset = 0.0
}
let _ = listNode.scrollToOffsetFromTop(offset, animated: true)
return true
}
if visibleSearchProgress > 0.0 && visibleSearchProgress < 1.0 {
let offset: CGFloat
if visibleSearchProgress < 0.6 {
offset = 94.0 + navigationBarSearchContentHeight
} else {
offset = 94.0
}
let _ = listNode.scrollToOffsetFromTop(offset, animated: true)
return true
}
if searchNode.expansionProgress > 0.0 && searchNode.expansionProgress < 0.2 {
let _ = listNode.scrollToOffsetFromTop(94.0 + navigationBarSearchContentHeight, animated: true)
return true
}
/*let storiesFraction = 94.0 / (navigationBarSearchContentHeight + 94.0)
var visibleStoriesProgress = max(0.0, min(1.0, searchNode.expansionProgress))
visibleStoriesProgress = (1.0 / storiesFraction) * visibleStoriesProgress
@ -122,7 +178,7 @@ private func fixListNodeScrolling(_ listNode: ListView, searchNode: NavigationBa
return true
}
}
}
}*/
return false
}
@ -178,6 +234,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
fileprivate private(set) var primaryContext: ChatListLocationContext?
private let primaryInfoReady = Promise<Bool>()
private let mainReady = Promise<Bool>()
private let storiesReady = Promise<Bool>()
private var pendingSecondaryContext: ChatListLocationContext?
fileprivate private(set) var secondaryContext: ChatListLocationContext?
@ -482,9 +540,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
tabsIsEmpty = true
}
if case .chatList(.root) = self.location {
self.searchContentNode?.additionalHeight = 94.0
}
self.navigationBar?.secondaryContentHeight = !tabsIsEmpty ? NavigationBar.defaultSecondaryContentHeight : 0.0
enum State: Equatable {
@ -1250,6 +1305,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if validLayout.inVoiceOver {
offset = .known(0.0)
}
//print("offset: \(offset), additionalHeight: \(searchContentNode.additionalHeight)")
searchContentNode.updateListVisibleContentOffset(offset, transition: strongSelf.chatListDisplayNode.temporaryContentOffsetChangeTransition ?? .immediate)
}
}
@ -1813,8 +1869,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
if case .chatList(.root) = self.location {
self.ready.set(.never())
self.ready.set(combineLatest([self.mainReady.get(), self.storiesReady.get()])
|> map { values -> Bool in
return !values.contains(where: { !$0 })
}
|> filter { $0 }
|> take(1))
} else {
self.storiesReady.set(.single(true))
self.ready.set(combineLatest([
self.chatListDisplayNode.mainContainerNode.ready,
self.primaryInfoReady.get()
@ -1826,6 +1889,88 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
self.displayNodeDidLoad()
if case .chatList(.root) = self.location {
self.preloadStorySubscriptionsDisposable = (self.context.engine.messages.preloadStorySubscriptions()
|> deliverOnMainQueue).start(next: { [weak self] resources in
guard let self else {
return
}
var validIds: [MediaResourceId] = []
for (_, info) in resources.sorted(by: { $0.value.priority < $1.value.priority }) {
let resource = info.resource
validIds.append(resource.resource.id)
if self.preloadStoryResourceDisposables[resource.resource.id] == nil {
var fetchRange: (Range<Int64>, MediaBoxFetchPriority)?
if let size = info.size {
fetchRange = (0 ..< Int64(size), .default)
}
self.preloadStoryResourceDisposables[resource.resource.id] = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: resource, range: fetchRange).start()
}
}
var removeIds: [MediaResourceId] = []
for (id, disposable) in self.preloadStoryResourceDisposables {
if !validIds.contains(id) {
removeIds.append(id)
disposable.dispose()
}
}
for id in removeIds {
self.preloadStoryResourceDisposables.removeValue(forKey: id)
}
})
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions()
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
guard let self else {
return
}
var wasEmpty = true
if let storySubscriptions = self.storySubscriptions, !storySubscriptions.items.isEmpty {
wasEmpty = false
}
self.storySubscriptions = storySubscriptions
let isEmpty = storySubscriptions.items.isEmpty
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
var chatListState = chatListState
var peersWithNewStories = Set<EnginePeer.Id>()
for item in storySubscriptions.items {
if item.peer.id == self.context.account.peerId {
continue
}
if item.hasUnseen {
peersWithNewStories.insert(item.peer.id)
}
}
chatListState.peersWithNewStories = peersWithNewStories
return chatListState
}
self.storyListHeight = isEmpty ? 0.0 : 94.0
let transition: ContainedViewLayoutTransition
if self.didAppear {
transition = .animated(duration: 0.4, curve: .spring)
} else {
transition = .immediate
}
if wasEmpty != isEmpty {
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = transition
self.requestLayout(transition: transition)
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
} else {
self.requestUpdateHeaderContent(transition: transition)
}
self.storiesReady.set(.single(true))
})
}
}
public override func displayNodeDidLoad() {
@ -2122,82 +2267,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
})
self.preloadStorySubscriptionsDisposable = (self.context.engine.messages.preloadStorySubscriptions()
|> deliverOnMainQueue).start(next: { [weak self] resources in
guard let self else {
return
}
var validIds: [MediaResourceId] = []
for (_, info) in resources.sorted(by: { $0.value.priority < $1.value.priority }) {
let resource = info.resource
validIds.append(resource.resource.id)
if self.preloadStoryResourceDisposables[resource.resource.id] == nil {
var fetchRange: (Range<Int64>, MediaBoxFetchPriority)?
if let size = info.size {
fetchRange = (0 ..< Int64(size), .default)
}
self.preloadStoryResourceDisposables[resource.resource.id] = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .other, userContentType: .other, reference: resource, range: fetchRange).start()
}
}
var removeIds: [MediaResourceId] = []
for (id, disposable) in self.preloadStoryResourceDisposables {
if !validIds.contains(id) {
removeIds.append(id)
disposable.dispose()
}
}
for id in removeIds {
self.preloadStoryResourceDisposables.removeValue(forKey: id)
}
})
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions()
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
guard let self else {
return
}
var wasEmpty = true
if let storySubscriptions = self.storySubscriptions, !storySubscriptions.items.isEmpty {
wasEmpty = false
}
self.storySubscriptions = storySubscriptions
let isEmpty = storySubscriptions.items.isEmpty
self.chatListDisplayNode.mainContainerNode.currentItemNode.updateState { chatListState in
var chatListState = chatListState
var peersWithNewStories = Set<EnginePeer.Id>()
for item in storySubscriptions.items {
if item.peer.id == self.context.account.peerId {
continue
}
if item.hasUnseen {
peersWithNewStories.insert(item.peer.id)
}
}
chatListState.peersWithNewStories = peersWithNewStories
return chatListState
}
self.storyListHeight = isEmpty ? 0.0 : 94.0
if case .chatList(.root) = self.location {
self.searchContentNode?.additionalHeight = 94.0
}
if wasEmpty != isEmpty {
let transition: ContainedViewLayoutTransition = .animated(duration: 0.4, curve: .spring)
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = transition
self.requestLayout(transition: transition)
self.chatListDisplayNode.temporaryContentOffsetChangeTransition = nil
} else {
self.updateHeaderStories(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)).containedViewLayoutTransition)
}
})
}
self.chatListDisplayNode.mainContainerNode.addedVisibleChatsWithPeerIds = { [weak self] peerIds in
@ -2390,6 +2459,20 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
)
}
var storiesFraction: CGFloat = 0.0
if let searchContentNode = self.searchContentNode, case .chatList(.root) = self.location {
if self.storyListHeight > 0.0 {
let fraction = navigationBarSearchContentHeight / searchContentNode.nominalHeight
let fromLow: CGFloat = fraction
let toLow: CGFloat = 0.0
let fromHigh: CGFloat = 1.0
let toHigh: CGFloat = 1.0
let visibleProgress: CGFloat = toLow + (searchContentNode.expansionProgress - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
storiesFraction = max(0.0, min(1.0, visibleProgress))
}
}
let _ = self.headerContentView.update(
transition: Transition(transition),
component: AnyComponent(ChatListHeaderComponent(
@ -2398,6 +2481,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
secondaryContent: secondaryContent,
secondaryTransition: self.chatListDisplayNode.inlineStackContainerTransitionFraction,
networkStatus: nil,
storySubscriptions: self.storySubscriptions,
storiesFraction: storiesFraction,
context: self.context,
theme: self.presentationData.theme,
strings: self.presentationData.strings,
@ -2422,16 +2507,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.navigationBar?.customHeaderContentView = componentView
}
}
}
override public func updateNavigationBarLayout(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
self.updateHeaderContent(layout: layout, transition: transition)
super.updateNavigationBarLayout(layout, transition: transition)
}
private func updateHeaderStories(transition: ContainedViewLayoutTransition) {
if let searchContentNode = self.searchContentNode, case .chatList(.root) = self.location {
if case .chatList(.root) = self.location {
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
componentView.storyPeerAction = { [weak self] peer in
guard let self else {
@ -2490,32 +2566,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
}
}
if let peer, peer.id == self.context.account.peerId {
if let stateValue = storyContent.stateValue {
let _ = stateValue
}
/*if initialFocusedId == AnyHashable(self.context.account.peerId), let firstItem = initialContent.first, firstItem.id == initialFocusedId && firstItem.items.isEmpty {
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
rootController.openStoryCamera(transitionIn: cameraTransitionIn, transitionOut: { [weak self] _ in
guard let self else {
return nil
}
if let componentView = self.headerContentView.view as? ChatListHeaderComponent.View {
if let transitionView = componentView.storyPeerListView()?.transitionViewForItem(peerId: self.context.account.peerId) {
return StoryCameraTransitionOut(
destinationView: transitionView,
destinationRect: transitionView.bounds,
destinationCornerRadius: transitionView.bounds.height * 0.5
)
}
}
return nil
})
}
}*/
}
let storyContainerScreen = StoryContainerScreen(
context: self.context,
content: storyContent,
@ -2543,19 +2593,21 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.push(storyContainerScreen)
})
}
let fraction = 94.0 / (navigationBarSearchContentHeight + 94.0)
var visibleProgress = max(0.0, min(1.0, searchContentNode.expansionProgress))
visibleProgress = (1.0 / fraction) * visibleProgress
visibleProgress = max(0.0, min(1.0, visibleProgress))
componentView.updateStories(offset: visibleProgress, context: self.context, theme: self.presentationData.theme, strings: self.presentationData.strings, storySubscriptions: self.storySubscriptions, transition: Transition(transition))
}
}
}
override public func updateNavigationBarLayout(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
self.updateHeaderContent(layout: layout, transition: transition)
super.updateNavigationBarLayout(layout, transition: transition)
}
override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
if case .chatList(.root) = self.location, !self.isSearchActive {
self.searchContentNode?.additionalHeight = (1.0 - self.chatListDisplayNode.inlineStackContainerTransitionFraction) * self.storyListHeight
}
super.containerLayoutUpdated(layout, transition: transition)
let wasInVoiceOver = self.validLayout?.inVoiceOver ?? false
@ -2564,8 +2616,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.updateLayout(layout: layout, transition: transition)
self.updateHeaderStories(transition: transition)
if let searchContentNode = self.searchContentNode, layout.inVoiceOver != wasInVoiceOver {
searchContentNode.updateListVisibleContentOffset(.known(0.0))
self.chatListDisplayNode.scrollToTop()
@ -2630,7 +2680,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
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.chatListDisplayNode.containerLayoutUpdated(layout, navigationBarHeight: self.cleanNavigationHeight, visualNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: self.cleanNavigationHeight, transition: transition)
self.chatListDisplayNode.containerLayoutUpdated(layout, navigationBarHeight: self.cleanNavigationHeight, visualNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: self.cleanNavigationHeight, storiesInset: self.storyListHeight, transition: transition)
}
override public func navigationStackConfigurationUpdated(next: [ViewController]) {
@ -3050,16 +3100,16 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.chatListDisplayNode.mainContainerNode.updateAvailableFilters(availableFilters, limit: filtersLimit)
if isPremium == nil && items.isEmpty {
strongSelf.ready.set(strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.ready)
strongSelf.mainReady.set(strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.ready)
} else if !strongSelf.initializedFilters {
if selectedEntryId != strongSelf.chatListDisplayNode.mainContainerNode.currentItemFilter {
strongSelf.chatListDisplayNode.mainContainerNode.switchToFilter(id: selectedEntryId, animated: false, completion: { [weak self] in
if let strongSelf = self {
strongSelf.ready.set(strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.ready)
strongSelf.mainReady.set(strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.ready)
}
})
} else {
strongSelf.ready.set(strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.ready)
strongSelf.mainReady.set(strongSelf.chatListDisplayNode.mainContainerNode.currentItemNode.ready)
}
strongSelf.initializedFilters = true
}
@ -3071,9 +3121,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if strongSelf.displayNavigationBar {
strongSelf.navigationBar?.secondaryContentHeight = (!isEmpty ? NavigationBar.defaultSecondaryContentHeight : 0.0)
if case .chatList(.root) = strongSelf.location {
strongSelf.searchContentNode?.additionalHeight = 94.0
}
strongSelf.navigationBar?.setSecondaryContentNode(strongSelf.navigationSecondaryContentNode, animated: false)
}
@ -3437,12 +3484,13 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let displaySearchFilters = true
if !tabsIsEmpty, let snapshotView = strongSelf.tabContainerNode.view.snapshotView(afterScreenUpdates: false) {
snapshotView.frame = strongSelf.tabContainerNode.frame
strongSelf.tabContainerNode.view.superview?.addSubview(snapshotView)
snapshotView.frame = strongSelf.navigationSecondaryContentNode.frame
strongSelf.navigationSecondaryContentNode.view.superview?.addSubview(snapshotView)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -strongSelf.storyListHeight), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
}
if let searchContentNode = strongSelf.searchContentNode {
@ -3460,8 +3508,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
searchContentNode.search(filter: filter, query: query)
}
let tabsOffset = 30.0 + strongSelf.storyListHeight
Queue.mainQueue().justDispatch {
filterContainerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: 30.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
filterContainerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: tabsOffset), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
filterContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
}
}
@ -3508,6 +3558,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if let filterContainerNode = filterContainerNode, let snapshotView = filterContainerNode.view.snapshotView(afterScreenUpdates: false) {
snapshotView.frame = filterContainerNode.frame//.offsetBy(dx: self.navigationSecondaryContentNode.frame.minX, dy: self.navigationSecondaryContentNode.frame.minY)
filterContainerNode.view.superview?.addSubview(snapshotView)
snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: self.storyListHeight), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
@ -3533,7 +3584,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.navigationBar?.secondaryContentHeight = (!tabsIsEmpty ? NavigationBar.defaultSecondaryContentHeight : 0.0)
if case .chatList(.root) = self.location {
self.searchContentNode?.additionalHeight = 94.0
self.searchContentNode?.additionalHeight = self.storyListHeight
}
self.navigationBar?.setSecondaryContentNode(self.navigationSecondaryContentNode, animated: false)

View File

@ -216,7 +216,8 @@ private final class ChatListShimmerNode: ASDisplayNode {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
let readState = EnginePeerReadCounters()
@ -357,7 +358,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
private var canReportPeer: Bool = false
private(set) var validLayout: (size: CGSize, insets: UIEdgeInsets, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat)?
private(set) var validLayout: (size: CGSize, insets: UIEdgeInsets, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat, storiesInset: CGFloat)?
init(context: AccountContext, controller: ChatListControllerImpl?, location: ChatListControllerLocation, filter: ChatListFilter?, chatListMode: ChatListNodeMode, previewing: Bool, isInlineMode: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, becameEmpty: @escaping (ChatListFilter?) -> Void, emptyAction: @escaping (ChatListFilter?) -> Void, secondaryEmptyAction: @escaping () -> Void) {
self.context = context
@ -442,7 +443,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
})
strongSelf.emptyNode = emptyNode
strongSelf.addSubnode(emptyNode)
if let (size, insets, _, _, _, _) = strongSelf.validLayout {
if let (size, insets, _, _, _, _, _) = strongSelf.validLayout {
let emptyNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: size.width, height: size.height - insets.top - insets.bottom))
emptyNode.frame = emptyNodeFrame
emptyNode.updateLayout(size: emptyNodeFrame.size, transition: .immediate)
@ -464,7 +465,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
let emptyShimmerEffectNode = ChatListShimmerNode()
strongSelf.emptyShimmerEffectNode = emptyShimmerEffectNode
strongSelf.insertSubnode(emptyShimmerEffectNode, belowSubnode: strongSelf.listNode)
if let (size, insets, _, _, _, _) = strongSelf.validLayout, let offset = strongSelf.floatingHeaderOffset {
if let (size, insets, _, _, _, _, _) = strongSelf.validLayout, let offset = strongSelf.floatingHeaderOffset {
strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset + strongSelf.shimmerNodeOffset, transition: .immediate)
}
}
@ -484,7 +485,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
return
}
strongSelf.floatingHeaderOffset = offset
if let (size, insets, _, _, _, _) = strongSelf.validLayout, let emptyShimmerEffectNode = strongSelf.emptyShimmerEffectNode {
if let (size, insets, _, _, _, _, _) = strongSelf.validLayout, let emptyShimmerEffectNode = strongSelf.emptyShimmerEffectNode {
strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset + strongSelf.shimmerNodeOffset, transition: transition)
}
strongSelf.layoutAdditionalPanels(transition: transition)
@ -510,8 +511,8 @@ private final class ChatListContainerItemNode: ASDisplayNode {
}
}
if update {
if let (size, insets, visualNavigationHeight, originalNavigationHeight, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout {
self.updateLayout(size: size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .animated(duration: 0.4, curve: .spring))
if let (size, insets, visualNavigationHeight, originalNavigationHeight, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout {
self.updateLayout(size: size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .animated(duration: 0.4, curve: .spring))
}
}
})
@ -531,8 +532,8 @@ private final class ChatListContainerItemNode: ASDisplayNode {
}
if self.canReportPeer != canReportPeer {
self.canReportPeer = canReportPeer
if let (size, insets, visualNavigationHeight, originalNavigationHeight, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout {
self.updateLayout(size: size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .animated(duration: 0.4, curve: .spring))
if let (size, insets, visualNavigationHeight, originalNavigationHeight, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout {
self.updateLayout(size: size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .animated(duration: 0.4, curve: .spring))
}
}
})
@ -551,7 +552,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
}
private func layoutAdditionalPanels(transition: ContainedViewLayoutTransition) {
guard let (size, insets, visualNavigationHeight, _, _, _) = self.validLayout, let offset = self.floatingHeaderOffset else {
guard let (size, insets, visualNavigationHeight, _, _, _, _) = self.validLayout, let offset = self.floatingHeaderOffset else {
return
}
@ -588,8 +589,8 @@ private final class ChatListContainerItemNode: ASDisplayNode {
self.emptyNode?.updateThemeAndStrings(theme: presentationData.theme, strings: presentationData.strings)
}
func updateLayout(size: CGSize, insets: UIEdgeInsets, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (size, insets, visualNavigationHeight, originalNavigationHeight, inlineNavigationLocation, inlineNavigationTransitionFraction)
func updateLayout(size: CGSize, insets: UIEdgeInsets, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat, storiesInset: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (size, insets, visualNavigationHeight, originalNavigationHeight, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset)
var listInsets = insets
var additionalTopInset: CGFloat = 0.0
@ -722,7 +723,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: size, insets: listInsets, duration: duration, curve: curve)
transition.updateFrame(node: self.listNode, frame: CGRect(origin: CGPoint(), size: size))
self.listNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, visibleTopInset: visualNavigationHeight + additionalTopInset, originalTopInset: originalNavigationHeight + additionalTopInset, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction)
self.listNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, visibleTopInset: visualNavigationHeight + additionalTopInset, originalTopInset: originalNavigationHeight + additionalTopInset, storiesInset: storiesInset, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction)
if let emptyNode = self.emptyNode {
let emptyNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: listInsets.top), size: CGSize(width: size.width, height: size.height - listInsets.top - listInsets.bottom))
@ -771,7 +772,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
public private(set) var transitionFraction: CGFloat = 0.0
private var transitionFractionOffset: CGFloat = 0.0
private var disableItemNodeOperationsWhileAnimating: Bool = false
private var validLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, insets: UIEdgeInsets, isReorderingFilters: Bool, isEditing: Bool, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat)?
private var validLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, insets: UIEdgeInsets, isReorderingFilters: Bool, isEditing: Bool, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat, storiesInset: CGFloat)?
private var enableAdjacentFilterLoading: Bool = false
@ -1048,7 +1049,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
self.onFilterSwitch?()
self.transitionFractionOffset = 0.0
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout, let itemNode = self.itemNodes[self.selectedId] {
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout, let itemNode = self.itemNodes[self.selectedId] {
for (id, itemNode) in self.itemNodes {
if id != selectedId {
itemNode.emptyNode?.restartAnimation()
@ -1061,13 +1062,13 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
for (_, itemNode) in self.itemNodes {
itemNode.layer.removeAllAnimations()
}
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, .immediate, true)
}
}
}
case .changed:
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) {
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) {
let translation = recognizer.translation(in: self.view)
var transitionFraction = translation.x / layout.size.width
@ -1108,11 +1109,11 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
}
}
}
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false)
}
case .cancelled, .ended:
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) {
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) {
let translation = recognizer.translation(in: self.view)
let velocity = recognizer.velocity(in: self.view)
var directionIsToRight: Bool?
@ -1151,12 +1152,12 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
self.transitionFraction = 0.0
let transition: ContainedViewLayoutTransition = .animated(duration: 0.45, curve: .spring)
self.disableItemNodeOperationsWhileAnimating = true
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: transition)
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: transition)
self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false)
DispatchQueue.main.async {
self.disableItemNodeOperationsWhileAnimating = false
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout {
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout {
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
}
}
}
@ -1236,8 +1237,8 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
}
strongSelf.availableFilters = availableFilters
strongSelf.filtersLimit = limit
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = strongSelf.validLayout {
strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
if let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = strongSelf.validLayout {
strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
}
}
if !availableFilters.contains(where: { $0.id == self.selectedId }) {
@ -1254,8 +1255,8 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
if value != self.enableAdjacentFilterLoading {
self.enableAdjacentFilterLoading = value
if self.enableAdjacentFilterLoading, let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout {
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
if self.enableAdjacentFilterLoading, let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout {
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
}
}
}
@ -1264,7 +1265,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
self.onFilterSwitch?()
if id != self.selectedId, let index = self.availableFilters.firstIndex(where: { $0.id == id }) {
if let itemNode = self.itemNodes[id] {
guard let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = self.validLayout else {
guard let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = self.validLayout else {
return
}
self.selectedId = id
@ -1273,7 +1274,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
}
self.applyItemNodeAsCurrent(id: id, itemNode: itemNode)
let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring)
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: transition)
self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: transition)
self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false)
itemNode.emptyNode?.restartAnimation()
completion?()
@ -1303,7 +1304,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
strongSelf.pendingItemNode = nil
guard let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction) = strongSelf.validLayout else {
guard let (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset) = strongSelf.validLayout else {
strongSelf.itemNodes[id] = itemNode
strongSelf.addSubnode(itemNode)
@ -1352,7 +1353,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
transition.animatePositionAdditive(node: itemNode, offset: CGPoint(x: -offset, y: 0.0))
itemNode.updateLayout(size: layout.size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
itemNode.updateLayout(size: layout.size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
strongSelf.selectedId = id
if let currentItemNode = strongSelf.currentItemNodeValue {
@ -1360,7 +1361,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
}
strongSelf.applyItemNodeAsCurrent(id: id, itemNode: itemNode)
strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, transition: .immediate)
strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: inlineNavigationTransitionFraction, storiesInset: storiesInset, transition: .immediate)
strongSelf.currentItemFilterUpdated?(strongSelf.currentItemFilter, strongSelf.transitionFraction, transition, false)
}
@ -1371,8 +1372,8 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
}
}
public func update(layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, insets: UIEdgeInsets, isReorderingFilters: Bool, isEditing: Bool, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction)
public func update(layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, originalNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, insets: UIEdgeInsets, isReorderingFilters: Bool, isEditing: Bool, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat, storiesInset: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (layout, navigationBarHeight, visualNavigationHeight, originalNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing, inlineNavigationLocation, inlineNavigationTransitionFraction, storiesInset)
self._validLayoutReady.set(.single(true))
@ -1440,7 +1441,7 @@ public final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDele
}
}
itemNode.updateLayout(size: layout.size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: itemInlineNavigationTransitionFraction, transition: nodeTransition)
itemNode.updateLayout(size: layout.size, insets: insets, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: originalNavigationHeight, inlineNavigationLocation: inlineNavigationLocation, inlineNavigationTransitionFraction: itemInlineNavigationTransitionFraction, storiesInset: storiesInset, transition: nodeTransition)
if wasAdded, case .animated = transition {
animateSlidingIds.append(id)
@ -1501,7 +1502,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
var didBeginSelectingChatsWhileEditing: Bool = false
var isEditing: Bool = false
private var containerLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat)?
private var containerLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, storiesInset: CGFloat)?
var contentOffsetChanged: ((ListViewVisibleContentOffset) -> Void)?
var contentScrollingEnded: ((ListView) -> Bool)?
@ -1694,8 +1695,8 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
}
}
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) {
self.containerLayout = (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight)
func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, storiesInset: CGFloat, transition: ContainedViewLayoutTransition) {
self.containerLayout = (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, storiesInset)
var insets = layout.insets(options: [.input])
insets.top += navigationBarHeight
@ -1764,7 +1765,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
cleanMainNavigationBarHeight = visualNavigationHeight
mainInsets.top = visualNavigationHeight
}
self.mainContainerNode.update(layout: layout, navigationBarHeight: mainNavigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: cleanMainNavigationBarHeight, insets: mainInsets, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, inlineNavigationLocation: self.inlineStackContainerNode?.location, inlineNavigationTransitionFraction: self.inlineStackContainerTransitionFraction, transition: transition)
self.mainContainerNode.update(layout: layout, navigationBarHeight: mainNavigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: cleanMainNavigationBarHeight, insets: mainInsets, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, inlineNavigationLocation: self.inlineStackContainerNode?.location, inlineNavigationTransitionFraction: self.inlineStackContainerTransitionFraction, storiesInset: storiesInset, transition: transition)
if let inlineStackContainerNode = self.inlineStackContainerNode {
var inlineStackContainerNodeTransition = transition
@ -1788,7 +1789,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
var inlineInsets = insets
inlineInsets.left = 0.0
inlineStackContainerNode.update(layout: inlineLayout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: inlineInsets, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0, transition: inlineStackContainerNodeTransition)
inlineStackContainerNode.update(layout: inlineLayout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, originalNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: inlineInsets, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0, storiesInset: storiesInset, transition: inlineStackContainerNodeTransition)
if animateIn {
transition.animatePosition(node: inlineStackContainerNode, from: CGPoint(x: inlineStackContainerNode.position.x + inlineStackContainerNode.bounds.width + UIScreenPixel, y: inlineStackContainerNode.position.y))
@ -1803,7 +1804,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
}
func activateSearch(placeholderNode: SearchBarPlaceholderNode, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter, navigationController: NavigationController?) -> (ASDisplayNode, (Bool) -> Void)? {
guard let (containerLayout, _, _, cleanNavigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else {
guard let (containerLayout, _, _, cleanNavigationBarHeight, _) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else {
return nil
}
@ -1866,7 +1867,7 @@ final class ChatListControllerNode: ASDisplayNode, UIGestureRecognizerDelegate {
self.inlineStackContainerNode?.accessibilityElementsHidden = false
return { [weak self] in
if let strongSelf = self, let (layout, _, _, cleanNavigationBarHeight) = strongSelf.containerLayout {
if let strongSelf = self, let (layout, _, _, cleanNavigationBarHeight, _) = strongSelf.containerLayout {
searchDisplayController.containerLayoutUpdated(layout, navigationBarHeight: cleanNavigationBarHeight, transition: .animated(duration: 0.4, curve: .spring))
}
}

View File

@ -1326,7 +1326,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
}
}

View File

@ -3436,7 +3436,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
let readState = EnginePeerReadCounters()
return ChatListItem(presentationData: chatListPresentationData, context: context, chatListLocation: .chatList(groupId: .root), filterData: nil, index: .chatList(EngineChatList.Item.Index.ChatList(pinningIndex: 0, messageIndex: EngineMessage.Index(id: EngineMessage.Id(peerId: peer1.id, namespace: 0, id: 0), timestamp: timestamp1))), content: .peer(ChatListItemContent.PeerData(
@ -3486,7 +3487,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: true, isGlobalSearchResult: true)
@ -3515,7 +3517,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true)
@ -3544,7 +3547,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true)
@ -3573,7 +3577,8 @@ private final class ChatListSearchShimmerNode: ASDisplayNode {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
return ListMessageItem(presentationData: ChatPresentationData(presentationData: presentationData), context: context, chatLocation: .peer(id: peer1.id), interaction: ListMessageItemInteraction.default, message: message._asMessage(), selection: hasSelection ? .selectable(selected: false) : .none, displayHeader: false, customHeader: nil, hintIsLink: false, isGlobalSearchResult: true)

View File

@ -2745,6 +2745,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
avatarScaleOffset = targetAvatarScaleOffset * inlineNavigationLocation.progress
}
let storyIndicatorScale = avatarScale
if displayStoryIndicator {
avatarScale *= (avatarFrame.width - 4.0 * 2.0) / avatarFrame.width
}
@ -2795,7 +2796,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
})
}
transition.updateFrame(node: avatarStoryIndicatorNode, frame: avatarFrame)
transition.updateFrame(node: avatarStoryIndicatorNode, frame: CGRect(origin: CGPoint(x: avatarFrame.minX, y: avatarFrame.minY + (avatarFrame.height - avatarFrame.height * storyIndicatorScale) * 0.5), size: CGSize(width: avatarFrame.width * storyIndicatorScale, height: avatarFrame.height * storyIndicatorScale)))
} else {
if let avatarStoryIndicatorNode = strongSelf.avatarStoryIndicatorNode {
strongSelf.avatarStoryIndicatorNode = nil

View File

@ -3216,7 +3216,10 @@ public final class ChatListNode: ListView {
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: scrollToItem, updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })*/
}
public func updateLayout(transition: ContainedViewLayoutTransition, updateSizeAndInsets: ListViewUpdateSizeAndInsets, visibleTopInset: CGFloat, originalTopInset: CGFloat, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat) {
private var previousStoriesInset: CGFloat?
public func updateLayout(transition: ContainedViewLayoutTransition, updateSizeAndInsets: ListViewUpdateSizeAndInsets, visibleTopInset: CGFloat, originalTopInset: CGFloat, storiesInset: CGFloat, inlineNavigationLocation: ChatListControllerLocation?, inlineNavigationTransitionFraction: CGFloat) {
//print("inset: \(updateSizeAndInsets.insets.top)")
var highlightedLocation: ChatListHighlightedLocation?
if case let .forum(peerId) = inlineNavigationLocation {
@ -3253,6 +3256,13 @@ public final class ChatListNode: ListView {
var additionalScrollDistance: CGFloat = 0.0
if let previousStoriesInset = self.previousStoriesInset {
additionalScrollDistance += previousStoriesInset - storiesInset
additionalScrollDistance = 0.0
}
self.previousStoriesInset = storiesInset
//print("storiesInset: \(storiesInset), additionalScrollDistance: \(additionalScrollDistance)")
var options: ListViewDeleteAndInsertOptions = [.Synchronous, .LowLatency]
if navigationLocationUpdated {
options.insert(.ForceUpdate)
@ -3263,7 +3273,9 @@ public final class ChatListNode: ListView {
additionalScrollDistance += insetDelta
}
self.ignoreStopScrolling = true
self.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: options, scrollToItem: nil, additionalScrollDistance: additionalScrollDistance, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
self.ignoreStopScrolling = false
if !self.dequeuedInitialTransitionOnLayout {
self.dequeuedInitialTransitionOnLayout = true

View File

@ -312,7 +312,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -392,7 +392,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: logData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(logData.count), attributes: [.FileName(fileName: "Log-iOS-Short.txt")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -478,7 +478,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -562,7 +562,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -647,7 +647,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -700,7 +700,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
let messages = logs.map { (name, path) -> EnqueueMessage in
let id = Int64.random(in: Int64.min ... Int64.max)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)])
return .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
return .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
}
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: messages).start()
}
@ -809,7 +809,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/zip", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-All.txt.zip")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -864,7 +864,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: allStatsData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/zip", size: Int64(allStatsData.count), attributes: [.FileName(fileName: "StorageReport.txt")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}
@ -1558,7 +1558,7 @@ public func triggerDebugSendLogsUI(context: AccountContext, additionalInfo: Stri
context.account.postbox.mediaBox.storeResourceData(fileResource.id, data: gzippedData)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: fileResource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: Int64(gzippedData.count), attributes: [.FileName(fileName: "Log-iOS-Full.txt.zip")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}

View File

@ -196,6 +196,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
private final var lastContentOffsetTimestamp: CFAbsoluteTime = 0.0
private final var ignoreScrollingEvents: Bool = false
public final var globalIgnoreScrollingEvents: Bool = false
public final var ignoreStopScrolling: Bool = false
private let infiniteScrollSize: CGFloat
@ -2930,8 +2931,10 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
}
}
} else if !additionalScrollDistance.isZero {
if !self.ignoreStopScrolling {
self.stopScrolling()
}
}
self.debugCheckMonotonity()

View File

@ -108,13 +108,13 @@ public struct ListViewDeleteAndInsertOptions: OptionSet {
}
public struct ListViewUpdateSizeAndInsets {
public let size: CGSize
public let insets: UIEdgeInsets
public let headerInsets: UIEdgeInsets?
public let scrollIndicatorInsets: UIEdgeInsets?
public let duration: Double
public let curve: ListViewAnimationCurve
public let ensureTopInsetForOverlayHighlightedItems: CGFloat?
public var size: CGSize
public var insets: UIEdgeInsets
public var headerInsets: UIEdgeInsets?
public var scrollIndicatorInsets: UIEdgeInsets?
public var duration: Double
public var curve: ListViewAnimationCurve
public var ensureTopInsetForOverlayHighlightedItems: CGFloat?
public init(size: CGSize, insets: UIEdgeInsets, headerInsets: UIEdgeInsets? = nil, scrollIndicatorInsets: UIEdgeInsets? = nil, duration: Double, curve: ListViewAnimationCurve, ensureTopInsetForOverlayHighlightedItems: CGFloat? = nil) {
self.size = size

View File

@ -1395,7 +1395,11 @@ open class NavigationBar: ASDisplayNode {
if let customHeaderContentView = self.customHeaderContentView {
let headerSize = CGSize(width: size.width, height: nominalHeight)
transition.updateFrame(view: customHeaderContentView, frame: CGRect(origin: CGPoint(x: 0.0, y: contentVerticalOrigin), size: headerSize))
var customHeaderFrame = CGRect(origin: CGPoint(x: 0.0, y: contentVerticalOrigin), size: headerSize)
if appearsHidden {
customHeaderFrame.origin.y = -customHeaderFrame.height
}
transition.updateFrame(view: customHeaderContentView, frame: customHeaderFrame)
}
if self.titleNode.supernode != nil {
@ -1446,7 +1450,7 @@ open class NavigationBar: ASDisplayNode {
if let titleView = titleView as? NavigationBarTitleView {
let titleWidth = size.width - (leftTitleInset > 0.0 ? leftTitleInset : rightTitleInset) - (rightTitleInset > 0.0 ? rightTitleInset : leftTitleInset)
titleView.updateLayout(size: titleFrame.size, clearBounds: CGRect(origin: CGPoint(x: leftTitleInset - titleFrame.minX, y: 0.0), size: CGSize(width: titleWidth, height: titleFrame.height)), transition: titleViewTransition)
let _ = titleView.updateLayout(size: titleFrame.size, clearBounds: CGRect(origin: CGPoint(x: leftTitleInset - titleFrame.minX, y: 0.0), size: CGSize(width: titleWidth, height: titleFrame.height)), sideContentWidth: 0.0, transition: titleViewTransition)
}
if let transitionState = self.transitionState, let otherNavigationBar = transitionState.navigationBar {

View File

@ -4,5 +4,5 @@ import UIKit
public protocol NavigationBarTitleView {
func animateLayoutTransition()
func updateLayout(size: CGSize, clearBounds: CGRect, transition: ContainedViewLayoutTransition)
func updateLayout(size: CGSize, clearBounds: CGRect, sideContentWidth: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat
}

View File

@ -41,7 +41,7 @@ final class GalleryTitleView: UIView, NavigationBarTitleView {
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: .white)
}
func updateLayout(size: CGSize, clearBounds: CGRect, transition: ContainedViewLayoutTransition) {
func updateLayout(size: CGSize, clearBounds: CGRect, sideContentWidth: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
let leftInset: CGFloat = 0.0
let rightInset: CGFloat = 0.0
@ -55,6 +55,8 @@ final class GalleryTitleView: UIView, NavigationBarTitleView {
self.authorNameNode.frame = CGRect(origin: CGPoint(x: floor((size.width - authorNameSize.width) / 2.0), y: floor((size.height - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0)), size: authorNameSize)
self.dateNode.frame = CGRect(origin: CGPoint(x: floor((size.width - dateSize.width) / 2.0), y: floor((size.height - dateSize.height - authorNameSize.height - labelsSpacing) / 2.0) + authorNameSize.height + labelsSpacing), size: dateSize)
}
return 0.0
}
func animateLayoutTransition() {

View File

@ -340,7 +340,7 @@ public final class SecretMediaPreviewController: ViewController {
|> deliverOnMainQueue).start(next: { [weak self] _ in
if let strongSelf = self, strongSelf.traceVisibility() {
if strongSelf.messageId.peerId.namespace == Namespaces.Peer.CloudUser {
let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
let _ = enqueueMessages(account: strongSelf.context.account, peerId: strongSelf.messageId.peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
} else if strongSelf.messageId.peerId.namespace == Namespaces.Peer.SecretChat {
let _ = strongSelf.context.engine.messages.addSecretChatMessageScreenshot(peerId: strongSelf.messageId.peerId).start()
}

View File

@ -1413,7 +1413,7 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
}, showAll: false)
let peer = TelegramUser(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(0)), accessHash: nil, firstName: "", lastName: nil, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let controller = LocationViewController(context: self.context, subject: EngineMessage(message), params: controllerParams)
self.pushController(controller)

View File

@ -636,7 +636,7 @@ private final class ItemListTextWithSubtitleTitleView: UIView, NavigationBarTitl
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.medium(17.0), textColor: theme.rootController.navigationBar.primaryTextColor)
self.subtitleNode.attributedText = NSAttributedString(string: self.subtitleNode.attributedText?.string ?? "", font: Font.regular(13.0), textColor: theme.rootController.navigationBar.secondaryTextColor)
if let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .immediate)
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: 0.0, transition: .immediate)
}
}
@ -644,11 +644,11 @@ private final class ItemListTextWithSubtitleTitleView: UIView, NavigationBarTitl
super.layoutSubviews()
if let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .immediate)
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: 0.0, transition: .immediate)
}
}
func updateLayout(size: CGSize, clearBounds: CGRect, transition: ContainedViewLayoutTransition) {
func updateLayout(size: CGSize, clearBounds: CGRect, sideContentWidth: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
self.validLayout = (size, clearBounds)
let titleSize = self.titleNode.updateLayout(size)
@ -660,6 +660,8 @@ private final class ItemListTextWithSubtitleTitleView: UIView, NavigationBarTitl
self.titleNode.frame = titleFrame
self.subtitleNode.frame = subtitleFrame
return titleSize.width
}
func animateLayoutTransition() {

View File

@ -353,7 +353,7 @@ public func legacyEnqueueGifMessage(account: Account, data: Data, correlationId:
fileAttributes.append(.Animated)
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
subscriber.putCompletion()
} else {
subscriber.putError(Void())
@ -395,7 +395,7 @@ public func legacyEnqueueVideoMessage(account: Account, data: Data, correlationI
fileAttributes.append(.Animated)
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: fileAttributes)
subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
subscriber.putNext(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
subscriber.putCompletion()
} else {
subscriber.putError(Void())
@ -491,7 +491,7 @@ public func legacyAssetPickerEnqueueMessages(context: AccountContext, account: A
}
}
}
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: false))
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: false))
}
}
case let .asset(asset):
@ -538,7 +538,7 @@ public func legacyAssetPickerEnqueueMessages(context: AccountContext, account: A
}
}
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: false))
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: false))
case .tempFile:
break
}
@ -589,7 +589,7 @@ public func legacyAssetPickerEnqueueMessages(context: AccountContext, account: A
}
}
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: true))
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: true))
case let .asset(asset):
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
@ -624,7 +624,7 @@ public func legacyAssetPickerEnqueueMessages(context: AccountContext, account: A
}
}
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: true))
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: true))
default:
break
}
@ -783,7 +783,7 @@ public func legacyAssetPickerEnqueueMessages(context: AccountContext, account: A
}
}
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: asFile))
messages.append(LegacyAssetPickerEnqueueMessage(message: .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: item.groupedId, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets), uniqueId: item.uniqueId, isFile: asFile))
}
}
}

View File

@ -859,10 +859,10 @@ final class MediaPickerSelectedListNode: ASDisplayNode, UIScrollViewDelegate, UI
let previewText = groupLayouts.count > 1 ? presentationData.strings.Attachment_MessagesPreview : presentationData.strings.Attachment_MessagePreview
let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let previewMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: previewText, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let previewItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [previewMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, isCentered: true)
let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let dragMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: presentationData.strings.Attachment_DragToReorder, entities: []))], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let dragItem = self.context.sharedContext.makeChatMessagePreviewItem(context: context, messages: [dragMessage], theme: theme, strings: presentationData.strings, wallpaper: wallpaper, fontSize: presentationData.chatFontSize, chatBubbleCorners: bubbleCorners, dateTimeFormat: presentationData.dateTimeFormat, nameOrder: presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.wallpaperBackgroundNode, availableReactions: nil, isCentered: true)
let headerItems: [ListViewItem] = [previewItem, dragItem]

View File

@ -533,7 +533,7 @@ final class MutableChatListView {
renderedPeers.append(ChatListGroupReferencePeer(peer: renderedPeer, isUnread: isUnread))
if foundIndices.count == 1 && message == nil {
message = postbox.messageHistoryTable.getMessage(messageIndex).flatMap({ postbox.messageHistoryTable.renderMessage($0, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable) })
message = postbox.messageHistoryTable.getMessage(messageIndex).flatMap({ postbox.messageHistoryTable.renderMessage($0, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable, storyTable: postbox.storyTable) })
}
}
}

View File

@ -105,7 +105,7 @@ private func updateMessagePeers(_ message: Message, updatedPeers: [PeerId: Peer]
peers[peerId] = currentPeer
}
}
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo)
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
}
return nil
}

View File

@ -167,7 +167,7 @@ final class MutableGlobalMessageTagsView: MutablePostboxView {
hasChanges = true
}
case let .message(message):
if self.add(.message(Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo))) {
if self.add(.message(Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: updatedTimestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories))) {
hasChanges = true
}
}

View File

@ -578,11 +578,41 @@ public struct MessageForwardInfo: Equatable {
}
}
public struct StoryId: Codable, Hashable {
private enum CodingKeys: String, CodingKey {
case peerId = "p"
case id = "i"
}
public var peerId: PeerId
public let id: Int32
public init(peerId: PeerId, id: Int32) {
self.peerId = peerId
self.id = id
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.peerId = PeerId(try container.decode(Int64.self, forKey: .peerId))
self.id = try container.decode(Int32.self, forKey: .id)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.peerId.toInt64(), forKey: .peerId)
try container.encode(self.id, forKey: .id)
}
}
public protocol MessageAttribute: AnyObject, PostboxCoding {
var associatedPeerIds: [PeerId] { get }
var associatedMessageIds: [MessageId] { get }
var associatedMediaIds: [MediaId] { get }
var automaticTimestampBasedAttribute: (UInt16, Int32)? { get }
var associatedStoryIds: [StoryId] { get }
}
public extension MessageAttribute {
@ -601,6 +631,10 @@ public extension MessageAttribute {
var automaticTimestampBasedAttribute: (UInt16, Int32)? {
return nil
}
var associatedStoryIds: [StoryId] {
return []
}
}
public struct MessageGroupInfo: Equatable {
@ -659,12 +693,13 @@ public final class Message {
public let associatedMessageIds: [MessageId]
public let associatedMedia: [MediaId: Media]
public let associatedThreadInfo: AssociatedThreadInfo?
public let associatedStories: [StoryId: CodableEntry]
public var index: MessageIndex {
return MessageIndex(id: self.id, timestamp: self.timestamp)
}
public init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: MessageForwardInfo?, author: Peer?, text: String, attributes: [MessageAttribute], media: [Media], peers: SimpleDictionary<PeerId, Peer>, associatedMessages: SimpleDictionary<MessageId, Message>, associatedMessageIds: [MessageId], associatedMedia: [MediaId: Media], associatedThreadInfo: AssociatedThreadInfo?) {
public init(stableId: UInt32, stableVersion: UInt32, id: MessageId, globallyUniqueId: Int64?, groupingKey: Int64?, groupInfo: MessageGroupInfo?, threadId: Int64?, timestamp: Int32, flags: MessageFlags, tags: MessageTags, globalTags: GlobalMessageTags, localTags: LocalMessageTags, forwardInfo: MessageForwardInfo?, author: Peer?, text: String, attributes: [MessageAttribute], media: [Media], peers: SimpleDictionary<PeerId, Peer>, associatedMessages: SimpleDictionary<MessageId, Message>, associatedMessageIds: [MessageId], associatedMedia: [MediaId: Media], associatedThreadInfo: AssociatedThreadInfo?, associatedStories: [StoryId: CodableEntry]) {
self.stableId = stableId
self.stableVersion = stableVersion
self.id = id
@ -687,50 +722,51 @@ public final class Message {
self.associatedMessageIds = associatedMessageIds
self.associatedMedia = associatedMedia
self.associatedThreadInfo = associatedThreadInfo
self.associatedStories = associatedStories
}
public func withUpdatedStableVersion(stableVersion: UInt32) -> Message {
return Message(stableId: self.stableId, stableVersion: stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedText(_ text: String) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedTimestamp(_ timestamp: Int32) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedMedia(_ media: [Media]) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedPeers(_ peers: SimpleDictionary<PeerId, Peer>) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedFlags(_ flags: MessageFlags) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
func withUpdatedGroupInfo(_ groupInfo: MessageGroupInfo?) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedAttributes(_ attributes: [MessageAttribute]) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
func withUpdatedAssociatedMessages(_ associatedMessages: SimpleDictionary<MessageId, Message>) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedForwardInfo(_ forwardInfo: MessageForwardInfo?) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
public func withUpdatedAuthor(_ author: Peer?) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo, associatedStories: self.associatedStories)
}
}

View File

@ -2507,7 +2507,7 @@ final class MessageHistoryTable: Table {
return parsedMedia
}
func renderMessage(_ message: IntermediateMessage, peerTable: PeerTable, threadIndexTable: MessageHistoryThreadIndexTable, addAssociatedMessages: Bool = true) -> Message {
func renderMessage(_ message: IntermediateMessage, peerTable: PeerTable, threadIndexTable: MessageHistoryThreadIndexTable, storyTable: StoryTable, addAssociatedMessages: Bool = true) -> Message {
var parsedAttributes: [MessageAttribute] = []
var parsedMedia: [Media] = []
@ -2585,6 +2585,8 @@ final class MessageHistoryTable: Table {
var associatedMessageIds: [MessageId] = []
var associatedMessages = SimpleDictionary<MessageId, Message>()
var associatedMedia: [MediaId: Media] = [:]
var associatedStories: [StoryId: CodableEntry] = [:]
for attribute in parsedAttributes {
for peerId in attribute.associatedPeerIds {
if let peer = peerTable.get(peerId) {
@ -2598,12 +2600,19 @@ final class MessageHistoryTable: Table {
}
}
}
for storyId in attribute.associatedStoryIds {
if associatedStories[storyId] == nil {
if let story = storyTable.get(id: storyId) {
associatedStories[storyId] = story
}
}
}
associatedMessageIds.append(contentsOf: attribute.associatedMessageIds)
if addAssociatedMessages {
for messageId in attribute.associatedMessageIds {
if let index = self.messageHistoryIndexTable.getIndex(messageId) {
if let message = self.getMessage(index) {
associatedMessages[messageId] = self.renderMessage(message, peerTable: peerTable, threadIndexTable: threadIndexTable, addAssociatedMessages: false)
associatedMessages[messageId] = self.renderMessage(message, peerTable: peerTable, threadIndexTable: threadIndexTable, storyTable: storyTable, addAssociatedMessages: false)
}
}
}
@ -2615,7 +2624,7 @@ final class MessageHistoryTable: Table {
associatedThreadInfo = self.seedConfiguration.decodeMessageThreadInfo(data.data)
}
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: parsedAttributes, media: parsedMedia, peers: peers, associatedMessages: associatedMessages, associatedMessageIds: associatedMessageIds, associatedMedia: associatedMedia, associatedThreadInfo: associatedThreadInfo)
return Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: parsedAttributes, media: parsedMedia, peers: peers, associatedMessages: associatedMessages, associatedMessageIds: associatedMessageIds, associatedMedia: associatedMedia, associatedThreadInfo: associatedThreadInfo, associatedStories: associatedStories)
}
func renderMessagePeers(_ message: Message, peerTable: PeerTable) -> Message {
@ -2658,12 +2667,12 @@ final class MessageHistoryTable: Table {
return message.withUpdatedPeers(peers)
}
func renderAssociatedMessages(associatedMessageIds: [MessageId], peerTable: PeerTable, threadIndexTable: MessageHistoryThreadIndexTable) -> SimpleDictionary<MessageId, Message> {
func renderAssociatedMessages(associatedMessageIds: [MessageId], peerTable: PeerTable, storyTable: StoryTable, threadIndexTable: MessageHistoryThreadIndexTable) -> SimpleDictionary<MessageId, Message> {
var associatedMessages = SimpleDictionary<MessageId, Message>()
for messageId in associatedMessageIds {
if let index = self.messageHistoryIndexTable.getIndex(messageId) {
if let message = self.getMessage(index) {
associatedMessages[messageId] = self.renderMessage(message, peerTable: peerTable, threadIndexTable: threadIndexTable, addAssociatedMessages: false)
associatedMessages[messageId] = self.renderMessage(message, peerTable: peerTable, threadIndexTable: threadIndexTable, storyTable: storyTable, addAssociatedMessages: false)
}
}
}

View File

@ -137,7 +137,7 @@ enum MutableMessageHistoryEntry {
return .IntermediateMessageEntry(updatedMessage, location, monthLocation)
case let .MessageEntry(value, reloadAssociatedMessages, reloadPeers):
let message = value.message
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo)
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: message.media, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers)
}
}
@ -902,7 +902,7 @@ final class MutableMessageHistoryView {
private func render(postbox: PostboxImpl) {
for namespace in self.topTaggedMessages.keys {
if let entry = self.topTaggedMessages[namespace]!, case let .intermediate(message) = entry {
let item: MessageHistoryTopTaggedMessage? = .message(postbox.messageHistoryTable.renderMessage(message, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable))
let item: MessageHistoryTopTaggedMessage? = .message(postbox.messageHistoryTable.renderMessage(message, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable, storyTable: postbox.storyTable))
self.topTaggedMessages[namespace] = item
}
}

View File

@ -1442,7 +1442,7 @@ final class HistoryViewLoadedState {
messageMedia.append(media)
}
}
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo)
let updatedMessage = Message(stableId: message.stableId, stableVersion: message.stableVersion, id: message.id, globallyUniqueId: message.globallyUniqueId, groupingKey: message.groupingKey, groupInfo: message.groupInfo, threadId: message.threadId, timestamp: message.timestamp, flags: message.flags, tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: message.forwardInfo, author: message.author, text: message.text, attributes: message.attributes, media: messageMedia, peers: message.peers, associatedMessages: message.associatedMessages, associatedMessageIds: message.associatedMessageIds, associatedMedia: message.associatedMedia, associatedThreadInfo: message.associatedThreadInfo, associatedStories: message.associatedStories)
return .MessageEntry(MessageHistoryMessageEntry(message: updatedMessage, location: value.location, monthLocation: value.monthLocation, attributes: value.attributes), reloadAssociatedMessages: reloadAssociatedMessages, reloadPeers: reloadPeers)
}
case .IntermediateMessageEntry:
@ -1643,7 +1643,7 @@ final class HistoryViewLoadedState {
case let .MessageEntry(value, reloadAssociatedMessages, reloadPeers):
var updatedMessage = value.message
if reloadAssociatedMessages {
let associatedMessages = postbox.messageHistoryTable.renderAssociatedMessages(associatedMessageIds: value.message.associatedMessageIds, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable)
let associatedMessages = postbox.messageHistoryTable.renderAssociatedMessages(associatedMessageIds: value.message.associatedMessageIds, peerTable: postbox.peerTable, storyTable: postbox.storyTable, threadIndexTable: postbox.messageHistoryThreadIndexTable)
updatedMessage = value.message.withUpdatedAssociatedMessages(associatedMessages)
}
if reloadPeers {
@ -1662,7 +1662,7 @@ final class HistoryViewLoadedState {
result.append(value)
}
case let .IntermediateMessageEntry(message, location, monthLocation):
let renderedMessage = postbox.messageHistoryTable.renderMessage(message, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable)
let renderedMessage = postbox.messageHistoryTable.renderMessage(message, peerTable: postbox.peerTable, threadIndexTable: postbox.messageHistoryThreadIndexTable, storyTable: postbox.storyTable)
var authorIsContact = false
if let author = renderedMessage.author {
authorIsContact = postbox.contactsTable.isContact(peerId: author.id)

View File

@ -1304,6 +1304,15 @@ public final class Transaction {
public func getStoryItems(peerId: PeerId) -> [StoryItemsTableEntry] {
return self.postbox!.getStoryItems(peerId: peerId)
}
public func setStory(id: StoryId, value: CodableEntry) {
assert(!self.disposed)
self.postbox!.setStory(id: id, value: value)
}
public func getStory(id: StoryId) -> CodableEntry? {
return self.postbox!.getStory(id: id)
}
}
public enum PostboxResult {
@ -1544,6 +1553,7 @@ final class PostboxImpl {
private var currentStoryStatesEvents: [StoryStatesTable.Event] = []
private var currentStorySubscriptionsEvents: [StorySubscriptionsTable.Event] = []
private var currentStoryItemsEvents: [StoryItemsTable.Event] = []
private var currentStoryEvents: [StoryTable.Event] = []
var hiddenChatIds: Set<PeerId> {
if self.currentHiddenChatIds.isEmpty {
@ -1666,6 +1676,7 @@ final class PostboxImpl {
let storyStatesTable: StoryStatesTable
let storySubscriptionsTable: StorySubscriptionsTable
let storyItemsTable: StoryItemsTable
let storyTable: StoryTable
//temporary
let peerRatingTable: RatingTable<PeerId>
@ -1758,6 +1769,7 @@ final class PostboxImpl {
self.storyStatesTable = StoryStatesTable(valueBox: self.valueBox, table: StoryStatesTable.tableSpec(65), useCaches: useCaches)
self.storySubscriptionsTable = StorySubscriptionsTable(valueBox: self.valueBox, table: StorySubscriptionsTable.tableSpec(66), useCaches: useCaches)
self.storyItemsTable = StoryItemsTable(valueBox: self.valueBox, table: StoryItemsTable.tableSpec(69), useCaches: useCaches)
self.storyTable = StoryTable(valueBox: self.valueBox, table: StoryTable.tableSpec(70), useCaches: useCaches)
var tables: [Table] = []
tables.append(self.metadataTable)
@ -1828,6 +1840,7 @@ final class PostboxImpl {
tables.append(self.storyStatesTable)
tables.append(self.storySubscriptionsTable)
tables.append(self.storyItemsTable)
tables.append(self.storyTable)
self.tables = tables
@ -2204,14 +2217,25 @@ final class PostboxImpl {
fileprivate func setStoryItems(peerId: PeerId, items: [StoryItemsTableEntry]) {
self.storyItemsTable.replace(peerId: peerId, entries: items, events: &self.currentStoryItemsEvents)
for item in items {
self.storyTable.set(id: StoryId(peerId: peerId, id: item.id), value: item.value, events: &self.currentStoryEvents)
}
}
fileprivate func getStoryItems(peerId: PeerId) -> [StoryItemsTableEntry] {
return self.storyItemsTable.get(peerId: peerId)
}
fileprivate func getStory(id: StoryId) -> CodableEntry? {
return self.storyTable.get(id: id)
}
fileprivate func setStory(id: StoryId, value: CodableEntry) {
self.storyTable.set(id: id, value: value, events: &self.currentStoryEvents)
}
func renderIntermediateMessage(_ message: IntermediateMessage) -> Message {
let renderedMessage = self.messageHistoryTable.renderMessage(message, peerTable: self.peerTable, threadIndexTable: self.messageHistoryThreadIndexTable)
let renderedMessage = self.messageHistoryTable.renderMessage(message, peerTable: self.peerTable, threadIndexTable: self.messageHistoryThreadIndexTable, storyTable: self.storyTable)
return renderedMessage
}
@ -2276,7 +2300,7 @@ final class PostboxImpl {
let updatedPeerTimeoutAttributes = self.peerTimeoutPropertiesTable.hasUpdates
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys), updatedPinnedThreads: self.currentUpdatedPinnedThreads, updatedHiddenPeerIds: self.currentUpdatedHiddenPeerIds, storyStatesEvents: self.currentStoryStatesEvents, storySubscriptionsEvents: self.currentStorySubscriptionsEvents, storyItemsEvents: self.currentStoryItemsEvents)
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys), updatedPinnedThreads: self.currentUpdatedPinnedThreads, updatedHiddenPeerIds: self.currentUpdatedHiddenPeerIds, storyStatesEvents: self.currentStoryStatesEvents, storySubscriptionsEvents: self.currentStorySubscriptionsEvents, storyItemsEvents: self.currentStoryItemsEvents, storyEvents: self.currentStoryEvents)
var updatedTransactionState: Int64?
var updatedMasterClientId: Int64?
if !transaction.isEmpty {
@ -2335,6 +2359,7 @@ final class PostboxImpl {
self.currentStoryStatesEvents.removeAll()
self.currentStorySubscriptionsEvents.removeAll()
self.currentStoryItemsEvents.removeAll()
self.currentStoryEvents.removeAll()
for table in self.tables {
table.beforeCommit()
@ -2754,7 +2779,7 @@ final class PostboxImpl {
var result: [Message] = []
for messageId in self.textIndexTable.search(peerId: peerId, text: query, tags: tags) {
if let index = self.messageHistoryIndexTable.getIndex(messageId), let message = self.messageHistoryTable.getMessage(index) {
result.append(self.messageHistoryTable.renderMessage(message, peerTable: self.peerTable, threadIndexTable: self.messageHistoryThreadIndexTable))
result.append(self.messageHistoryTable.renderMessage(message, peerTable: self.peerTable, threadIndexTable: self.messageHistoryThreadIndexTable, storyTable: self.storyTable))
} else {
assertionFailure()
}

View File

@ -52,6 +52,7 @@ final class PostboxTransaction {
let storyStatesEvents: [StoryStatesTable.Event]
let storySubscriptionsEvents: [StorySubscriptionsTable.Event]
let storyItemsEvents: [StoryItemsTable.Event]
let storyEvents: [StoryTable.Event]
var isEmpty: Bool {
if currentUpdatedState != nil {
@ -207,10 +208,13 @@ final class PostboxTransaction {
if !self.storyItemsEvents.isEmpty {
return false
}
if !self.storyEvents.isEmpty {
return false
}
return true
}
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: Set<PeerId>, currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState], currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [AdditionalChatListItem]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>, updatedGlobalNotificationSettings: Bool, updatedPeerTimeoutAttributes: Bool, updatedMessageThreadPeerIds: Set<PeerId>, updatedPeerThreadCombinedStates: Set<PeerId>, updatedPeerThreadsSummaries: Set<PeerId>, updatedPinnedThreads: Set<PeerId>, updatedHiddenPeerIds: Bool, storyStatesEvents: [StoryStatesTable.Event], storySubscriptionsEvents: [StorySubscriptionsTable.Event], storyItemsEvents: [StoryItemsTable.Event]) {
init(currentUpdatedState: PostboxCoding?, currentPeerHoleOperations: [MessageHistoryIndexHoleOperationKey: [MessageHistoryIndexHoleOperation]] = [:], currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], chatListOperations: [PeerGroupId: [ChatListOperation]], currentUpdatedChatListInclusions: [PeerId: PeerChatListInclusion], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: (PeerNotificationSettings?, PeerNotificationSettings)], currentUpdatedPeerNotificationBehaviorTimestamps: [PeerId: PeerNotificationSettingsBehaviorTimestamp], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: Set<PeerId>, currentUpdatedTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState], currentUpdatedTotalUnreadSummaries: [PeerGroupId: PeerGroupUnreadCountersCombinedSummary], alteredInitialPeerCombinedReadStates: [PeerId: CombinedPeerReadState], currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentUpdatedGroupSummarySynchronizeOperations: [PeerGroupAndNamespace: Bool], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, replacedAdditionalChatListItems: [AdditionalChatListItem]?, updatedNoticeEntryKeys: Set<NoticeEntryKey>, updatedCacheEntryKeys: Set<ItemCacheEntryId>, currentUpdatedMasterClientId: Int64?, updatedFailedMessagePeerIds: Set<PeerId>, updatedFailedMessageIds: Set<MessageId>, updatedGlobalNotificationSettings: Bool, updatedPeerTimeoutAttributes: Bool, updatedMessageThreadPeerIds: Set<PeerId>, updatedPeerThreadCombinedStates: Set<PeerId>, updatedPeerThreadsSummaries: Set<PeerId>, updatedPinnedThreads: Set<PeerId>, updatedHiddenPeerIds: Bool, storyStatesEvents: [StoryStatesTable.Event], storySubscriptionsEvents: [StorySubscriptionsTable.Event], storyItemsEvents: [StoryItemsTable.Event], storyEvents: [StoryTable.Event]) {
self.currentUpdatedState = currentUpdatedState
self.currentPeerHoleOperations = currentPeerHoleOperations
self.currentOperationsByPeerId = currentOperationsByPeerId
@ -261,5 +265,6 @@ final class PostboxTransaction {
self.storyStatesEvents = storyStatesEvents
self.storySubscriptionsEvents = storySubscriptionsEvents
self.storyItemsEvents = storyItemsEvents
self.storyEvents = storyEvents
}
}

View File

@ -0,0 +1,40 @@
import Foundation
final class StoryTable: Table {
enum Event {
case updated(id: StoryId)
}
static func tableSpec(_ id: Int32) -> ValueBoxTable {
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false)
}
private let sharedKey = ValueBoxKey(length: 8 + 4)
private func key(_ key: StoryId) -> ValueBoxKey {
self.sharedKey.setInt64(0, value: key.peerId.toInt64())
self.sharedKey.setInt32(8, value: key.id)
return self.sharedKey
}
public func get(id: StoryId) -> CodableEntry? {
if let value = self.valueBox.get(self.table, key: self.key(id)) {
return CodableEntry(data: value.makeData())
} else {
return nil
}
}
public func set(id: StoryId, value: CodableEntry, events: inout [Event]) {
if self.get(id: id) != value {
self.valueBox.set(self.table, key: self.key(id), value: MemoryBuffer(data: value.data))
events.append(.updated(id: id))
}
}
override func clearMemoryCache() {
}
override func beforeCommit() {
}
}

View File

@ -107,9 +107,14 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
let fieldHeight: CGFloat = 36.0
let fraction = fieldHeight / self.nominalHeight
let fullFraction = navigationBarSearchContentHeight / self.nominalHeight
let visibleProgress = max(0.0, min(1.0, self.expansionProgress) - 1.0 + fraction) / fraction
let overscrollProgress = max(0.0, max(0.0, self.expansionProgress - 1.0 + fraction) / fraction - visibleProgress)
let fromLow: CGFloat = fullFraction - fraction
let toLow: CGFloat = 0.0
let fromHigh: CGFloat = fullFraction
let toHigh: CGFloat = 1.0
var visibleProgress: CGFloat = toLow + (self.expansionProgress - fromLow) * (toHigh - toLow) / (fromHigh - fromLow)
visibleProgress = max(0.0, min(1.0, visibleProgress))
let searchBarNodeLayout = self.placeholderNode.asyncLayout()
@ -127,7 +132,6 @@ public class NavigationBarSearchContentNode: NavigationBarContentNode {
let (searchBarHeight, searchBarApply) = searchBarNodeLayout(placeholderString, compactPlaceholderString, CGSize(width: baseWidth, height: fieldHeight), visibleProgress, textColor, fillColor, backgroundColor, transition)
searchBarApply()
let _ = overscrollProgress
let searchBarFrame = CGRect(origin: CGPoint(x: padding + leftInset, y: size.height + (1.0 - visibleProgress) * fieldHeight - 8.0 - fieldHeight), size: CGSize(width: baseWidth, height: fieldHeight))
transition.updateFrame(node: self.placeholderNode, frame: searchBarFrame)

View File

@ -167,22 +167,22 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, UIScrollViewDel
peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let width: CGFloat

View File

@ -149,7 +149,7 @@ class ForwardPrivacyChatPreviewItemNode: ListViewItemNode {
let forwardInfo = MessageForwardInfo(author: item.linkEnabled ? peers[peerId] : nil, source: nil, sourceMessageId: nil, date: 0, authorSignature: item.linkEnabled ? nil : item.peerName, psaType: nil, flags: [])
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: forwardInfo, author: nil, text: item.strings.Privacy_Forwards_PreviewMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false)
var node: ListViewItemNode?
if let current = currentNode {

View File

@ -283,7 +283,7 @@ class ReactionChatPreviewItemNode: ListViewItemNode {
attributes.append(ReactionsMessageAttribute(canViewList: false, reactions: [MessageReaction(value: reaction, count: 1, chosenOrder: 0)], recentPeers: []))
}
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, isCentered: true)
let messageItem = item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: chatPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[userPeerId], text: messageText, attributes: attributes, media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])], theme: item.theme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: item.availableReactions, isCentered: true)
var node: ListViewItemNode?
if let current = currentNode {

View File

@ -268,7 +268,8 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
],
peer: EngineRenderedPeer(peer: peer),
@ -428,22 +429,22 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, UIScrollView
peers[otherPeerId] = TelegramUser(id: otherPeerId, accessHash: nil, firstName: self.presentationData.strings.Appearance_ThemePreview_Chat_2_ReplyName, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message3 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: FileMediaResourceStatus(mediaStatus: .playbackStatus(.paused), fetchStatus: .Local), tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message4 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message4], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, isCentered: false))
let width: CGFloat

View File

@ -537,7 +537,7 @@ public func editThemeController(context: AccountContext, mode: EditThemeControll
|> take(1)).start(next: { previewTheme, settings in
let saveThemeTemplateFile: (String, LocalFileMediaResource, @escaping () -> Void) -> Void = { title, resource, completion in
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: resource.fileId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/x-tgtheme-ios", size: nil, attributes: [.FileName(fileName: "\(title).tgios-theme")])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: context.account.peerId, messages: [message]).start()

View File

@ -901,7 +901,8 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
],
peer: EngineRenderedPeer(peer: peer),
@ -1032,20 +1033,20 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
var sampleMessages: [Message] = []
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message1)
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message2)
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message3)
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message4.id] = message4
sampleMessages.append(message4)
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message5.id] = message5
sampleMessages.append(message5)
@ -1053,13 +1054,13 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, UIScrollViewDelegate
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message6)
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message7)
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message8)
items = sampleMessages.reversed().map { message in

View File

@ -414,7 +414,8 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
associatedMessages: [:],
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
],
peer: EngineRenderedPeer(peer: peer),
@ -583,20 +584,20 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
var sampleMessages: [Message] = []
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message1 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_4_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message1)
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message2 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_5_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message2)
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message3 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_6_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message3)
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message4 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_7_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message4.id] = message4
sampleMessages.append(message4)
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
messages[message5.id] = message5
sampleMessages.append(message5)
@ -604,13 +605,13 @@ final class ThemePreviewControllerNode: ASDisplayNode, UIScrollViewDelegate {
let voiceAttributes: [TelegramMediaFileAttribute] = [.Audio(isVoice: true, duration: 23, title: nil, performer: nil, waveform: Data(base64Encoded: waveformBase64)!)]
let voiceMedia = TelegramMediaFile(fileId: MediaId(namespace: 0, id: 0), partialReference: nil, resource: LocalFileMediaResource(fileId: 0), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: 0, attributes: voiceAttributes)
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message6)
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message7)
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
sampleMessages.append(message8)
items = sampleMessages.reversed().map { message in

View File

@ -156,10 +156,10 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
if let (author, text) = messageItem.reply {
peers[peerId] = TelegramUser(id: peerId, accessHash: nil, firstName: author, lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [])
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
}
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: []) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, isCentered: false))
}

View File

@ -1573,17 +1573,17 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
let theme = self.presentationData.theme
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message1 = Message(stableId: 2, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 2), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66001, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[otherPeerId], text: bottomMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false))
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message2 = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: topMessageText, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false))
if let serviceMessageText {
let attributedText = convertMarkdownToAttributes(NSAttributedString(string: serviceMessageText))
let entities = generateChatInputTextEntities(attributedText)
let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message3 = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [TelegramMediaAction(action: .customText(text: attributedText.string, entities: entities))], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message3], theme: theme, strings: self.presentationData.strings, wallpaper: currentWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.nativeNode, availableReactions: nil, isCentered: false))
}

View File

@ -891,9 +891,9 @@ public final class ShareController: ViewController {
var messages: [EnqueueMessage] = []
if !text.isEmpty {
messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
} else {
messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
messages = transformMessages(messages, showNames: showNames, silently: silently)
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
@ -924,9 +924,9 @@ public final class ShareController: ViewController {
var messages: [EnqueueMessage] = []
if !text.isEmpty {
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages = transformMessages(messages, showNames: showNames, silently: silently)
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
}
@ -956,12 +956,12 @@ public final class ShareController: ViewController {
var messages: [EnqueueMessage] = []
if !text.isEmpty {
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
let entities = generateChatInputTextEntities(attributedText)
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages = transformMessages(messages, showNames: showNames, silently: silently)
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
}
@ -990,7 +990,7 @@ public final class ShareController: ViewController {
}
var messages: [EnqueueMessage] = []
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages = transformMessages(messages, showNames: showNames, silently: silently)
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
}
@ -1065,9 +1065,9 @@ public final class ShareController: ViewController {
var messages: [EnqueueMessage] = []
if !text.isEmpty && !sendTextAsCaption {
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: sendTextAsCaption ? text : "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages = transformMessages(messages, showNames: showNames, silently: silently)
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
}
@ -1097,9 +1097,9 @@ public final class ShareController: ViewController {
var messages: [EnqueueMessage] = []
if !text.isEmpty {
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages = transformMessages(messages, showNames: showNames, silently: silently)
shareSignals.append(enqueueMessages(account: strongSelf.currentAccount, peerId: peerId, messages: messages))
}
@ -1131,7 +1131,7 @@ public final class ShareController: ViewController {
return .fail(.generic)
}
messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
for message in messages {
for media in message.media {

View File

@ -459,11 +459,11 @@ public func sentShareItems(account: Account, to peerIds: [PeerId], threadIds: [P
for item in items {
switch item {
case let .text(text):
messages.append(.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
case let .media(media):
switch media {
case let .media(reference):
let message: EnqueueMessage = .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: reference, replyToMessageId: nil, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: reference, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
messages.append(message)
mediaMessages.append(message)

View File

@ -292,7 +292,7 @@ func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int
let name = "\(callId.id)_\(callId.accessHash).log.json"
let path = callLogsPath(account: engine.account) + "/" + name
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: path, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: name)])
let message = EnqueueMessage.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
return rate
|> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [message])
|> mapToSignal({ _ -> Signal<Void, NoError> in
@ -300,7 +300,7 @@ func rateCallAndSendLogs(engine: TelegramEngine, callId: CallId, starsCount: Int
}))
} else if !comment.isEmpty {
return rate
|> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|> then(enqueueMessages(account: engine.account, peerId: peerId, messages: [.message(text: comment, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|> mapToSignal({ _ -> Signal<Void, NoError> in
return .single(Void())
}))

View File

@ -1263,7 +1263,7 @@ public final class VoiceChatControllerImpl: ViewController, VoiceChatController
dismissController?()
if let strongSelf = self {
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: listenerLink, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|> deliverOnMainQueue).start(next: { [weak self] _ in
if let strongSelf = self {
strongSelf.presentUndoOverlay(content: .forward(savedMessages: false, text: strongSelf.presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peer.displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder)).string), action: { _ in return true })

View File

@ -189,6 +189,7 @@ struct AccountMutableState {
var channelStates: [PeerId: AccountStateChannelState]
var peerChatInfos: [PeerId: PeerChatInfo]
var referencedReplyMessageIds: ReferencedReplyMessageIds
var referencedStoryIds = Set<StoryId>()
var referencedGeneralMessageIds: Set<MessageId>
var storedMessages: Set<MessageId>
var readInboxMaxIds: [PeerId: MessageId]
@ -641,7 +642,8 @@ struct AccountMutableState {
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
self.referencedReplyMessageIds.add(sourceId: id, targetId: attribute.messageId)
break inner
} else if let attribute = attribute as? ReplyStoryAttribute {
self.referencedStoryIds.insert(attribute.storyId)
}
}
}
@ -653,7 +655,8 @@ struct AccountMutableState {
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
self.referencedReplyMessageIds.add(sourceId: id, targetId: attribute.messageId)
break inner
} else if let attribute = attribute as? ReplyStoryAttribute {
self.referencedStoryIds.insert(attribute.storyId)
}
}
}

View File

@ -92,6 +92,7 @@ private var declaredEncodables: Void = {
declareEncodable(InlineBotMessageAttribute.self, f: { InlineBotMessageAttribute(decoder: $0) })
declareEncodable(TextEntitiesMessageAttribute.self, f: { TextEntitiesMessageAttribute(decoder: $0) })
declareEncodable(ReplyMessageAttribute.self, f: { ReplyMessageAttribute(decoder: $0) })
declareEncodable(ReplyStoryAttribute.self, f: { ReplyStoryAttribute(decoder: $0) })
declareEncodable(ReplyThreadMessageAttribute.self, f: { ReplyThreadMessageAttribute(decoder: $0) })
declareEncodable(ReactionsMessageAttribute.self, f: { ReactionsMessageAttribute(decoder: $0) })
declareEncodable(PendingReactionsMessageAttribute.self, f: { PendingReactionsMessageAttribute(decoder: $0) })

View File

@ -142,7 +142,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
switch message {
case let .message(_, _, fromId, chatPeerId, fwdHeader, viaBotId, _, _, _, media, _, entities, _, _, _, _, _, _, _, _, _):
case let .message(_, _, fromId, chatPeerId, fwdHeader, viaBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _):
let peerId: PeerId = chatPeerId.peerId
var result = [peerId]
@ -191,6 +191,18 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
}
}
if let replyTo = replyTo {
switch replyTo {
case let .messageReplyStoryHeader(userId, _):
let storyPeerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId))
if !result.contains(storyPeerId) {
result.append(storyPeerId)
}
default:
break
}
}
return result
case .messageEmpty:
return []
@ -483,8 +495,8 @@ extension StoreMessage {
}
}
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId))
case .messageReplyStoryHeader:
break
case let .messageReplyStoryHeader(userId, storyId):
attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), id: storyId)))
}
}
@ -734,8 +746,8 @@ extension StoreMessage {
break
}
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId))
case .messageReplyStoryHeader:
break
case let .messageReplyStoryHeader(userId, storyId):
attributes.append(ReplyStoryAttribute(storyId: StoryId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), id: storyId)))
}
} else {
switch action {

View File

@ -10,13 +10,22 @@ public enum EnqueueMessageGrouping {
}
public enum EnqueueMessage {
case message(text: String, attributes: [MessageAttribute], inlineStickers: [MediaId: Media], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, localGroupingKey: Int64?, correlationId: Int64?, bubbleUpEmojiOrStickersets: [ItemCollectionId])
case message(text: String, attributes: [MessageAttribute], inlineStickers: [MediaId: Media], mediaReference: AnyMediaReference?, replyToMessageId: MessageId?, replyToStoryId: StoryId?, localGroupingKey: Int64?, correlationId: Int64?, bubbleUpEmojiOrStickersets: [ItemCollectionId])
case forward(source: MessageId, threadId: Int64?, grouping: EnqueueMessageGrouping, attributes: [MessageAttribute], correlationId: Int64?)
public func withUpdatedReplyToMessageId(_ replyToMessageId: MessageId?) -> EnqueueMessage {
switch self {
case let .message(text, attributes, inlineStickers, mediaReference, _, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case let .message(text, attributes, inlineStickers, mediaReference, _, replyToStoryId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case .forward:
return self
}
}
public func withUpdatedReplyToStoryId(_ replyToStoryId: StoryId?) -> EnqueueMessage {
switch self {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, _, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case .forward:
return self
}
@ -24,8 +33,8 @@ public enum EnqueueMessage {
public func withUpdatedAttributes(_ f: ([MessageAttribute]) -> [MessageAttribute]) -> EnqueueMessage {
switch self {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: f(attributes), inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, replyToStoryId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: f(attributes), inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case let .forward(source, threadId, grouping, attributes, correlationId):
return .forward(source: source, threadId: threadId, grouping: grouping, attributes: f(attributes), correlationId: correlationId)
}
@ -33,8 +42,8 @@ public enum EnqueueMessage {
public func withUpdatedGroupingKey(_ f: (Int64?) -> Int64?) -> EnqueueMessage {
switch self {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: f(localGroupingKey), correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, replyToStoryId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: f(localGroupingKey), correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case .forward:
return self
}
@ -42,15 +51,15 @@ public enum EnqueueMessage {
public func withUpdatedCorrelationId(_ value: Int64?) -> EnqueueMessage {
switch self {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: value, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, replyToStoryId, localGroupingKey, _, bubbleUpEmojiOrStickersets):
return .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: value, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
case let .forward(source, threadId, grouping, attributes, _):
return .forward(source: source, threadId: threadId, grouping: grouping, attributes: attributes, correlationId: value)
}
}
public var groupingKey: Int64? {
if case let .message(_, _, _, _, _, localGroupingKey, _, _) = self {
if case let .message(_, _, _, _, _, _, localGroupingKey, _, _) = self {
return localGroupingKey
} else {
return nil
@ -61,7 +70,7 @@ public enum EnqueueMessage {
private extension EnqueueMessage {
var correlationId: Int64? {
switch self {
case let .message(_, _, _, _, _, _, correlationId, _):
case let .message(_, _, _, _, _, _, _, correlationId, _):
return correlationId
case let .forward(_, _, _, _, correlationId):
return correlationId
@ -70,7 +79,7 @@ private extension EnqueueMessage {
var bubbleUpEmojiOrStickersets: [ItemCollectionId] {
switch self {
case let .message(_, _, _, _, _, _, _, bubbleUpEmojiOrStickersets):
case let .message(_, _, _, _, _, _, _, _, bubbleUpEmojiOrStickersets):
return bubbleUpEmojiOrStickersets
case .forward:
return []
@ -193,7 +202,7 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox:
var hasMedia = false
loop: for message in messages {
switch message {
case let .message(_, _, _, mediaReference, _, _, _, _):
case let .message(_, _, _, mediaReference, _, _, _, _, _):
if mediaReference != nil {
hasMedia = true
break loop
@ -210,14 +219,14 @@ private func opportunisticallyTransformOutgoingMedia(network: Network, postbox:
var signals: [Signal<(Bool, EnqueueMessage), NoError>] = []
for message in messages {
switch message {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, replyToStoryId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
if let mediaReference = mediaReference {
signals.append(opportunisticallyTransformMessageWithMedia(network: network, postbox: postbox, transformOutgoingMessageMedia: transformOutgoingMessageMedia, mediaReference: mediaReference, userInteractive: userInteractive)
|> map { result -> (Bool, EnqueueMessage) in
if let result = result {
return (true, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
return (true, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: .standalone(media: result.media), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
} else {
return (false, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
return (false, .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
}
})
} else {
@ -287,11 +296,14 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<
var filteredAttributes: [MessageAttribute] = []
var replyToMessageId: MessageId?
var replyToStoryId: StoryId?
var bubbleUpEmojiOrStickersets: [ItemCollectionId] = []
var forwardSource: MessageId?
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
replyToMessageId = attribute.messageId
} else if let attribute = attribute as? ReplyStoryAttribute {
replyToStoryId = attribute.storyId
} else if let attribute = attribute as? OutgoingMessageInfoAttribute {
bubbleUpEmojiOrStickersets = attribute.bubbleUpEmojiOrStickersets
continue inner
@ -305,7 +317,7 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<
if let forwardSource = forwardSource {
messages.append(.forward(source: forwardSource, threadId: nil, grouping: .auto, attributes: filteredAttributes, correlationId: nil))
} else {
messages.append(.message(text: message.text, attributes: filteredAttributes, inlineStickers: [:], mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, localGroupingKey: message.groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
messages.append(.message(text: message.text, attributes: filteredAttributes, inlineStickers: [:], mediaReference: message.media.first.flatMap(AnyMediaReference.standalone), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: message.groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
}
}
}
@ -336,7 +348,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
}
}
switch message {
case let .message(_, attributes, _, _, replyToMessageId, _, _, _):
case let .message(_, attributes, _, _, replyToMessageId, _, _, _, _):
if let replyToMessageId = replyToMessageId, replyToMessageId.peerId != peerId, let replyMessage = transaction.getMessage(replyToMessageId) {
var canBeForwarded = true
if replyMessage.id.namespace != Namespaces.Message.Cloud {
@ -360,7 +372,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
mediaReference = .standalone(media: media)
}
}
updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: threadId.flatMap { MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: $0)) }, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])))
updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: threadId.flatMap { MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: $0)) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])))
continue outer
}
}
@ -402,7 +414,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
globallyUniqueIds.append(randomId)
switch message {
case let .message(text, requestedAttributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, _, _):
case let .message(text, requestedAttributes, inlineStickers, mediaReference, replyToMessageId, replyToStoryId, localGroupingKey, _, _):
for (_, file) in inlineStickers {
transaction.storeMediaIfNotPresent(media: file)
}
@ -478,6 +490,9 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
}
attributes.append(ReplyMessageAttribute(messageId: replyToMessageId, threadMessageId: threadMessageId))
}
if let replyToStoryId = replyToStoryId {
attributes.append(ReplyStoryAttribute(storyId: replyToStoryId))
}
var mediaList: [Media] = []
if let mediaReference = mediaReference {
let augmentedMedia = augmentMediaWithReference(mediaReference)

View File

@ -77,6 +77,7 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
//var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
var replyMessageId: Int32?
var replyToStoryId: StoryId?
var scheduleTime: Int32?
var sendAsPeerId: PeerId?
@ -86,6 +87,8 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
for attribute in attributes {
if let replyAttribute = attribute as? ReplyMessageAttribute {
replyMessageId = replyAttribute.messageId.id
} else if let attribute = attribute as? ReplyStoryAttribute {
replyToStoryId = attribute.storyId
} else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute {
uniqueId = outgoingInfo.uniqueId
} else if let _ = attribute as? ForwardSourceInfoAttribute {
@ -123,6 +126,11 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil)
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
}
}
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer))
@ -136,6 +144,11 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil)
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
}
}
sendMessageRequest = account.network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyTo: replyTo, media: inputMedia, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer))

View File

@ -20,7 +20,7 @@ func _internal_setSecretChatMessageAutoremoveTimeoutInteractively(transaction: T
transaction.setPeerChatState(peerId, state: updatedState)
}
let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(period: timeout == nil ? 0 : timeout!, autoSettingSource: nil))), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))])
let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.messageAutoremoveTimeoutUpdated(period: timeout == nil ? 0 : timeout!, autoSettingSource: nil))), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))])
}
}
}
@ -34,7 +34,7 @@ func _internal_addSecretChatMessageScreenshot(account: Account, peerId: PeerId)
default:
break
}
let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))])
let _ = enqueueMessages(transaction: transaction, account: account, peerId: peerId, messages: [(true, .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaAction(action: TelegramMediaActionType.historyScreenshot)), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))])
}
}
}

View File

@ -769,6 +769,7 @@ public final class PendingMessageManager {
var hideSendersNames = false
var hideCaptions = false
var replyMessageId: Int32?
var replyToStoryId: StoryId?
var scheduleTime: Int32?
var sendAsPeerId: PeerId?
@ -777,6 +778,8 @@ public final class PendingMessageManager {
for attribute in messages[0].0.attributes {
if let replyAttribute = attribute as? ReplyMessageAttribute {
replyMessageId = replyAttribute.messageId.id
} else if let attribute = attribute as? ReplyStoryAttribute {
replyToStoryId = attribute.storyId
} else if let _ = attribute as? ForwardSourceInfoAttribute {
isForward = true
} else if let attribute = attribute as? NotificationInfoMessageAttribute {
@ -919,6 +922,11 @@ public final class PendingMessageManager {
replyFlags |= 1 << 0
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId)
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
}
}
sendMessageRequest = network.request(Api.functions.messages.sendMultiMedia(flags: flags, peer: inputPeer, replyTo: replyTo, multiMedia: singleMedias, scheduleDate: scheduleTime, sendAs: sendAsInputPeer))
@ -1090,6 +1098,7 @@ public final class PendingMessageManager {
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
var replyMessageId: Int32?
var replyToStoryId: StoryId?
var scheduleTime: Int32?
var sendAsPeerId: PeerId?
var bubbleUpEmojiOrStickersets = false
@ -1099,6 +1108,8 @@ public final class PendingMessageManager {
for attribute in message.attributes {
if let replyAttribute = attribute as? ReplyMessageAttribute {
replyMessageId = replyAttribute.messageId.id
} else if let attribute = attribute as? ReplyStoryAttribute {
replyToStoryId = attribute.storyId
} else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute {
uniqueId = outgoingInfo.uniqueId
bubbleUpEmojiOrStickersets = !outgoingInfo.bubbleUpEmojiOrStickersets.isEmpty
@ -1158,6 +1169,11 @@ public final class PendingMessageManager {
replyFlags |= 1 << 0
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: message.threadId.flatMap(Int32.init(clamping:)))
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
}
}
sendMessageRequest = network.requestWithAdditionalInfo(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer), info: .acknowledgement, tag: dependencyTag)
@ -1175,6 +1191,11 @@ public final class PendingMessageManager {
replyFlags |= 1 << 0
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: message.threadId.flatMap(Int32.init(clamping:)))
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
}
}
sendMessageRequest = network.request(Api.functions.messages.sendMedia(flags: flags, peer: inputPeer, replyTo: replyTo, media: inputMedia, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer), tag: dependencyTag)
@ -1206,15 +1227,33 @@ public final class PendingMessageManager {
replyFlags |= 1 << 0
}
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: message.threadId.flatMap(Int32.init(clamping:)))
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
}
}
sendMessageRequest = network.request(Api.functions.messages.sendInlineBotResult(flags: flags, peer: inputPeer, replyTo: replyTo, randomId: uniqueId, queryId: chatContextResult.queryId, id: chatContextResult.id, scheduleDate: scheduleTime, sendAs: sendAsInputPeer))
|> map(NetworkRequestResult.result)
case .messageScreenshot:
var replyTo: Api.InputReplyTo
let replyTo: Api.InputReplyTo
if let replyMessageId = replyMessageId {
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId ?? 0, topMsgId: nil)
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: nil)
} else if let replyToStoryId = replyToStoryId {
if let inputUser = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputUser) {
flags |= 1 << 0
replyTo = .inputReplyToStory(flags: 0, userId: inputUser, storyId: replyToStoryId.id)
} else {
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: 0, topMsgId: nil)
}
} else {
let replyFlags: Int32 = 0
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: 0, topMsgId: nil)
}
sendMessageRequest = network.request(Api.functions.messages.sendScreenshotNotification(peer: inputPeer, replyTo: replyTo, randomId: uniqueId))
|> map(NetworkRequestResult.result)

View File

@ -37,6 +37,30 @@ public class ReplyMessageAttribute: MessageAttribute {
}
}
public class ReplyStoryAttribute: MessageAttribute {
public let storyId: StoryId
public var associatedStoryIds: [StoryId] {
return [self.storyId]
}
public var associatedPeerIds: [PeerId] {
return [self.storyId.peerId]
}
public init(storyId: StoryId) {
self.storyId = storyId
}
required public init(decoder: PostboxDecoder) {
self.storyId = decoder.decode(StoryId.self, forKey: "i") ?? StoryId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(1)), id: 1)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encode(self.storyId, forKey: "i")
}
}
public extension Message {
var effectiveReplyThreadMessageId: MessageId? {
if let threadId = self.threadId {

View File

@ -280,7 +280,8 @@ private class AdMessagesHistoryContextImpl {
associatedMessages: SimpleDictionary<MessageId, Message>(),
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
}
}

View File

@ -81,6 +81,9 @@ public final class EngineMessage: Equatable {
public var associatedThreadInfo: Message.AssociatedThreadInfo? {
return self.impl.associatedThreadInfo
}
public var associatedStories: [StoryId: CodableEntry] {
return self.impl.associatedStories
}
public var index: MessageIndex {
return self.impl.index
@ -108,7 +111,8 @@ public final class EngineMessage: Equatable {
associatedMessages: [EngineMessage.Id: EngineMessage],
associatedMessageIds: [EngineMessage.Id],
associatedMedia: [MediaId: Media],
associatedThreadInfo: Message.AssociatedThreadInfo?
associatedThreadInfo: Message.AssociatedThreadInfo?,
associatedStories: [StoryId: CodableEntry]
) {
var mappedPeers: [PeerId: Peer] = [:]
for (id, peer) in peers {
@ -142,7 +146,8 @@ public final class EngineMessage: Equatable {
associatedMessages: SimpleDictionary(mappedAssociatedMessages),
associatedMessageIds: associatedMessageIds,
associatedMedia: associatedMedia,
associatedThreadInfo: associatedThreadInfo
associatedThreadInfo: associatedThreadInfo,
associatedStories: associatedStories
)
}

View File

@ -2,15 +2,15 @@ import Foundation
import Postbox
import SwiftSignalKit
func _internal_enqueueOutgoingMessageWithChatContextResult(account: Account, to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> Bool {
guard let message = _internal_outgoingMessageWithChatContextResult(to: peerId, threadId: threadId, botId: botId, result: result, replyToMessageId: replyToMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId) else {
func _internal_enqueueOutgoingMessageWithChatContextResult(account: Account, to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId?, replyToStoryId: StoryId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> Bool {
guard let message = _internal_outgoingMessageWithChatContextResult(to: peerId, threadId: threadId, botId: botId, result: result, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId) else {
return false
}
let _ = enqueueMessages(account: account, peerId: peerId, messages: [message]).start()
return true
}
func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> EnqueueMessage? {
func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId?, replyToStoryId: StoryId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> EnqueueMessage? {
var replyToMessageId = replyToMessageId
if replyToMessageId == nil, let threadId = threadId {
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: MessageId.Id(clamping: threadId))
@ -46,19 +46,19 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId:
return true
}
if let media: Media = internalReference.file ?? internalReference.image {
return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
} else {
return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: filteredAttributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
}
} else {
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaGame(gameId: 0, accessHash: 0, name: "", title: internalReference.title ?? "", description: internalReference.description ?? "", image: internalReference.image, file: internalReference.file)), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
}
} else if let file = internalReference.file, internalReference.type == "gif" {
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
} else if let image = internalReference.image {
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: image), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
} else if let file = internalReference.file {
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
} else {
return nil
}
@ -70,9 +70,9 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId:
let thumbnailResource = thumbnail.resource
let imageDimensions = thumbnail.dimensions ?? PixelDimensions(width: 128, height: 128)
let tmpImage = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: [TelegramMediaImageRepresentation(dimensions: imageDimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false)], immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: tmpImage), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
} else {
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
}
} else if externalReference.type == "document" || externalReference.type == "gif" || externalReference.type == "audio" || externalReference.type == "voice" {
var videoThumbnails: [TelegramMediaFile.VideoThumbnail] = []
@ -132,9 +132,9 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId:
}
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, immediateThumbnailData: nil, mimeType: externalReference.content?.mimeType ?? "application/binary", size: nil, attributes: fileAttributes)
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
} else {
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: caption, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
}
}
case let .text(text, entities, _, replyMarkup):
@ -144,21 +144,21 @@ func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId:
if let replyMarkup = replyMarkup {
attributes.append(replyMarkup)
}
return .message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
case let .mapLocation(media, replyMarkup):
if let replyMarkup = replyMarkup {
attributes.append(replyMarkup)
}
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
case let .contact(media, replyMarkup):
if let replyMarkup = replyMarkup {
attributes.append(replyMarkup)
}
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
case let .invoice(media, replyMarkup):
if let replyMarkup = replyMarkup {
attributes.append(replyMarkup)
}
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
return .message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])
}
}

View File

@ -24,7 +24,7 @@ func _internal_requestStartBot(account: Account, botPeerId: PeerId, payload: Str
}
}
} else {
return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) |> mapToSignal { _ -> Signal<Void, NoError> in
return enqueueMessages(account: account, peerId: botPeerId, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) |> mapToSignal { _ -> Signal<Void, NoError> in
return .complete()
}
}

View File

@ -218,6 +218,7 @@ public extension TelegramEngine {
public func enqueueOutgoingMessage(
to peerId: EnginePeer.Id,
replyTo replyToMessageId: EngineMessage.Id?,
storyId: StoryId? = nil,
content: EngineOutgoingMessageContent
) {
switch content {
@ -228,6 +229,7 @@ public extension TelegramEngine {
inlineStickers: [:],
mediaReference: nil,
replyToMessageId: replyToMessageId,
replyToStoryId: storyId,
localGroupingKey: nil,
correlationId: nil,
bubbleUpEmojiOrStickersets: []
@ -240,12 +242,12 @@ public extension TelegramEngine {
}
}
public func enqueueOutgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId? = nil, hideVia: Bool = false, silentPosting: Bool = false, scheduleTime: Int32? = nil, correlationId: Int64? = nil) -> Bool {
return _internal_enqueueOutgoingMessageWithChatContextResult(account: self.account, to: peerId, threadId: threadId, botId: botId, result: result, replyToMessageId: replyToMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId)
public func enqueueOutgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId? = nil, replyToStoryId: StoryId? = nil, hideVia: Bool = false, silentPosting: Bool = false, scheduleTime: Int32? = nil, correlationId: Int64? = nil) -> Bool {
return _internal_enqueueOutgoingMessageWithChatContextResult(account: self.account, to: peerId, threadId: threadId, botId: botId, result: result, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId)
}
public func outgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> EnqueueMessage? {
return _internal_outgoingMessageWithChatContextResult(to: peerId, threadId: threadId, botId: botId, result: result, replyToMessageId: replyToMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId)
public func outgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: MessageId?, replyToStoryId: StoryId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, correlationId: Int64?) -> EnqueueMessage? {
return _internal_outgoingMessageWithChatContextResult(to: peerId, threadId: threadId, botId: botId, result: result, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime, correlationId: correlationId)
}
public func setMessageReactions(
@ -591,13 +593,30 @@ public extension TelegramEngine {
}
public func storySubscriptions() -> Signal<EngineStorySubscriptions, NoError> {
let debugTimerSignal: Signal<Bool, NoError>
#if DEBUG && false
debugTimerSignal = Signal<Bool, NoError>.single(true)
|> then(
Signal<Bool, NoError>.single(true)
|> delay(1.0, queue: .mainQueue())
|> then(
Signal<Bool, NoError>.single(false)
|> delay(1.0, queue: .mainQueue())
)
|> restart
)
#else
debugTimerSignal = .single(true)
#endif
let basicPeerKey = PostboxViewKey.basicPeer(self.account.peerId)
return self.account.postbox.combinedView(keys: [
return combineLatest(debugTimerSignal |> distinctUntilChanged,
self.account.postbox.combinedView(keys: [
basicPeerKey,
PostboxViewKey.storySubscriptions,
PostboxViewKey.storiesState(key: .subscriptions)
])
|> mapToSignal { views -> Signal<EngineStorySubscriptions, NoError> in
]))
|> mapToSignal { debugTimer, views -> Signal<EngineStorySubscriptions, NoError> in
guard let basicPeerView = views.views[basicPeerKey] as? BasicPeerView, let accountPeer = basicPeerView.peer else {
return .single(EngineStorySubscriptions(accountItem: nil, items: [], hasMoreToken: nil))
}
@ -613,7 +632,10 @@ public extension TelegramEngine {
additionalDataKeys.append(PostboxViewKey.storyItems(peerId: self.account.peerId))
additionalDataKeys.append(PostboxViewKey.storiesState(key: .peer(self.account.peerId)))
let subscriptionPeerIds = storySubscriptionsView.peerIds.filter { $0 != self.account.peerId }
var subscriptionPeerIds = storySubscriptionsView.peerIds.filter { $0 != self.account.peerId }
if !debugTimer {
subscriptionPeerIds.removeAll()
}
additionalDataKeys.append(contentsOf: subscriptionPeerIds.map { peerId -> PostboxViewKey in
return PostboxViewKey.storyItems(peerId: peerId)

View File

@ -220,7 +220,7 @@ func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer], associ
let second = UInt32(hashValue & 0xffffffff)
let stableId = first &+ second
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo)
return Message(stableId: stableId, stableVersion: 0, id: id, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: message.threadId, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, globalTags: message.globalTags, localTags: message.localTags, forwardInfo: forwardInfo, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: associatedThreadInfo, associatedStories: [:])
}
public extension Message {

View File

@ -172,6 +172,7 @@ public final class ChatControllerInteraction {
public let cancelInteractiveKeyboardGestures: () -> Void
public let dismissTextInput: () -> Void
public let scrollToMessageId: (MessageIndex) -> Void
public let navigateToStory: (Message, StoryId) -> Void
public var canPlayMedia: Bool = false
public var hiddenMedia: [MessageId: [Media]] = [:]
@ -283,6 +284,7 @@ public final class ChatControllerInteraction {
cancelInteractiveKeyboardGestures: @escaping () -> Void,
dismissTextInput: @escaping () -> Void,
scrollToMessageId: @escaping (MessageIndex) -> Void,
navigateToStory: @escaping (Message, StoryId) -> Void,
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
pollActionState: ChatInterfacePollActionState,
stickerSettings: ChatInterfaceStickerSettings,
@ -377,6 +379,7 @@ public final class ChatControllerInteraction {
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
self.dismissTextInput = dismissTextInput
self.scrollToMessageId = scrollToMessageId
self.navigateToStory = navigateToStory
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings

View File

@ -2101,7 +2101,7 @@ public final class ChatEntityKeyboardInputNode: ChatInputNode {
}
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: PeerId(0), namespace: Namespaces.Message.Local, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: nil, text: "", attributes: [], media: [file.media], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let gallery = GalleryController(context: strongSelf.context, source: .standaloneMessage(message), streamSingleVideo: true, replaceRootController: { _, _ in
}, baseNavigationController: nil)

View File

@ -132,6 +132,8 @@ public final class ChatListHeaderComponent: Component {
public let secondaryContent: Content?
public let secondaryTransition: CGFloat
public let networkStatus: HeaderNetworkStatusComponent.Content?
public let storySubscriptions: EngineStorySubscriptions?
public let storiesFraction: CGFloat
public let context: AccountContext
public let theme: PresentationTheme
public let strings: PresentationStrings
@ -145,6 +147,8 @@ public final class ChatListHeaderComponent: Component {
secondaryContent: Content?,
secondaryTransition: CGFloat,
networkStatus: HeaderNetworkStatusComponent.Content?,
storySubscriptions: EngineStorySubscriptions?,
storiesFraction: CGFloat,
context: AccountContext,
theme: PresentationTheme,
strings: PresentationStrings,
@ -157,6 +161,8 @@ public final class ChatListHeaderComponent: Component {
self.secondaryTransition = secondaryTransition
self.context = context
self.networkStatus = networkStatus
self.storySubscriptions = storySubscriptions
self.storiesFraction = storiesFraction
self.theme = theme
self.strings = strings
self.openStatusSetup = openStatusSetup
@ -179,6 +185,12 @@ public final class ChatListHeaderComponent: Component {
if lhs.networkStatus != rhs.networkStatus {
return false
}
if lhs.storySubscriptions != rhs.storySubscriptions {
return false
}
if lhs.storiesFraction != rhs.storiesFraction {
return false
}
if lhs.context !== rhs.context {
return false
}
@ -280,6 +292,7 @@ public final class ChatListHeaderComponent: Component {
var chatListTitleView: ChatListTitleView?
var contentOffsetFraction: CGFloat = 0.0
private(set) var centerContentWidth: CGFloat = 0.0
init(
backPressed: @escaping () -> Void,
@ -342,15 +355,11 @@ public final class ChatListHeaderComponent: Component {
}
self.contentOffsetFraction = contentOffsetFraction
let scale = 1.0 * (1.0 - contentOffsetFraction) + 0.001 * contentOffsetFraction
let translation = -44.0 * contentOffsetFraction * 0.5
let translation = 44.0 * contentOffsetFraction * 0.5
var transform = CATransform3DIdentity
transform = CATransform3DTranslate(transform, 0.0, translation, 0.0)
transform = CATransform3DTranslate(transform, translation, 0.0, 0.0)
transition.setSublayerTransform(view: self.titleOffsetContainer, transform: transform)
transition.setScale(view: self.titleScaleContainer, scale: scale)
transition.setAlpha(view: self.titleScaleContainer, alpha: 1.0 - contentOffsetFraction)
}
func updateNavigationTransitionAsPrevious(nextView: ContentView, fraction: CGFloat, transition: Transition, completion: @escaping () -> Void) {
@ -431,7 +440,7 @@ public final class ChatListHeaderComponent: Component {
}
}
func update(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, content: Content, backTitle: String?, sideInset: CGFloat, size: CGSize, transition: Transition) {
func update(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, content: Content, backTitle: String?, sideInset: CGFloat, sideContentWidth: CGFloat, size: CGSize, transition: Transition) {
transition.setPosition(view: self.titleOffsetContainer, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5))
transition.setBounds(view: self.titleOffsetContainer, bounds: CGRect(origin: self.titleOffsetContainer.bounds.origin, size: size))
@ -573,7 +582,8 @@ public final class ChatListHeaderComponent: Component {
let remainingWidth = size.width - commonInset * 2.0
let titleTextSize = self.titleTextView.updateLayout(CGSize(width: remainingWidth, height: size.height))
let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleTextSize.width) / 2.0), y: floor((size.height - titleTextSize.height) / 2.0)), size: titleTextSize)
let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleTextSize.width) / 2.0) + sideContentWidth, y: floor((size.height - titleTextSize.height) / 2.0)), size: titleTextSize)
transition.setFrame(view: self.titleTextView, frame: titleFrame)
if let titleComponent = content.titleComponent {
@ -592,6 +602,7 @@ public final class ChatListHeaderComponent: Component {
environment: {},
containerSize: CGSize(width: remainingWidth, height: size.height)
)
if let titleContentComponentView = titleContentView.view {
if titleContentComponentView.superview == nil {
self.titleScaleContainer.addSubview(titleContentComponentView)
@ -622,7 +633,8 @@ public final class ChatListHeaderComponent: Component {
chatListTitleView.theme = theme
chatListTitleView.strings = strings
chatListTitleView.setTitle(chatListTitle, animated: false)
chatListTitleView.updateLayout(size: chatListTitleContentSize, clearBounds: CGRect(origin: CGPoint(), size: chatListTitleContentSize), transition: transition.containedViewLayoutTransition)
let centerContentWidth = chatListTitleView.updateLayout(size: chatListTitleContentSize, clearBounds: CGRect(origin: CGPoint(), size: chatListTitleContentSize), sideContentWidth: sideContentWidth, transition: transition.containedViewLayoutTransition)
self.centerContentWidth = centerContentWidth
chatListTitleView.openStatusSetup = { [weak self] sourceView in
guard let self else {
@ -657,6 +669,7 @@ public final class ChatListHeaderComponent: Component {
private var secondaryContentView: ContentView?
private var storyOffsetFraction: CGFloat = 0.0
private let storyPeerListExternalState = StoryPeerListComponent.ExternalState()
private var storyPeerList: ComponentView<Empty>?
public var storyPeerAction: ((EnginePeer?) -> Void)?
@ -718,6 +731,12 @@ public final class ChatListHeaderComponent: Component {
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let storyPeerListView = self.storyPeerList?.view {
if let result = storyPeerListView.hitTest(self.convert(point, to: storyPeerListView), with: event) {
return result
}
}
for subview in self.subviews.reversed() {
if !subview.isUserInteractionEnabled || subview.alpha < 0.01 || subview.isHidden {
continue
@ -730,12 +749,6 @@ public final class ChatListHeaderComponent: Component {
}
}
if let storyPeerListView = self.storyPeerList?.view {
if let result = storyPeerListView.hitTest(self.convert(point, to: storyPeerListView), with: event) {
return result
}
}
let defaultResult = super.hitTest(point, with: event)
if let defaultResult, defaultResult !== self {
@ -745,16 +758,29 @@ public final class ChatListHeaderComponent: Component {
return defaultResult
}
public func updateStories(offset: CGFloat, context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, storySubscriptions: EngineStorySubscriptions?, transition: Transition) {
var storyOffsetFraction: CGFloat = 1.0
if let storySubscriptions, !storySubscriptions.items.isEmpty {
storyOffsetFraction = offset
/*public func updateStories(offset: CGFloat, context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, storySubscriptions: EngineStorySubscriptions?, transition: Transition) {
}*/
private func updateContentStoryOffsets(transition: Transition) {
}
self.storyOffsetFraction = storyOffsetFraction
func update(component: ChatListHeaderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
self.state = state
let previousComponent = self.component
self.component = component
var storyListTransition = transition
if let storySubscriptions = component.storySubscriptions {
var storyOffsetFraction: CGFloat = 1.0
storyOffsetFraction = component.storiesFraction
let _ = storyOffsetFraction
//self.storyOffsetFraction = storyOffsetFraction
let storyPeerList: ComponentView<Empty>
var storyListTransition = transition
if let current = self.storyPeerList {
storyPeerList = current
} else {
@ -763,15 +789,15 @@ public final class ChatListHeaderComponent: Component {
self.storyPeerList = storyPeerList
}
if !self.bounds.isEmpty {
let _ = storyPeerList.update(
transition: storyListTransition,
component: AnyComponent(StoryPeerListComponent(
context: context,
theme: theme,
strings: strings,
externalState: self.storyPeerListExternalState,
context: component.context,
theme: component.theme,
strings: component.strings,
storySubscriptions: storySubscriptions,
collapseFraction: 1.0 - offset,
collapseFraction: 1.0 - component.storiesFraction,
peerAction: { [weak self] peer in
guard let self else {
return
@ -782,44 +808,8 @@ public final class ChatListHeaderComponent: Component {
environment: {},
containerSize: CGSize(width: self.bounds.width, height: 94.0)
)
if let storyPeerListComponentView = storyPeerList.view {
if storyPeerListComponentView.superview == nil {
self.addSubview(storyPeerListComponentView)
}
let storyPeerListMinOffset: CGFloat = -7.0
let storyPeerListMaxOffset: CGFloat = self.bounds.height + 8.0
let storyPeerListPosition: CGFloat = storyPeerListMinOffset * (1.0 - offset) + storyPeerListMaxOffset * offset
storyListTransition.setFrame(view: storyPeerListComponentView, frame: CGRect(origin: CGPoint(x: 0.0, y: storyPeerListPosition), size: CGSize(width: self.bounds.width, height: 94.0)))
var storyListAlpha: CGFloat = 1.0
if let storySubscriptions, !storySubscriptions.items.isEmpty {
} else {
storyListAlpha = offset
}
storyListTransition.setAlpha(view: storyPeerListComponentView, alpha: storyListAlpha)
}
if let primaryContentView = self.primaryContentView {
primaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: transition)
}
if let secondaryContentView = self.secondaryContentView {
secondaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: transition)
}
}
}
private func updateContentStoryOffsets(transition: Transition) {
}
func update(component: ChatListHeaderComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
self.state = state
let previousComponent = self.component
self.component = component
if let primaryContent = component.primaryContent {
var primaryContentTransition = transition
let primaryContentView: ContentView
@ -850,7 +840,18 @@ public final class ChatListHeaderComponent: Component {
self.primaryContentView = primaryContentView
self.addSubview(primaryContentView)
}
primaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: primaryContent, backTitle: primaryContent.backTitle, sideInset: component.sideInset, size: availableSize, transition: primaryContentTransition)
var sideContentWidth: CGFloat = 0.0
if let storySubscriptions = component.storySubscriptions, !storySubscriptions.items.isEmpty {
sideContentWidth = self.storyPeerListExternalState.collapsedWidth + 8.0
}
if let chatListTitle = primaryContent.chatListTitle {
if chatListTitle.activity {
sideContentWidth = 0.0
}
}
primaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: primaryContent, backTitle: primaryContent.backTitle, sideInset: component.sideInset, sideContentWidth: sideContentWidth * (1.0 - component.storiesFraction), size: availableSize, transition: primaryContentTransition)
primaryContentTransition.setFrame(view: primaryContentView, frame: CGRect(origin: CGPoint(), size: availableSize))
primaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: primaryContentTransition)
@ -889,7 +890,7 @@ public final class ChatListHeaderComponent: Component {
self.secondaryContentView = secondaryContentView
self.addSubview(secondaryContentView)
}
secondaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: secondaryContent, backTitle: component.primaryContent?.navigationBackTitle ?? component.primaryContent?.title, sideInset: component.sideInset, size: availableSize, transition: secondaryContentTransition)
secondaryContentView.update(context: component.context, theme: component.theme, strings: component.strings, content: secondaryContent, backTitle: component.primaryContent?.navigationBackTitle ?? component.primaryContent?.title, sideInset: component.sideInset, sideContentWidth: 0.0, size: availableSize, transition: secondaryContentTransition)
secondaryContentTransition.setFrame(view: secondaryContentView, frame: CGRect(origin: CGPoint(), size: availableSize))
secondaryContentView.updateContentOffsetFraction(contentOffsetFraction: 1.0 - self.storyOffsetFraction, transition: secondaryContentTransition)
@ -933,6 +934,34 @@ public final class ChatListHeaderComponent: Component {
}
}
if let storyPeerList = self.storyPeerList, let storyPeerListComponentView = storyPeerList.view {
if storyPeerListComponentView.superview == nil {
self.addSubview(storyPeerListComponentView)
}
let storyPeerListMinOffset: CGFloat = -7.0
let storyPeerListMaxOffset: CGFloat = availableSize.height + 8.0
let storyPeerListPosition: CGFloat = storyPeerListMinOffset * (1.0 - component.storiesFraction) + storyPeerListMaxOffset * component.storiesFraction
var defaultStoryListX: CGFloat = 0.0
if let primaryContentView = self.primaryContentView {
defaultStoryListX = floor((self.storyPeerListExternalState.collapsedWidth - primaryContentView.centerContentWidth) * 0.5)
}
storyListTransition.setFrame(view: storyPeerListComponentView, frame: CGRect(origin: CGPoint(x: -1.0 * availableSize.width * component.secondaryTransition + (1.0 - component.storiesFraction) * defaultStoryListX, y: storyPeerListPosition), size: CGSize(width: availableSize.width, height: 94.0)))
var storyListNormalAlpha: CGFloat = 1.0
if let chatListTitle = component.primaryContent?.chatListTitle {
if chatListTitle.activity {
storyListNormalAlpha = component.storiesFraction
}
}
let storyListAlpha: CGFloat = (1.0 - component.secondaryTransition) * storyListNormalAlpha
storyListTransition.setAlpha(view: storyPeerListComponentView, alpha: storyListAlpha)
}
return availableSize
}

View File

@ -62,7 +62,7 @@ public final class ChatListTitleView: UIView, NavigationBarTitleView, Navigation
public var openStatusSetup: ((UIView) -> Void)?
private var validLayout: (CGSize, CGRect)?
private var validLayout: (CGSize, CGRect, CGFloat)?
public var manualLayout: Bool = false
@ -316,13 +316,13 @@ public final class ChatListTitleView: UIView, NavigationBarTitleView, Navigation
override public func layoutSubviews() {
super.layoutSubviews()
if !self.manualLayout, let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .immediate)
if !self.manualLayout, let (size, clearBounds, sideContentWidth) = self.validLayout {
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: sideContentWidth, transition: .immediate)
}
}
public func updateLayout(size: CGSize, clearBounds: CGRect, transition: ContainedViewLayoutTransition) {
self.validLayout = (size, clearBounds)
public func updateLayout(size: CGSize, clearBounds: CGRect, sideContentWidth: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
self.validLayout = (size, clearBounds, sideContentWidth)
var indicatorPadding: CGFloat = 0.0
let indicatorSize = self.activityIndicator.bounds.size
@ -344,7 +344,10 @@ public final class ChatListTitleView: UIView, NavigationBarTitleView, Navigation
let combinedHeight = titleSize.height
var titleContentRect = CGRect(origin: CGPoint(x: indicatorPadding + floor((size.width - titleSize.width - indicatorPadding) / 2.0), y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
let combinedWidth = sideContentWidth + titleSize.width
var titleContentRect = CGRect(origin: CGPoint(x: indicatorPadding + floor((size.width - combinedWidth - indicatorPadding) / 2.0) + sideContentWidth, y: floor((size.height - combinedHeight) / 2.0)), size: titleSize)
titleContentRect.origin.x = min(titleContentRect.origin.x, clearBounds.maxX - proxyPadding - titleContentRect.width)
let titleFrame = titleContentRect
@ -425,6 +428,8 @@ public final class ChatListTitleView: UIView, NavigationBarTitleView, Navigation
}
}
}
return combinedWidth
}
@objc private func buttonPressed() {

View File

@ -118,7 +118,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
private let button: HighlightTrackingButtonNode
var manualLayout: Bool = false
private var validLayout: (CGSize, CGRect)?
private var validLayout: (CGSize, CGRect, CGFloat)?
private var titleLeftIcon: ChatTitleIcon = .none
private var titleRightIcon: ChatTitleIcon = .none
@ -355,8 +355,8 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.button.isUserInteractionEnabled = isEnabled
if !self.updateStatus() {
if updated {
if !self.manualLayout, let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .animated(duration: 0.2, curve: .easeInOut))
if !self.manualLayout, let (size, clearBounds, sideContentWidth) = self.validLayout {
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: sideContentWidth, transition: .animated(duration: 0.2, curve: .easeInOut))
}
}
}
@ -605,8 +605,8 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
}
if self.activityNode.transitionToState(state, animation: .slide) {
if !self.manualLayout, let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .animated(duration: 0.3, curve: .spring))
if !self.manualLayout, let (size, clearBounds, sideContentWidth) = self.validLayout {
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: sideContentWidth, transition: .animated(duration: 0.3, curve: .spring))
}
return true
} else {
@ -688,8 +688,8 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
override public func layoutSubviews() {
super.layoutSubviews()
if !self.manualLayout, let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .immediate)
if !self.manualLayout, let (size, clearBounds, sideContentWidth) = self.validLayout {
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: sideContentWidth, transition: .immediate)
}
}
@ -704,14 +704,14 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.titleContent = titleContent
let _ = self.updateStatus()
if !self.manualLayout, let (size, clearBounds) = self.validLayout {
self.updateLayout(size: size, clearBounds: clearBounds, transition: .immediate)
if !self.manualLayout, let (size, clearBounds, sideContentWidth) = self.validLayout {
let _ = self.updateLayout(size: size, clearBounds: clearBounds, sideContentWidth: sideContentWidth, transition: .immediate)
}
}
}
public func updateLayout(size: CGSize, clearBounds: CGRect, transition: ContainedViewLayoutTransition) {
self.validLayout = (size, clearBounds)
public func updateLayout(size: CGSize, clearBounds: CGRect, sideContentWidth: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat {
self.validLayout = (size, clearBounds, sideContentWidth)
self.button.frame = clearBounds
self.contentContainer.frame = clearBounds
@ -850,6 +850,8 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
}
self.pointerInteraction = PointerInteraction(view: self, style: .rectangle(CGSize(width: titleFrame.width + 16.0, height: 40.0)))
return titleFrame.width
}
@objc private func buttonPressed() {
@ -1013,7 +1015,7 @@ public final class ChatTitleComponent: Component {
}
contentView.updateThemeAndStrings(theme: component.theme, strings: component.strings, hasEmbeddedTitleContent: false)
contentView.updateLayout(size: availableSize, clearBounds: CGRect(origin: CGPoint(), size: availableSize), transition: transition.containedViewLayoutTransition)
let _ = contentView.updateLayout(size: availableSize, clearBounds: CGRect(origin: CGPoint(), size: availableSize), sideContentWidth: 0.0, transition: transition.containedViewLayoutTransition)
transition.setFrame(view: contentView, frame: CGRect(origin: CGPoint(), size: availableSize))
return availableSize

View File

@ -213,7 +213,7 @@ public func legacyInstantVideoController(theme: PresentationTheme, panelFrame: C
}
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: "video/mp4", size: nil, attributes: [.FileName(fileName: "video.mp4"), .Video(duration: Int(finalDuration), size: PixelDimensions(finalDimensions), flags: [.instantRoundVideo], preloadSize: nil)])
var message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
var message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let scheduleTime: Int32? = scheduleTimestamp > 0 ? scheduleTimestamp : nil

View File

@ -879,7 +879,8 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
associatedMessages: SimpleDictionary<MessageId, Message>(),
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
let messageItem = ListMessageItem(
presentationData: self.chatPresentationData,
@ -2284,7 +2285,8 @@ public final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode,
associatedMessages: SimpleDictionary<MessageId, Message>(),
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
let messageItem = ListMessageItem(
presentationData: self.itemGridBinding.chatPresentationData,

View File

@ -510,7 +510,7 @@ private final class SendInviteLinkScreenComponent: Component {
} else if let link = component.link {
let selectedPeers = component.peers.filter { self.selectedItems.contains($0.id) }
let _ = enqueueMessagesToMultiplePeers(account: component.context.account, peerIds: Array(self.selectedItems), threadIds: [:], messages: [.message(text: link, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
let _ = enqueueMessagesToMultiplePeers(account: component.context.account, peerIds: Array(self.selectedItems), threadIds: [:], messages: [.message(text: link, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
let text: String
if selectedPeers.count == 1 {
text = environment.strings.Conversation_ShareLinkTooltip_Chat_One(selectedPeers[0].displayTitle(strings: environment.strings, displayOrder: .firstLast).replacingOccurrences(of: "*", with: "")).string

View File

@ -0,0 +1,207 @@
import Foundation
import UIKit
import Display
import ComponentFlow
import MultilineTextComponent
final class StoryContentCaptionComponent: Component {
final class ExternalState {
fileprivate(set) var expandFraction: CGFloat = 0.0
init() {
}
}
let externalState: ExternalState
let text: String
init(
externalState: ExternalState,
text: String
) {
self.externalState = externalState
self.text = text
}
static func ==(lhs: StoryContentCaptionComponent, rhs: StoryContentCaptionComponent) -> Bool {
if lhs.text != rhs.text {
return false
}
return true
}
final class View: UIView, UIScrollViewDelegate {
private let scrollViewContainer: UIView
private let scrollView: UIScrollView
private let scrollMaskContainer: UIView
private let scrollFullMaskView: UIView
private let scrollCenterMaskView: UIView
private let scrollBottomMaskView: UIImageView
private let text = ComponentView<Empty>()
private var component: StoryContentCaptionComponent?
private weak var state: EmptyComponentState?
private var ignoreScrolling: Bool = false
private var ignoreExternalState: Bool = false
override init(frame: CGRect) {
self.scrollViewContainer = UIView()
self.scrollView = UIScrollView()
self.scrollView.canCancelContentTouches = true
self.scrollView.delaysContentTouches = false
self.scrollView.showsVerticalScrollIndicator = false
self.scrollView.contentInsetAdjustmentBehavior = .never
self.scrollView.alwaysBounceVertical = false
self.scrollMaskContainer = UIView()
self.scrollFullMaskView = UIView()
self.scrollFullMaskView.backgroundColor = .white
self.scrollFullMaskView.alpha = 0.0
self.scrollMaskContainer.addSubview(self.scrollFullMaskView)
self.scrollCenterMaskView = UIView()
self.scrollCenterMaskView.backgroundColor = .white
self.scrollMaskContainer.addSubview(self.scrollCenterMaskView)
self.scrollBottomMaskView = UIImageView(image: generateGradientImage(size: CGSize(width: 8.0, height: 8.0), colors: [
UIColor(white: 1.0, alpha: 1.0),
UIColor(white: 1.0, alpha: 0.0)
], locations: [0.0, 1.0]))
self.scrollMaskContainer.addSubview(self.scrollBottomMaskView)
super.init(frame: frame)
self.scrollViewContainer.addSubview(self.scrollView)
self.scrollView.delegate = self
self.addSubview(self.scrollViewContainer)
self.scrollViewContainer.mask = self.scrollMaskContainer
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.bounds.contains(point) {
return nil
}
if let textView = self.text.view {
let textLocalPoint = self.convert(point, to: textView)
if textLocalPoint.y >= -7.0 {
return self.scrollView
}
}
return nil
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !self.ignoreScrolling {
self.updateScrolling(transition: .immediate)
}
}
func collapse(transition: Transition) {
self.ignoreScrolling = true
transition.setBounds(view: self.scrollView, bounds: CGRect(origin: CGPoint(), size: self.scrollView.bounds.size))
self.ignoreScrolling = false
self.updateScrolling(transition: transition)
}
private func updateScrolling(transition: Transition) {
guard let component = self.component else {
return
}
var edgeDistance = self.scrollView.contentSize.height - self.scrollView.bounds.maxY
edgeDistance = max(0.0, min(7.0, edgeDistance))
let edgeDistanceFraction = edgeDistance / 7.0
transition.setAlpha(view: self.scrollFullMaskView, alpha: 1.0 - edgeDistanceFraction)
let expandDistance: CGFloat = 50.0
var expandFraction: CGFloat = self.scrollView.contentOffset.y / expandDistance
expandFraction = max(0.0, min(1.0, expandFraction))
if self.scrollView.contentSize.height < self.scrollView.bounds.height + expandDistance {
expandFraction = 0.0
}
if component.externalState.expandFraction != expandFraction {
component.externalState.expandFraction = expandFraction
if !self.ignoreExternalState {
self.state?.updated(transition: transition)
}
}
}
func update(component: StoryContentCaptionComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
self.ignoreExternalState = true
self.component = component
self.state = state
let sideInset: CGFloat = 16.0
let verticalInset: CGFloat = 7.0
let textContainerSize = CGSize(width: availableSize.width - sideInset * 2.0 - 50.0, height: availableSize.height - verticalInset * 2.0)
let textSize = self.text.update(
transition: .immediate,
component: AnyComponent(MultilineTextComponent(
text: .plain(NSAttributedString(string: component.text, font: Font.regular(16.0), textColor: .white)),
maximumNumberOfLines: 0,
textShadowColor: UIColor(white: 0.0, alpha: 0.3)
)),
environment: {},
containerSize: textContainerSize
)
let maxHeight: CGFloat = 50.0
let visibleTextHeight = min(maxHeight, textSize.height)
let textOverflowHeight: CGFloat = textSize.height - visibleTextHeight
let scrollContentSize = CGSize(width: availableSize.width, height: availableSize.height + textOverflowHeight)
if let textView = self.text.view {
if textView.superview == nil {
self.scrollView.addSubview(textView)
}
textView.frame = CGRect(origin: CGPoint(x: sideInset, y: availableSize.height - visibleTextHeight - verticalInset), size: textSize)
}
self.ignoreScrolling = true
if self.scrollView.contentSize != scrollContentSize {
self.scrollView.contentSize = scrollContentSize
}
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: availableSize.height)))
transition.setFrame(view: self.scrollViewContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: availableSize.height)))
self.ignoreScrolling = false
self.updateScrolling(transition: transition)
let gradientEdgeHeight: CGFloat = 18.0
transition.setFrame(view: self.scrollFullMaskView, frame: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: availableSize.height)))
transition.setFrame(view: self.scrollCenterMaskView, frame: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: availableSize.height - gradientEdgeHeight)))
transition.setFrame(view: self.scrollBottomMaskView, frame: CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - gradientEdgeHeight), size: CGSize(width: availableSize.width, height: gradientEdgeHeight)))
self.ignoreExternalState = false
return availableSize
}
}
func makeView() -> View {
return View(frame: CGRect())
}
func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
}
}

View File

@ -15,6 +15,7 @@ import LegacyInstantVideoController
import UndoUI
import ContextUI
import TelegramCore
import Postbox
import AvatarNode
public final class StoryItemSetContainerComponent: Component {
@ -148,6 +149,16 @@ public final class StoryItemSetContainerComponent: Component {
}
}
final class CaptionItem {
let itemId: Int32
let externalState = StoryContentCaptionComponent.ExternalState()
let view = ComponentView<Empty>()
init(itemId: Int32) {
self.itemId = itemId
}
}
public final class View: UIView, UIScrollViewDelegate, UIGestureRecognizerDelegate {
let sendMessageContext: StoryItemSetContainerSendMessage
@ -167,6 +178,8 @@ public final class StoryItemSetContainerComponent: Component {
var centerInfoItem: InfoItem?
var rightInfoItem: InfoItem?
var captionItem: CaptionItem?
let inputPanel = ComponentView<Empty>()
let footerPanel = ComponentView<Empty>()
let inputPanelExternalState = MessageInputPanelComponent.ExternalState()
@ -375,6 +388,10 @@ public final class StoryItemSetContainerComponent: Component {
} else if self.displayReactions {
self.displayReactions = false
self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)))
} else if let captionItem = self.captionItem, captionItem.externalState.expandFraction > 0.0 {
if let captionItemView = captionItem.view.view as? StoryContentCaptionComponent.View {
captionItemView.collapse(transition: Transition(animation: .curve(duration: 0.4, curve: .spring)))
}
} else {
let point = recognizer.location(in: self)
@ -522,11 +539,25 @@ public final class StoryItemSetContainerComponent: Component {
)
footerPanelView.layer.animateAlpha(from: 0.0, to: footerPanelView.alpha, duration: 0.28)
}
if let captionItemView = self.captionItem?.view.view {
captionItemView.layer.animatePosition(
from: CGPoint(x: 0.0, y: self.bounds.height - captionItemView.frame.minY),
to: CGPoint(),
duration: 0.25,
timingFunction: kCAMediaTimingFunctionSpring,
additive: true
)
captionItemView.layer.animateAlpha(from: 0.0, to: captionItemView.alpha, duration: 0.28)
}
if let sourceView = transitionIn.sourceView {
let sourceLocalFrame = sourceView.convert(transitionIn.sourceRect, to: self)
let innerSourceLocalFrame = CGRect(origin: CGPoint(x: sourceLocalFrame.minX - self.contentContainerView.frame.minX, y: sourceLocalFrame.minY - self.contentContainerView.frame.minY), size: sourceLocalFrame.size)
if let centerInfoView = self.centerInfoItem?.view.view {
centerInfoView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
}
if let rightInfoView = self.rightInfoItem?.view.view {
if transitionIn.sourceCornerRadius != 0.0 {
let positionKeyframes: [CGPoint] = generateParabollicMotionKeyframes(from: CGPoint(x: innerSourceLocalFrame.center.x - rightInfoView.layer.position.x, y: innerSourceLocalFrame.center.y - rightInfoView.layer.position.y), to: CGPoint(), elevation: 0.0, duration: 0.3, curve: .spring, reverse: false)
@ -591,11 +622,26 @@ public final class StoryItemSetContainerComponent: Component {
)
footerPanelView.layer.animateAlpha(from: footerPanelView.alpha, to: 0.0, duration: 0.3, removeOnCompletion: false)
}
if let captionItemView = self.captionItem?.view.view {
captionItemView.layer.animatePosition(
from: CGPoint(),
to: CGPoint(x: 0.0, y: self.bounds.height - captionItemView.frame.minY),
duration: 0.3,
timingFunction: kCAMediaTimingFunctionSpring,
removeOnCompletion: false,
additive: true
)
captionItemView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
}
if let sourceView = transitionOut.destinationView {
let sourceLocalFrame = sourceView.convert(transitionOut.destinationRect, to: self)
let innerSourceLocalFrame = CGRect(origin: CGPoint(x: sourceLocalFrame.minX - self.contentContainerView.frame.minX, y: sourceLocalFrame.minY - self.contentContainerView.frame.minY), size: sourceLocalFrame.size)
if let centerInfoView = self.centerInfoItem?.view.view {
centerInfoView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
}
if let rightInfoView = self.rightInfoItem?.view.view {
if transitionOut.destinationIsAvatar {
let positionKeyframes: [CGPoint] = generateParabollicMotionKeyframes(from: innerSourceLocalFrame.center, to: rightInfoView.layer.position, elevation: 0.0, duration: 0.3, curve: .spring, reverse: true)
@ -619,7 +665,15 @@ public final class StoryItemSetContainerComponent: Component {
if let component = self.component, let visibleItemView = self.visibleItems[component.slice.item.id]?.view.view {
let innerScale = innerSourceLocalFrame.width / visibleItemView.bounds.width
let innerFromFrame = CGRect(origin: CGPoint(x: innerSourceLocalFrame.minX, y: innerSourceLocalFrame.minY), size: CGSize(width: innerSourceLocalFrame.width, height: visibleItemView.bounds.height * innerScale))
var adjustedInnerSourceLocalFrame = innerSourceLocalFrame
if !transitionOut.destinationIsAvatar {
let innerSourceSize = visibleItemView.bounds.size.aspectFilled(adjustedInnerSourceLocalFrame.size)
adjustedInnerSourceLocalFrame.origin.y += (adjustedInnerSourceLocalFrame.height - innerSourceSize.height) * 0.5
adjustedInnerSourceLocalFrame.size.height = innerSourceSize.height
}
let innerFromFrame = CGRect(origin: CGPoint(x: adjustedInnerSourceLocalFrame.minX, y: adjustedInnerSourceLocalFrame.minY), size: CGSize(width: adjustedInnerSourceLocalFrame.width, height: visibleItemView.bounds.height * innerScale))
visibleItemView.layer.animatePosition(
from: visibleItemView.layer.position,
@ -1017,9 +1071,6 @@ public final class StoryItemSetContainerComponent: Component {
self.centerInfoItem = nil
if let view = centerInfoItem.view.view {
view.removeFromSuperview()
/*view.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak view] _ in
view?.removeFromSuperview()
})*/
}
}
@ -1091,6 +1142,46 @@ public final class StoryItemSetContainerComponent: Component {
transition.setAlpha(view: inputPanelView, alpha: focusedItem?.isMy == true ? 0.0 : 1.0)
}
if let captionItem = self.captionItem, captionItem.itemId != component.slice.item.storyItem.id {
self.captionItem = nil
if let captionItemView = captionItem.view.view {
captionItemView.removeFromSuperview()
}
}
if !component.slice.item.storyItem.text.isEmpty {
var captionItemTransition = transition
let captionItem: CaptionItem
if let current = self.captionItem {
captionItem = current
} else {
if !transition.animation.isImmediate {
captionItemTransition = .immediate
}
captionItem = CaptionItem(itemId: component.slice.item.storyItem.id)
self.captionItem = captionItem
}
let captionSize = captionItem.view.update(
transition: captionItemTransition,
component: AnyComponent(StoryContentCaptionComponent(
externalState: captionItem.externalState,
text: component.slice.item.storyItem.text
)),
environment: {},
containerSize: CGSize(width: availableSize.width, height: contentFrame.height)
)
captionItem.view.parentState = state
let captionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentFrame.maxY - captionSize.height), size: captionSize)
if let captionItemView = captionItem.view.view {
if captionItemView.superview == nil {
self.addSubview(captionItemView)
}
captionItemTransition.setFrame(view: captionItemView, frame: captionFrame)
captionItemTransition.setAlpha(view: captionItemView, alpha: component.hideUI ? 0.0 : 1.0)
}
}
let reactionsAnchorRect = CGRect(origin: CGPoint(x: inputPanelFrame.maxX - 40.0, y: inputPanelFrame.minY + 9.0), size: CGSize(width: 32.0, height: 32.0)).insetBy(dx: -4.0, dy: -4.0)
var effectiveDisplayReactions = self.displayReactions
@ -1216,6 +1307,34 @@ public final class StoryItemSetContainerComponent: Component {
self.state?.updated(transition: Transition(animation: .curve(duration: 0.25, curve: .easeInOut)))
if let centerAnimation = reaction.centerAnimation {
/*let file = centerAnimation
var text = "."
loop: for attribute in file.attributes {
switch attribute {
case let .CustomEmoji(_, _, displayText, _):
text = displayText
break loop
default:
break
}
}*/
let message: EnqueueMessage = .message(
text: "",
attributes: [
//TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< 1, type: .CustomEmoji(stickerPack: nil, fileId: centerAnimation.fileId.id))])
],
inlineStickers: [:],//[centerAnimation.fileId: centerAnimation],
mediaReference: AnyMediaReference.standalone(media: reaction.activateAnimation),
replyToMessageId: nil,
replyToStoryId: StoryId(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id),
localGroupingKey: nil,
correlationId: nil,
bubbleUpEmojiOrStickersets: []
)
let _ = enqueueMessages(account: component.context.account, peerId: component.slice.peer.id, messages: [message]).start()
let presentationData = component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: component.theme)
component.presentController(UndoOverlayController(
presentationData: presentationData,
@ -1288,8 +1407,17 @@ public final class StoryItemSetContainerComponent: Component {
//transition.setAlpha(layer: self.bottomContentGradientLayer, alpha: inputPanelIsOverlay ? 1.0 : 0.0)
transition.setAlpha(layer: self.bottomContentGradientLayer, alpha: 0.0)
var normalDimAlpha: CGFloat = 0.0
if let captionItem = self.captionItem {
normalDimAlpha = captionItem.externalState.expandFraction
}
var dimAlpha: CGFloat = (inputPanelIsOverlay || self.inputPanelExternalState.isEditing) ? 1.0 : normalDimAlpha
if component.hideUI {
dimAlpha = 0.0
}
transition.setFrame(layer: self.contentDimLayer, frame: CGRect(origin: CGPoint(), size: contentFrame.size))
transition.setAlpha(layer: self.contentDimLayer, alpha: (inputPanelIsOverlay || self.inputPanelExternalState.isEditing) ? 1.0 : 0.0)
transition.setAlpha(layer: self.contentDimLayer, alpha: dimAlpha)
self.ignoreScrolling = true
transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: availableSize.width, height: availableSize.height)))

View File

@ -31,6 +31,7 @@ import LegacyInstantVideoController
import TelegramPresentationData
import ShareController
import ChatPresentationInterfaceState
import Postbox
final class StoryItemSetContainerSendMessage {
weak var attachmentController: AttachmentController?
@ -63,6 +64,7 @@ final class StoryItemSetContainerSendMessage {
guard let peerId = focusedItem.peerId else {
return
}
let focusedStoryId = StoryId(peerId: peerId, id: focusedItem.storyItem.id)
guard let inputPanelView = view.inputPanel.view as? MessageInputPanelComponent.View else {
return
}
@ -72,7 +74,7 @@ final class StoryItemSetContainerSendMessage {
let waveformBuffer = recordedAudioPreview.waveform.makeBitstream()
let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedAudioPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedAudioPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedAudioPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]
let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedAudioPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedAudioPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedAudioPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]
let _ = enqueueMessages(account: component.context.account, peerId: peerId, messages: messages).start()
@ -84,6 +86,7 @@ final class StoryItemSetContainerSendMessage {
component.context.engine.messages.enqueueOutgoingMessage(
to: peerId,
replyTo: nil,
storyId: StoryId(peerId: component.slice.peer.id, id: component.slice.item.storyItem.id),
content: .text(text)
)
inputPanelView.clearSendMessageInput()
@ -119,6 +122,7 @@ final class StoryItemSetContainerSendMessage {
guard let peerId = focusedItem.peerId else {
return
}
let focusedStoryId = StoryId(peerId: peerId, id: focusedItem.storyItem.id)
let _ = (component.context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)
)
@ -200,7 +204,7 @@ final class StoryItemSetContainerSendMessage {
let waveformBuffer: Data? = data.waveform
self.sendMessages(view: view, peer: peer, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
self.sendMessages(view: view, peer: peer, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
HapticFeedback().tap()
@ -335,6 +339,7 @@ final class StoryItemSetContainerSendMessage {
guard let peerId = focusedItem.peerId else {
return
}
let focusedStoryId = StoryId(peerId: peerId, id: focusedItem.storyItem.id)
guard let inputPanelView = view.inputPanel.view as? MessageInputPanelComponent.View else {
return
}
@ -564,6 +569,7 @@ final class StoryItemSetContainerSendMessage {
view: view,
peer: peer,
replyToMessageId: nil,
replyToStoryId: focusedStoryId,
saveEditedPhotos: dataSettings.storeEditedPhotos,
bannedSendPhotos: bannedSendPhotos,
bannedSendVideos: bannedSendVideos,
@ -582,7 +588,7 @@ final class StoryItemSetContainerSendMessage {
if !inputText.string.isEmpty {
self.clearInputText(view: view)
}
self.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: nil, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime, getAnimatedTransitionSource: getAnimatedTransitionSource, completion: completion)
self.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: nil, replyToStoryId: focusedStoryId, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime, getAnimatedTransitionSource: getAnimatedTransitionSource, completion: completion)
}
)
case .file:
@ -601,18 +607,18 @@ final class StoryItemSetContainerSendMessage {
return
}
attachmentController?.dismiss(animated: true)
self.presentFileGallery(view: view, peer: peer, replyMessageId: nil)
self.presentFileGallery(view: view, peer: peer, replyMessageId: nil, replyToStoryId: focusedStoryId)
}, presentFiles: { [weak self, weak view, weak attachmentController] in
guard let self, let view else {
return
}
attachmentController?.dismiss(animated: true)
self.presentICloudFileGallery(view: view, peer: peer, replyMessageId: nil)
self.presentICloudFileGallery(view: view, peer: peer, replyMessageId: nil, replyToStoryId: focusedStoryId)
}, send: { [weak view] mediaReference in
guard let view, let component = view.component else {
return
}
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = (enqueueMessages(account: component.context.account, peerId: peer.id, messages: [message.withUpdatedReplyToMessageId(nil)])
|> deliverOnMainQueue).start()
@ -659,7 +665,7 @@ final class StoryItemSetContainerSendMessage {
guard let self, let view else {
return
}
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
self.sendMessages(view: view, peer: peer, messages: [message])
})
completion(controller, controller.mediaPickerContext)
@ -695,7 +701,7 @@ final class StoryItemSetContainerSendMessage {
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
}
if peers.count > 1 {
var enqueueMessages: [EnqueueMessage] = []
@ -724,7 +730,7 @@ final class StoryItemSetContainerSendMessage {
}
if let media = media {
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
enqueueMessages.append(message)
}
}
@ -782,7 +788,7 @@ final class StoryItemSetContainerSendMessage {
if let textEnqueueMessage = textEnqueueMessage {
enqueueMessages.append(textEnqueueMessage)
}
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
self.sendMessages(view: view, peer: targetPeer, messages: self.transformEnqueueMessages(view: view, messages: enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime))
} else {
@ -801,7 +807,7 @@ final class StoryItemSetContainerSendMessage {
if let textEnqueueMessage = textEnqueueMessage {
enqueueMessages.append(textEnqueueMessage)
}
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: focusedStoryId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
self.sendMessages(view: view, peer: targetPeer, messages: self.transformEnqueueMessages(view: view, messages: enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime))
}
@ -904,6 +910,7 @@ final class StoryItemSetContainerSendMessage {
view: StoryItemSetContainerComponent.View,
peer: EnginePeer,
replyToMessageId: EngineMessage.Id?,
replyToStoryId: StoryId?,
subject: MediaPickerScreen.Subject = .assets(nil, .default),
saveEditedPhotos: Bool,
bannedSendPhotos: (Int32, Bool)?,
@ -922,7 +929,7 @@ final class StoryItemSetContainerSendMessage {
guard let self, let view else {
return
}
self.openCamera(view: view, peer: peer, replyToMessageId: replyToMessageId, cameraView: cameraView)
self.openCamera(view: view, peer: peer, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, cameraView: cameraView)
}
controller.presentWebSearch = { [weak self, weak view, weak controller] mediaGroups, activateOnDisplay in
guard let self, let view, let controller else {
@ -975,7 +982,7 @@ final class StoryItemSetContainerSendMessage {
present(controller, mediaPickerContext)
}
private func presentOldMediaPicker(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, fileMode: Bool, editingMedia: Bool, present: @escaping (AttachmentContainable, AttachmentMediaPickerContext) -> Void, completion: @escaping ([Any], Bool, Int32) -> Void) {
private func presentOldMediaPicker(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, replyToStoryId: StoryId?, fileMode: Bool, editingMedia: Bool, present: @escaping (AttachmentContainable, AttachmentMediaPickerContext) -> Void, completion: @escaping ([Any], Bool, Int32) -> Void) {
guard let component = view.component else {
return
}
@ -1040,14 +1047,14 @@ final class StoryItemSetContainerSendMessage {
}
legacyEnqueueWebSearchMessages(selectionState, editingState, enqueueChatContextResult: { [weak view] result in
if let strongSelf = self, let view {
strongSelf.enqueueChatContextResult(view: view, peer: peer, replyMessageId: replyMessageId, results: results, result: result, hideVia: true)
strongSelf.enqueueChatContextResult(view: view, peer: peer, replyMessageId: replyMessageId, storyId: replyToStoryId, results: results, result: result, hideVia: true)
}
}, enqueueMediaMessages: { [weak view] signals in
if let strongSelf = self, let view {
if editingMedia {
strongSelf.editMessageMediaWithLegacySignals(view: view, signals: signals)
} else {
strongSelf.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: replyMessageId, signals: signals, silentPosting: silentPosting)
strongSelf.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: replyMessageId, replyToStoryId: replyToStoryId, signals: signals, silentPosting: silentPosting)
}
}
})
@ -1110,8 +1117,8 @@ final class StoryItemSetContainerSendMessage {
})
}
private func presentFileGallery(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, editingMessage: Bool = false) {
self.presentOldMediaPicker(view: view, peer: peer, replyMessageId: replyMessageId, fileMode: true, editingMedia: editingMessage, present: { [weak view] c, _ in
private func presentFileGallery(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, replyToStoryId: StoryId?, editingMessage: Bool = false) {
self.presentOldMediaPicker(view: view, peer: peer, replyMessageId: replyMessageId, replyToStoryId: replyToStoryId, fileMode: true, editingMedia: editingMessage, present: { [weak view] c, _ in
view?.component?.controller()?.push(c)
}, completion: { [weak self, weak view] signals, silentPosting, scheduleTime in
guard let self, let view else {
@ -1120,12 +1127,12 @@ final class StoryItemSetContainerSendMessage {
if editingMessage {
self.editMessageMediaWithLegacySignals(view: view, signals: signals)
} else {
self.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: replyMessageId, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil)
self.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: replyMessageId, replyToStoryId: replyToStoryId, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil)
}
})
}
private func presentICloudFileGallery(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?) {
private func presentICloudFileGallery(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, replyToStoryId: StoryId?) {
guard let component = view.component else {
return
}
@ -1208,7 +1215,7 @@ final class StoryItemSetContainerSendMessage {
}
let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes)
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, replyToStoryId: replyToStoryId, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
messages.append(message)
}
if let _ = groupingKey, messages.count % 10 == 0 {
@ -1226,7 +1233,7 @@ final class StoryItemSetContainerSendMessage {
})
}
private func enqueueChatContextResult(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, results: ChatContextResultCollection, result: ChatContextResult, hideVia: Bool = false, closeMediaInput: Bool = false, silentPosting: Bool = false, resetTextInputState: Bool = true) {
private func enqueueChatContextResult(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyMessageId: EngineMessage.Id?, storyId: StoryId?, results: ChatContextResultCollection, result: ChatContextResult, hideVia: Bool = false, closeMediaInput: Bool = false, silentPosting: Bool = false, resetTextInputState: Bool = true) {
if !canSendMessagesToPeer(peer._asPeer()) {
return
}
@ -1235,7 +1242,7 @@ final class StoryItemSetContainerSendMessage {
guard let self, let view, let component = view.component else {
return
}
if component.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peer.id, threadId: nil, botId: results.botId, result: result, replyToMessageId: replyMessageId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime) {
if component.context.engine.messages.enqueueOutgoingMessageWithChatContextResult(to: peer.id, threadId: nil, botId: results.botId, result: result, replyToMessageId: replyMessageId, replyToStoryId: storyId, hideVia: hideVia, silentPosting: silentPosting, scheduleTime: scheduleTime) {
}
if let attachmentController = self.attachmentController {
@ -1378,7 +1385,7 @@ final class StoryItemSetContainerSendMessage {
}) as? TGCaptionPanelView
}
private func openCamera(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyToMessageId: EngineMessage.Id?, cameraView: TGAttachmentCameraView? = nil) {
private func openCamera(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyToMessageId: EngineMessage.Id?, replyToStoryId: StoryId?, cameraView: TGAttachmentCameraView? = nil) {
guard let component = view.component else {
return
}
@ -1440,7 +1447,7 @@ final class StoryItemSetContainerSendMessage {
guard let self, let view else {
return
}
self.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: replyToMessageId, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil)
self.enqueueMediaMessages(view: view, peer: peer, replyToMessageId: replyToMessageId, replyToStoryId: replyToStoryId, signals: signals, silentPosting: silentPosting, scheduleTime: scheduleTime > 0 ? scheduleTime : nil)
if !inputText.string.isEmpty {
self.clearInputText(view: view)
}
@ -1536,6 +1543,12 @@ final class StoryItemSetContainerSendMessage {
guard let component = view.component else {
return nil
}
let focusedItem = component.slice.item
guard let peerId = focusedItem.peerId else {
return nil
}
let focusedStoryId = StoryId(peerId: peerId, id: focusedItem.storyItem.id)
let theme = component.theme
return createPollController(context: component.context, updatedPresentationData: (component.context.sharedContext.currentPresentationData.with({ $0 }).withUpdated(theme: theme), component.context.sharedContext.presentationData |> map { $0.withUpdated(theme: theme) }), peer: peer, isQuiz: isQuiz, completion: { [weak self, weak view] poll in
guard let self, let view else {
@ -1567,6 +1580,7 @@ final class StoryItemSetContainerSendMessage {
deadlineTimeout: poll.deadlineTimeout
)),
replyToMessageId: nil,
replyToStoryId: focusedStoryId,
localGroupingKey: nil,
correlationId: nil,
bubbleUpEmojiOrStickersets: []
@ -1576,16 +1590,19 @@ final class StoryItemSetContainerSendMessage {
}
private func transformEnqueueMessages(view: StoryItemSetContainerComponent.View, messages: [EnqueueMessage], silentPosting: Bool, scheduleTime: Int32? = nil) -> [EnqueueMessage] {
let defaultReplyMessageId: EngineMessage.Id? = nil
var focusedStoryId: StoryId?
if let component = view.component, let peerId = component.slice.item.peerId {
focusedStoryId = StoryId(peerId: peerId, id: component.slice.item.storyItem.id)
}
return messages.map { message in
var message = message
if let defaultReplyMessageId = defaultReplyMessageId {
if let focusedStoryId {
switch message {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, _, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
if replyToMessageId == nil {
message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: replyToMessageId, replyToStoryId: focusedStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
}
case .forward:
break
@ -1639,7 +1656,7 @@ final class StoryItemSetContainerSendMessage {
}
}
private func enqueueMediaMessages(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyToMessageId: EngineMessage.Id?, signals: [Any]?, silentPosting: Bool, scheduleTime: Int32? = nil, getAnimatedTransitionSource: ((String) -> UIView?)? = nil, completion: @escaping () -> Void = {}) {
private func enqueueMediaMessages(view: StoryItemSetContainerComponent.View, peer: EnginePeer, replyToMessageId: EngineMessage.Id?, replyToStoryId: StoryId?, signals: [Any]?, silentPosting: Bool, scheduleTime: Int32? = nil, getAnimatedTransitionSource: ((String) -> UIView?)? = nil, completion: @escaping () -> Void = {}) {
guard let component = view.component else {
return
}
@ -1695,7 +1712,7 @@ final class StoryItemSetContainerSendMessage {
let messages = strongSelf.transformEnqueueMessages(view: view, messages: mappedMessages, silentPosting: silentPosting, scheduleTime: scheduleTime)
strongSelf.sendMessages(view: view, peer: peer, messages: messages.map { $0.withUpdatedReplyToMessageId(replyToMessageId) }, media: true)
strongSelf.sendMessages(view: view, peer: peer, messages: messages.map { $0.withUpdatedReplyToMessageId(replyToMessageId).withUpdatedReplyToStoryId(replyToStoryId) }, media: true)
if let _ = scheduleTime {
completion()

View File

@ -8,12 +8,12 @@ import TelegramCore
import Postbox
import StoryContainerScreen
public final class StoryContentContextImpl: StoryContentContext {
private struct StoryKey: Hashable {
var peerId: EnginePeer.Id
var id: Int32
}
public final class StoryContentContextImpl: StoryContentContext {
private final class PeerContext {
private let context: AccountContext
private let peerId: EnginePeer.Id
@ -533,3 +533,136 @@ public final class StoryContentContextImpl: StoryContentContext {
}
}
}
public final class SingleStoryContentContextImpl: StoryContentContext {
private let context: AccountContext
public private(set) var stateValue: StoryContentContextState?
public var state: Signal<StoryContentContextState, NoError> {
return self.statePromise.get()
}
private let statePromise = Promise<StoryContentContextState>()
private let updatedPromise = Promise<Void>()
public var updated: Signal<Void, NoError> {
return self.updatedPromise.get()
}
private var storyDisposable: Disposable?
private var requestedStoryKeys = Set<StoryKey>()
private var requestStoryDisposables = DisposableSet()
public init(
context: AccountContext,
storyId: StoryId
) {
self.context = context
self.storyDisposable = (combineLatest(queue: .mainQueue(),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: storyId.peerId)),
context.account.postbox.transaction { transaction -> Stories.StoredItem? in
return transaction.getStory(id: storyId)?.get(Stories.StoredItem.self)
}
)
|> deliverOnMainQueue).start(next: { [weak self] peer, item in
guard let self else {
return
}
if let item, case let .item(itemValue) = item, let media = itemValue.media, let peer {
let mappedItem = EngineStoryItem(
id: itemValue.id,
timestamp: itemValue.timestamp,
media: EngineMedia(media),
text: itemValue.text,
entities: itemValue.entities,
views: itemValue.views.flatMap { views in
return EngineStoryItem.Views(
seenCount: views.seenCount,
seenPeers: views.seenPeerIds.compactMap { id -> EnginePeer? in
return nil
}
)
},
privacy: nil
)
let stateValue = StoryContentContextState(
slice: StoryContentContextState.FocusedSlice(
peer: peer,
item: StoryContentItem(
id: AnyHashable(item.id),
position: 0,
component: AnyComponent(StoryItemContentComponent(
context: context,
peer: peer,
item: mappedItem
)),
centerInfoComponent: AnyComponent(StoryAuthorInfoComponent(
context: context,
peer: peer,
timestamp: item.timestamp
)),
rightInfoComponent: AnyComponent(StoryAvatarInfoComponent(
context: context,
peer: peer
)),
peerId: peer.id,
storyItem: mappedItem,
preload: nil,
delete: { [weak context] in
guard let context else {
return
}
let _ = context
},
markAsSeen: { [weak context] in
guard let context else {
return
}
let _ = context.engine.messages.markStoryAsSeen(peerId: peer.id, id: item.id).start()
},
hasLike: false,
isMy: peer.id == context.account.peerId
),
totalCount: 1,
previousItemId: nil,
nextItemId: nil
),
previousSlice: nil,
nextSlice: nil
)
if self.stateValue == nil || self.stateValue?.slice != stateValue.slice {
self.stateValue = stateValue
self.statePromise.set(.single(stateValue))
self.updatedPromise.set(.single(Void()))
}
} else {
let stateValue = StoryContentContextState(
slice: nil,
previousSlice: nil,
nextSlice: nil
)
if self.stateValue == nil || self.stateValue?.slice != stateValue.slice {
self.stateValue = stateValue
self.statePromise.set(.single(stateValue))
self.updatedPromise.set(.single(Void()))
}
}
})
}
deinit {
self.storyDisposable?.dispose()
self.requestStoryDisposables.dispose()
}
public func resetSideStates() {
}
public func navigate(navigation: StoryContentContextNavigation) {
}
}

View File

@ -10,6 +10,14 @@ import SwiftSignalKit
import TelegramPresentationData
public final class StoryPeerListComponent: Component {
public final class ExternalState {
public fileprivate(set) var collapsedWidth: CGFloat = 0.0
public init() {
}
}
public let externalState: ExternalState
public let context: AccountContext
public let theme: PresentationTheme
public let strings: PresentationStrings
@ -18,6 +26,7 @@ public final class StoryPeerListComponent: Component {
public let peerAction: (EnginePeer?) -> Void
public init(
externalState: ExternalState,
context: AccountContext,
theme: PresentationTheme,
strings: PresentationStrings,
@ -25,6 +34,7 @@ public final class StoryPeerListComponent: Component {
collapseFraction: CGFloat,
peerAction: @escaping (EnginePeer?) -> Void
) {
self.externalState = externalState
self.context = context
self.theme = theme
self.strings = strings
@ -105,8 +115,6 @@ public final class StoryPeerListComponent: Component {
private var sortedItems: [EngineStorySubscriptions.Item] = []
private var visibleItems: [EnginePeer.Id: VisibleItem] = [:]
private let title = ComponentView<Empty>()
private var component: StoryPeerListComponent?
private weak var state: EmptyComponentState?
@ -189,31 +197,10 @@ public final class StoryPeerListComponent: Component {
}
var hasStories: Bool = false
var storyCount = 0
if let storySubscriptions = component.storySubscriptions, !storySubscriptions.items.isEmpty {
hasStories = true
storyCount = storySubscriptions.items.count
}
let titleSpacing: CGFloat = 8.0
let titleText: String
if storyCount <= 0 {
titleText = "No Stories"
} else {
if storyCount == 1 {
titleText = "1 Story"
} else {
titleText = "\(storyCount) Stories"
}
}
let titleSize = self.title.update(
transition: .immediate,
component: AnyComponent(Text(text: titleText, font: Font.semibold(17.0), color: component.theme.rootController.navigationBar.primaryTextColor)),
environment: {},
containerSize: CGSize(width: itemLayout.containerSize.width, height: 100.0)
)
let _ = hasStories
let collapseStartIndex = 1
@ -223,44 +210,19 @@ public final class StoryPeerListComponent: Component {
var collapsedContentWidth: CGFloat = 0.0
if collapsedItemCount > 0 {
collapsedContentWidth = 1.0 * collapsedItemWidth + (collapsedItemDistance) * max(0.0, collapsedItemCount - 1.0)
collapsedContentWidth += titleSpacing
}
let collapseEndIndex = collapseStartIndex + max(0, Int(collapsedItemCount) - 1)
let titleOffset = collapsedContentWidth
collapsedContentWidth += titleSize.width
let collapsedContentOrigin: CGFloat
let collapsedItemOffsetY: CGFloat
let itemScale: CGFloat
if hasStories {
collapsedContentOrigin = floor((itemLayout.containerSize.width - collapsedContentWidth) * 0.5)
itemScale = 1.0
collapsedItemOffsetY = 0.0
} else {
collapsedContentOrigin = itemLayout.frame(at: 0).minX + 30.0
itemScale = 1.0//1.0 * (1.0 - component.collapseFraction) + 0.001 * component.collapseFraction
collapsedItemOffsetY = 16.0
}
let titleFrame = CGRect(origin: CGPoint(x: component.collapseFraction * (collapsedContentOrigin + titleOffset) + (1.0 - component.collapseFraction) * (itemLayout.containerSize.width), y: 19.0/* * component.collapseFraction + (1.0 - component.collapseFraction) * (-40.0)*/), size: titleSize)
if let titleView = self.title.view {
if titleView.superview == nil {
titleView.layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.scrollView.addSubview(titleView)
}
transition.setPosition(view: titleView, position: CGPoint(x: titleFrame.midX, y: titleFrame.midY))
transition.setBounds(view: titleView, bounds: CGRect(origin: CGPoint(), size: titleFrame.size))
var titleAlpha: CGFloat = pow(component.collapseFraction, 1.5)
if !hasStories {
titleAlpha = 0.0
}
transition.setAlpha(view: titleView, alpha: titleAlpha)
transition.setScale(view: titleView, scale: (component.collapseFraction) * 1.0 + (1.0 - component.collapseFraction) * 0.001)
}
component.externalState.collapsedWidth = collapsedContentWidth
let visibleBounds = self.scrollView.bounds
@ -389,11 +351,23 @@ public final class StoryPeerListComponent: Component {
self.visibleItems.removeValue(forKey: id)
}
transition.setFrame(view: self.collapsedButton, frame: CGRect(origin: CGPoint(x: 0.0, y: 8.0), size: CGSize(width: itemLayout.containerSize.width, height: itemLayout.containerSize.height - 8.0)))
transition.setFrame(view: self.collapsedButton, frame: CGRect(origin: CGPoint(x: collapsedContentOrigin, y: 6.0), size: CGSize(width: collapsedContentWidth, height: 44.0 - 4.0)))
}
override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
return super.hitTest(point, with: event)
guard let result = super.hitTest(point, with: event) else {
return nil
}
if self.collapsedButton.isUserInteractionEnabled {
if result !== self.collapsedButton {
return nil
}
} else {
if !result.isDescendant(of: self.scrollView) {
return nil
}
}
return result
}
func update(component: StoryPeerListComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: Transition) -> CGSize {

View File

@ -2435,7 +2435,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
if let threadId {
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))
}
return enqueueMessages(account: account, peerId: peerId, messages: [EnqueueMessage.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
return enqueueMessages(account: account, peerId: peerId, messages: [EnqueueMessage.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|> map { messageIds -> MessageId? in
if messageIds.isEmpty {
return nil

View File

@ -94,6 +94,8 @@ import ChatScheduleTimeController
import ICloudResources
import LegacyCamera
import LegacyInstantVideoController
import StoryContainerScreen
import StoryContentComponent
#if DEBUG
import os.signpost
@ -2063,9 +2065,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let peerId = strongSelf.chatLocation.peerId
if peerId?.namespace != Namespaces.Peer.SecretChat, let interactiveEmojis = strongSelf.chatDisplayNode.interactiveEmojis, interactiveEmojis.emojis.contains(text) {
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: text)), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: text)), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
} else {
strongSelf.sendMessages([.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: text, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
}
}, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer, bubbleUpEmojiOrStickersets in
guard let strongSelf = self else {
@ -2163,7 +2165,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
let messages: [EnqueueMessage] = [.message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)]
let messages: [EnqueueMessage] = [.message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)]
if silentPosting {
let transformedMessages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting)
strongSelf.sendMessages(transformedMessages)
@ -2192,7 +2194,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
strongSelf.sendMessages([.message(text: text, attributes: [TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< (text as NSString).length, type: .CustomEmoji(stickerPack: nil, fileId: file.fileId.id))])], inlineStickers: [file.fileId : file], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)], commit: false)
strongSelf.sendMessages([.message(text: text, attributes: [TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< (text as NSString).length, type: .CustomEmoji(stickerPack: nil, fileId: file.fileId.id))])], inlineStickers: [file.fileId : file], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)], commit: false)
}
} else {
strongSelf.interfaceInteraction?.insertText(NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: attribute]))
@ -2239,7 +2241,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}, nil)
var messages = [EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]
var messages = [EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: fileReference.abstract, replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]
if silentPosting {
messages = strongSelf.transformEnqueueMessages(messages, silentPosting: true)
strongSelf.sendMessages(messages)
@ -2591,7 +2593,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|> deliverOnMainQueue).start(next: { coordinate in
if let strongSelf = self {
if let coordinate = coordinate {
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaMap(latitude: coordinate.latitude, longitude: coordinate.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
} else {
strongSelf.present(textAlertController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, title: nil, text: strongSelf.presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})]), in: .window(.root))
}
@ -2615,7 +2617,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId)
|> deliverOnMainQueue).start(next: { peer in
if let peer = peer as? TelegramUser, let phone = peer.phone, !phone.isEmpty {
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaContact(firstName: peer.firstName ?? "", lastName: peer.lastName ?? "", phoneNumber: phone, peerId: peer.id, vCardData: nil)), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
}
})
}
@ -2659,7 +2661,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
strongSelf.sendMessages([.message(text: command, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: command, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: (postAsReply && messageId != nil) ? messageId! : nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
}
}, openInstantPage: { [weak self] message, associatedData in
if let strongSelf = self, strongSelf.isNodeLoaded, let navigationController = strongSelf.effectiveNavigationController, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) {
@ -2984,7 +2986,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_Send, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
if let strongSelf = self {
strongSelf.sendMessages([.message(text: command, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: command, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
}
}))
}
@ -4493,6 +4495,84 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self?.chatDisplayNode.dismissTextInput()
}, scrollToMessageId: { [weak self] index in
self?.chatDisplayNode.historyNode.scrollToMessage(index: index)
}, navigateToStory: { [weak self] message, storyId in
guard let self else {
return
}
let storyContent = SingleStoryContentContextImpl(context: self.context, storyId: storyId)
let _ = (storyContent.state
|> take(1)
|> deliverOnMainQueue).start(next: { [weak self] _ in
guard let self else {
return
}
var transitionIn: StoryContainerScreen.TransitionIn?
for i in 0 ..< 2 {
if transitionIn != nil {
break
}
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView {
if i == 0 {
if itemNode.item?.message.id != message.id {
return
}
}
if let result = itemNode.targetForStoryTransition(id: storyId) {
transitionIn = StoryContainerScreen.TransitionIn(
sourceView: result,
sourceRect: result.bounds,
sourceCornerRadius: 2.0
)
}
}
}
}
let storyContainerScreen = StoryContainerScreen(
context: self.context,
content: storyContent,
transitionIn: transitionIn,
transitionOut: { [weak self] peerId, storyIdValue in
guard let self, let storyIdId = storyIdValue.base as? Int32 else {
return nil
}
let storyId = StoryId(peerId: peerId, id: storyIdId)
var transitionOut: StoryContainerScreen.TransitionOut?
for i in 0 ..< 2 {
if transitionOut != nil {
break
}
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView {
if i == 0 {
if itemNode.item?.message.id != message.id {
return
}
}
if let result = itemNode.targetForStoryTransition(id: storyId) {
transitionOut = StoryContainerScreen.TransitionOut(
destinationView: result,
destinationRect: result.bounds,
destinationCornerRadius: 2.0,
destinationIsAvatar: false,
completed: {
}
)
}
}
}
}
return transitionOut
}
)
self.push(storyContainerScreen)
})
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: self.stickerSettings, presentationContext: ChatPresentationContext(context: context, backgroundNode: self.chatBackgroundNode))
controllerInteraction.enableFullTranslucency = context.sharedContext.energyUsageSettings.fullTranslucency
@ -7575,7 +7655,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var correlationIds: [Int64] = []
for message in messages {
switch message {
case let .message(_, _, _, _, _, _, correlationId, _):
case let .message(_, _, _, _, _, _, _, correlationId, _):
if let correlationId = correlationId {
correlationIds.append(correlationId)
}
@ -8877,7 +8957,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
strongSelf.sendMessages([.message(text: messageText, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: messageText, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.interfaceInteraction?.updateShowCommands { _ in
return false
}
@ -12663,7 +12743,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
private func editMessageMediaWithMessages(_ messages: [EnqueueMessage]) {
if let message = messages.first, case let .message(text, attributes, _, maybeMediaReference, _, _, _, _) = message, let mediaReference = maybeMediaReference {
if let message = messages.first, case let .message(text, attributes, _, maybeMediaReference, _, _, _, _, _) = message, let mediaReference = maybeMediaReference {
self.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
var entities: [MessageTextEntity] = []
for attribute in attributes {
@ -13182,7 +13262,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self, let peerId = strongSelf.chatLocation.peerId else {
return
}
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: mediaReference, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: strongSelf.transformEnqueueMessages([message]))
|> deliverOnMainQueue).start(next: { [weak self] _ in
if let strongSelf = self, strongSelf.presentationInterfaceState.subject != .scheduledMessages {
@ -13221,7 +13301,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
if let strongSelf = self {
strongSelf.chatDisplayNode.collapseInput()
@ -13256,7 +13336,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
textEnqueueMessage = .message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
}
if peers.count > 1 {
var enqueueMessages: [EnqueueMessage] = []
@ -13295,7 +13375,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
}, nil)
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
enqueueMessages.append(message)
}
}
@ -13361,7 +13441,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let textEnqueueMessage = textEnqueueMessage {
enqueueMessages.append(textEnqueueMessage)
}
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime))
} else {
let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in
@ -13386,7 +13466,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let textEnqueueMessage = textEnqueueMessage {
enqueueMessages.append(textEnqueueMessage)
}
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime))
}
}), completed: nil, cancelled: nil)
@ -13848,7 +13928,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes)
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
messages.append(message)
}
if let _ = groupingKey, messages.count % 10 == 0 {
@ -14211,7 +14291,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
if let strongSelf = self {
strongSelf.chatDisplayNode.collapseInput()
@ -14270,7 +14350,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
}, nil)
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
enqueueMessages.append(message)
}
}
@ -14331,7 +14411,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
}, nil)
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
strongSelf.sendMessages([message])
} else {
let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in
@ -14351,7 +14431,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
}, nil)
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
strongSelf.sendMessages([message])
}
}), completed: nil, cancelled: nil)
@ -14706,6 +14786,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
deadlineTimeout: poll.deadlineTimeout
)),
replyToMessageId: nil,
replyToStoryId: nil,
localGroupingKey: nil,
correlationId: nil,
bubbleUpEmojiOrStickersets: []
@ -14872,7 +14953,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let value = value {
self.present(UndoOverlayController(presentationData: self.presentationData, content: .dice(dice: dice, context: self.context, text: value, action: canSendMessagesToChat(self.presentationInterfaceState) ? self.presentationData.strings.Conversation_SendDice : nil), elevatedLayout: false, action: { [weak self] action in
if let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState), action == .undo {
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: dice.emoji)), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
}
return false
}), in: .current)
@ -14895,9 +14976,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let defaultReplyMessageId = defaultReplyMessageId {
switch message {
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
case let .message(text, attributes, inlineStickers, mediaReference, replyToMessageId, replyToStoryId, localGroupingKey, correlationId, bubbleUpEmojiOrStickersets):
if replyToMessageId == nil {
message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
message = .message(text: text, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, replyToMessageId: defaultReplyMessageId, replyToStoryId: replyToStoryId, localGroupingKey: localGroupingKey, correlationId: correlationId, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)
}
case .forward:
break
@ -15155,7 +15236,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
fileAttributes.append(.ImageSize(size: PixelDimensions(size)))
let media = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "image/webp", size: Int64(data.count), attributes: fileAttributes)
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
@ -15445,7 +15526,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}, usedCorrelationId ? correlationId : nil)
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])])
strongSelf.sendMessages([.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.compressedData.count), attributes: [.Audio(isVoice: true, duration: Int(data.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: strongSelf.presentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: [])])
strongSelf.recorderFeedback?.tap()
strongSelf.recorderFeedback = nil
@ -15542,7 +15623,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}, nil)
let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]
let messages: [EnqueueMessage] = [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: recordedMediaPreview.resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(recordedMediaPreview.fileSize), attributes: [.Audio(isVoice: true, duration: Int(recordedMediaPreview.duration), title: nil, performer: nil, waveform: waveformBuffer)])), replyToMessageId: self.presentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]
let transformedMessages: [EnqueueMessage]
if let silentPosting = silentPosting {
@ -16490,7 +16571,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
}
}

View File

@ -3181,7 +3181,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
let trimmedInputText = effectiveInputText.string.trimmingCharacters(in: .whitespacesAndNewlines)
let peerId = effectivePresentationInterfaceState.chatLocation.peerId
if peerId?.namespace != Namespaces.Peer.SecretChat, let interactiveEmojis = self.interactiveEmojis, interactiveEmojis.emojis.contains(trimmedInputText), effectiveInputText.attribute(ChatTextInputAttributes.customEmoji, at: 0, effectiveRange: nil) == nil {
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
} else {
let inputText = convertMarkdownToAttributes(effectiveInputText)
@ -3214,7 +3214,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
bubbleUpEmojiOrStickersets.removeAll()
}
messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: webpage.flatMap(AnyMediaReference.standalone), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
}
}

View File

@ -75,7 +75,8 @@ func chatHistoryEntriesForView(
associatedMessages: SimpleDictionary<MessageId, Message>(),
associatedMessageIds: [],
associatedMedia: [:],
associatedThreadInfo: nil
associatedThreadInfo: nil,
associatedStories: [:]
)
}
@ -391,7 +392,8 @@ func chatHistoryEntriesForView(
associatedMessages: message.associatedMessages,
associatedMessageIds: message.associatedMessageIds,
associatedMedia: message.associatedMedia,
associatedThreadInfo: message.associatedThreadInfo
associatedThreadInfo: message.associatedThreadInfo,
associatedStories: message.associatedStories
)
nextAdMessageId += 1
entries.append(.MessageEntry(updatedMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false)))

View File

@ -1956,7 +1956,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
associatedMessages: initialMessage.associatedMessages,
associatedMessageIds: initialMessage.associatedMessageIds,
associatedMedia: initialMessage.associatedMedia,
associatedThreadInfo: initialMessage.associatedThreadInfo
associatedThreadInfo: initialMessage.associatedThreadInfo,
associatedStories: initialMessage.associatedStories
)
self.nextPendingDynamicMessageId += 1

View File

@ -784,7 +784,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
let id = Int64.random(in: Int64.min ... Int64.max)
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: id), partialReference: nil, resource: LocalFileReferenceMediaResource(localFilePath: logPath, randomId: id), previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "application/text", size: nil, attributes: [.FileName(fileName: "CallStats.log")])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [message]).start()
}

View File

@ -1221,6 +1221,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
}
var replyMessage: Message?
var replyStory: StoryId?
for attribute in item.message.attributes {
if let attribute = attribute as? InlineBotMessageAttribute {
var inlineBotNameString: String?
@ -1246,12 +1247,14 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
} else {
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
}
} else if let attribute = attribute as? ReplyStoryAttribute {
replyStory = attribute.storyId
} else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty {
replyMarkup = attribute
}
}
var hasReply = replyMessage != nil
var hasReply = replyMessage != nil || replyStory != nil
if case let .peer(peerId) = item.chatLocation, (peerId == replyMessage?.id.peerId || item.message.threadId == 1), let channel = item.message.peers[item.message.id.peerId] as? TelegramChannel, channel.flags.contains(.isForum), item.message.associatedThreadInfo != nil {
if let threadId = item.message.threadId, let replyMessage = replyMessage, Int64(replyMessage.id.id) == threadId {
hasReply = false
@ -1271,13 +1274,14 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
))
}
if let replyMessage = replyMessage, hasReply {
if hasReply, (replyMessage != nil || replyStory != nil) {
replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments(
presentationData: item.presentationData,
strings: item.presentationData.strings,
context: item.context,
type: .standalone,
message: replyMessage,
story: replyStory,
parentMessage: item.message,
constrainedSize: CGSize(width: availableContentWidth, height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache,
@ -2098,6 +2102,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
return .optionalAction({
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId)
})
} else if let attribute = attribute as? ReplyStoryAttribute {
return .optionalAction({
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
})
}
}
}
@ -2858,6 +2866,22 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
return nil
}
override func targetForStoryTransition(id: StoryId) -> UIView? {
guard let item = self.item else {
return nil
}
for attribute in item.message.attributes {
if let attribute = attribute as? ReplyStoryAttribute {
if attribute.storyId == id {
if let replyInfoNode = self.replyInfoNode {
return replyInfoNode.mediaTransitionView()
}
}
}
}
return nil
}
override func unreadMessageRangeUpdated() {
self.updateVisibility()
}

View File

@ -1462,6 +1462,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
var inlineBotNameString: String?
var replyMessage: Message?
var replyStory: StoryId?
var replyMarkup: ReplyMarkupMessageAttribute?
var authorNameColor: UIColor?
@ -1477,6 +1478,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
} else {
replyMessage = firstMessage.associatedMessages[attribute.messageId]
}
} else if let attribute = attribute as? ReplyStoryAttribute {
replyStory = attribute.storyId
} else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty && !isPreview {
var isExtendedMedia = false
for media in firstMessage.media {
@ -1703,7 +1706,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
} else if let backgroundHiding, case .always = backgroundHiding {
initialDisplayHeader = false
} else {
if inlineBotNameString == nil && (ignoreForward || firstMessage.forwardInfo == nil) && replyMessage == nil {
if inlineBotNameString == nil && (ignoreForward || firstMessage.forwardInfo == nil) && replyMessage == nil && replyStory == nil {
if let first = contentPropertiesAndLayouts.first, first.1.hidesSimpleAuthorHeader && !ignoreNameHiding {
if let author = firstMessage.author as? TelegramChannel, case .group = author.info, author.id == firstMessage.id.peerId, !incoming {
} else {
@ -1770,7 +1773,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
if firstMessage.forwardInfo != nil {
displayHeader = true
}
if replyMessage != nil {
if replyMessage != nil || replyStory != nil {
displayHeader = true
}
if !displayHeader, case .peer = item.chatLocation, let channel = item.message.peers[item.message.id.peerId] as? TelegramChannel, channel.flags.contains(.isForum), item.message.associatedThreadInfo != nil {
@ -2002,7 +2005,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
headerSize.height += forwardInfoSizeApply.0.height
}
var hasReply = replyMessage != nil
var hasReply = replyMessage != nil || replyStory != nil
if !isInstantVideo, case let .peer(peerId) = item.chatLocation, (peerId == replyMessage?.id.peerId || item.message.threadId == 1), let channel = item.message.peers[item.message.id.peerId] as? TelegramChannel, channel.flags.contains(.isForum), item.message.associatedThreadInfo != nil {
if let threadId = item.message.threadId, let replyMessage = replyMessage, Int64(replyMessage.id.id) == threadId {
hasReply = false
@ -2034,7 +2037,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
}
}
if !isInstantVideo, let replyMessage = replyMessage, hasReply {
if !isInstantVideo, hasReply, (replyMessage != nil || replyStory != nil) {
if headerSize.height.isZero {
headerSize.height += 6.0
} else {
@ -2046,6 +2049,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
context: item.context,
type: .bubble(incoming: incoming),
message: replyMessage,
story: replyStory,
parentMessage: item.message,
constrainedSize: CGSize(width: maximumNodeWidth - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right, height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache,
@ -3650,6 +3654,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
return .optionalAction({
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId)
})
} else if let attribute = attribute as? ReplyStoryAttribute {
return .optionalAction({
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
})
}
}
}
@ -4505,6 +4513,22 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
return nil
}
override func targetForStoryTransition(id: StoryId) -> UIView? {
guard let item = self.item else {
return nil
}
for attribute in item.message.attributes {
if let attribute = attribute as? ReplyStoryAttribute {
if attribute.storyId == id {
if let replyInfoNode = self.replyInfoNode {
return replyInfoNode.mediaTransitionView()
}
}
}
}
return nil
}
override func unreadMessageRangeUpdated() {
for contentNode in self.contentNodes {
contentNode.unreadMessageRangeUpdated()

View File

@ -475,6 +475,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
context: item.context,
type: .standalone,
message: replyMessage,
story: nil,
parentMessage: item.message,
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache,
@ -1404,6 +1405,22 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
return nil
}
override func targetForStoryTransition(id: StoryId) -> UIView? {
guard let item = self.item else {
return nil
}
for attribute in item.message.attributes {
if let attribute = attribute as? ReplyStoryAttribute {
if attribute.storyId == id {
if let replyInfoNode = self.replyInfoNode {
return replyInfoNode.mediaTransitionView()
}
}
}
}
return nil
}
override func contentFrame() -> CGRect {
return self.interactiveVideoNode.frame
}

View File

@ -346,6 +346,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
context: item.context,
type: .standalone,
message: replyMessage,
story: nil,
parentMessage: item.message,
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache,

View File

@ -922,6 +922,10 @@ public class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol
return nil
}
public func targetForStoryTransition(id: StoryId) -> UIView? {
return nil
}
func getStatusNode() -> ASDisplayNode? {
return nil
}

View File

@ -27,7 +27,8 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
let strings: PresentationStrings
let context: AccountContext
let type: ChatMessageReplyInfoType
let message: Message
let message: Message?
let story: StoryId?
let parentMessage: Message
let constrainedSize: CGSize
let animationCache: AnimationCache?
@ -39,7 +40,8 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
strings: PresentationStrings,
context: AccountContext,
type: ChatMessageReplyInfoType,
message: Message,
message: Message?,
story: StoryId?,
parentMessage: Message,
constrainedSize: CGSize,
animationCache: AnimationCache?,
@ -51,6 +53,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
self.context = context
self.type = type
self.message = message
self.story = story
self.parentMessage = parentMessage
self.constrainedSize = constrainedSize
self.animationCache = animationCache
@ -104,10 +107,16 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
let titleFont = Font.medium(fontSize)
let textFont = Font.regular(fontSize)
let author = arguments.message.effectiveAuthor
var titleString = author.flatMap(EnginePeer.init)?.displayTitle(strings: arguments.strings, displayOrder: arguments.presentationData.nameDisplayOrder) ?? arguments.strings.User_DeletedAccount
var titleString: String
let textString: NSAttributedString
let isMedia: Bool
let isText: Bool
if let forwardInfo = arguments.message.forwardInfo, forwardInfo.flags.contains(.isImported) || arguments.parentMessage.forwardInfo != nil {
if let message = arguments.message {
let author = message.effectiveAuthor
titleString = author.flatMap(EnginePeer.init)?.displayTitle(strings: arguments.strings, displayOrder: arguments.presentationData.nameDisplayOrder) ?? arguments.strings.User_DeletedAccount
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) || arguments.parentMessage.forwardInfo != nil {
if let author = forwardInfo.author {
titleString = EnginePeer(author).displayTitle(strings: arguments.strings, displayOrder: arguments.presentationData.nameDisplayOrder)
} else if let authorSignature = forwardInfo.authorSignature {
@ -115,9 +124,29 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
}
}
let (textString, isMedia, isText) = descriptionStringForMessage(contentSettings: arguments.context.currentContentSettings.with { $0 }, message: EngineMessage(arguments.message), strings: arguments.strings, nameDisplayOrder: arguments.presentationData.nameDisplayOrder, dateTimeFormat: arguments.presentationData.dateTimeFormat, accountPeerId: arguments.context.account.peerId)
let (textStringValue, isMediaValue, isTextValue) = descriptionStringForMessage(contentSettings: arguments.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: arguments.strings, nameDisplayOrder: arguments.presentationData.nameDisplayOrder, dateTimeFormat: arguments.presentationData.dateTimeFormat, accountPeerId: arguments.context.account.peerId)
textString = textStringValue
isMedia = isMediaValue
isText = isTextValue
} else if let story = arguments.story {
if let authorPeer = arguments.parentMessage.peers[story.peerId] {
titleString = EnginePeer(authorPeer).displayTitle(strings: arguments.strings, displayOrder: arguments.presentationData.nameDisplayOrder)
} else {
titleString = arguments.strings.User_DeletedAccount
}
//TODO:localize
textString = NSAttributedString(string: "Story")
isMedia = true
isText = false
} else {
titleString = " "
textString = NSAttributedString(string: " ")
isMedia = true
isText = false
}
let placeholderColor: UIColor = arguments.parentMessage.effectivelyIncoming(arguments.context.account.peerId) ? arguments.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : arguments.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor
let placeholderColor: UIColor = arguments.message.effectivelyIncoming(arguments.context.account.peerId) ? arguments.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : arguments.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor
let titleColor: UIColor
let lineImage: UIImage?
let textColor: UIColor
@ -125,6 +154,8 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
var authorNameColor: UIColor?
let author = arguments.message?.effectiveAuthor
if [Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel].contains(arguments.parentMessage.id.peerId.namespace) && author?.id.namespace == Namespaces.Peer.CloudUser {
authorNameColor = author.flatMap { chatMessagePeerIdColors[Int(clamping: $0.id.id._internalGetInt64Value() % 7)] }
if let rawAuthorNameColor = authorNameColor {
@ -167,12 +198,12 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
let messageText: NSAttributedString
if isText {
var text = foldLineBreaks(arguments.message.text)
var messageEntities = arguments.message.textEntitiesAttribute?.entities ?? []
if isText, let message = arguments.message {
var text = foldLineBreaks(message.text)
var messageEntities = message.textEntitiesAttribute?.entities ?? []
if let translateToLanguage = arguments.associatedData.translateToLanguage, !text.isEmpty {
for attribute in arguments.message.attributes {
for attribute in message.attributes {
if let attribute = attribute as? TranslationMessageAttribute, !attribute.text.isEmpty, attribute.toLang == translateToLanguage {
text = attribute.text
messageEntities = attribute.entities
@ -193,7 +224,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
}
}
if entities.count > 0 {
messageText = stringWithAppliedEntities(trimToLineCount(text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: arguments.message)
messageText = stringWithAppliedEntities(trimToLineCount(text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message)
} else {
messageText = NSAttributedString(string: text, font: textFont, textColor: textColor)
}
@ -207,16 +238,16 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
var updatedMediaReference: AnyMediaReference?
var imageDimensions: CGSize?
var hasRoundImage = false
if !arguments.message.containsSecretMedia {
for media in arguments.message.media {
if let message = arguments.message, !message.containsSecretMedia {
for media in message.media {
if let image = media as? TelegramMediaImage {
updatedMediaReference = .message(message: MessageReference(arguments.message), media: image)
updatedMediaReference = .message(message: MessageReference(message), media: image)
if let representation = largestRepresentationForPhoto(image) {
imageDimensions = representation.dimensions.cgSize
}
break
} else if let file = media as? TelegramMediaFile, file.isVideo && !file.isVideoSticker {
updatedMediaReference = .message(message: MessageReference(arguments.message), media: file)
updatedMediaReference = .message(message: MessageReference(message), media: file)
if let dimensions = file.dimensions {
imageDimensions = dimensions.cgSize
@ -229,6 +260,23 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
break
}
}
} else if let story = arguments.story, let storyPeer = arguments.parentMessage.peers[story.peerId], let storyItem = arguments.parentMessage.associatedStories[story] {
if let itemValue = storyItem.get(Stories.StoredItem.self), case let .item(item) = itemValue, let peerReference = PeerReference(storyPeer) {
if let image = item.media as? TelegramMediaImage {
updatedMediaReference = .story(peer: peerReference, id: story.id, media: image)
if let representation = largestRepresentationForPhoto(image) {
imageDimensions = representation.dimensions.cgSize
}
} else if let file = item.media as? TelegramMediaFile, file.isVideo && !file.isVideoSticker {
updatedMediaReference = .story(peer: peerReference, id: story.id, media: file)
if let dimensions = file.dimensions {
imageDimensions = dimensions.cgSize
} else if let representation = largestImageRepresentation(file.previewRepresentations), !file.isSticker {
imageDimensions = representation.dimensions.cgSize
}
}
}
}
var imageTextInset: CGFloat = 0.0
@ -268,17 +316,28 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
mediaUpdated = true
}
let hasSpoiler = arguments.message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute })
let hasSpoiler: Bool
if let message = arguments.message {
hasSpoiler = message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute })
} else {
hasSpoiler = false
}
var updateImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>?
var mediaUserLocation: MediaResourceUserLocation = .other
if let message = arguments.message {
mediaUserLocation = .peer(message.id.peerId)
}
if let updatedMediaReference = updatedMediaReference, mediaUpdated && imageDimensions != nil {
if let imageReference = updatedMediaReference.concrete(TelegramMediaImage.self) {
updateImageSignal = chatMessagePhotoThumbnail(account: arguments.context.account, userLocation: .peer(arguments.message.id.peerId), photoReference: imageReference, blurred: hasSpoiler)
updateImageSignal = chatMessagePhotoThumbnail(account: arguments.context.account, userLocation: mediaUserLocation, photoReference: imageReference, blurred: hasSpoiler)
} else if let fileReference = updatedMediaReference.concrete(TelegramMediaFile.self) {
if fileReference.media.isVideo {
updateImageSignal = chatMessageVideoThumbnail(account: arguments.context.account, userLocation: .peer(arguments.message.id.peerId), fileReference: fileReference, blurred: hasSpoiler)
updateImageSignal = chatMessageVideoThumbnail(account: arguments.context.account, userLocation: mediaUserLocation, fileReference: fileReference, blurred: hasSpoiler)
} else if let iconImageRepresentation = smallestImageRepresentation(fileReference.media.previewRepresentations) {
updateImageSignal = chatWebpageSnippetFile(account: arguments.context.account, userLocation: .peer(arguments.message.id.peerId), mediaReference: fileReference.abstract, representation: iconImageRepresentation)
updateImageSignal = chatWebpageSnippetFile(account: arguments.context.account, userLocation: mediaUserLocation, mediaReference: fileReference.abstract, representation: iconImageRepresentation)
}
}
}
@ -321,7 +380,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
if let applyImage = applyImage {
let imageNode = applyImage()
if node.imageNode == nil {
imageNode.isLayerBacked = !smartInvertColorsEnabled()
imageNode.isLayerBacked = false//!smartInvertColorsEnabled()
node.addSubnode(imageNode)
node.imageNode = imageNode
}
@ -334,7 +393,9 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
imageNode.removeFromSupernode()
node.imageNode = nil
}
node.imageNode?.captureProtected = arguments.message.isCopyProtected()
if let message = arguments.message {
node.imageNode?.captureProtected = message.isCopyProtected()
}
titleNode.frame = CGRect(origin: CGPoint(x: leftInset - textInsets.left - 2.0, y: spacing - textInsets.top + 1.0), size: titleLayout.size)
@ -478,4 +539,11 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
return offset
}
}
func mediaTransitionView() -> UIView? {
if let imageNode = self.imageNode {
return imageNode.view
}
return nil
}
}

View File

@ -682,6 +682,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
context: item.context,
type: .standalone,
message: replyMessage,
story: nil,
parentMessage: item.message,
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache,
@ -1838,6 +1839,22 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
return nil
}
override func targetForStoryTransition(id: StoryId) -> UIView? {
guard let item = self.item else {
return nil
}
for attribute in item.message.attributes {
if let attribute = attribute as? ReplyStoryAttribute {
if attribute.storyId == id {
if let replyInfoNode = self.replyInfoNode {
return replyInfoNode.mediaTransitionView()
}
}
}
}
return nil
}
override func contentFrame() -> CGRect {
return self.imageNode.frame
}

View File

@ -560,6 +560,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
}, scrollToMessageId: { _ in
}, navigateToStory: { _, _ in
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: self.backgroundNode))
self.controllerInteraction = controllerInteraction

View File

@ -114,7 +114,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
peers[peer.id] = peer
let action = TelegramMediaActionType.titleUpdated(title: new)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeAbout(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -145,14 +145,14 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
let peers = SimpleDictionary<PeerId, Peer>()
let attributes: [MessageAttribute] = []
let prevMessage = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prev, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let prevMessage = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prev, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: new, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: new, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousDescription(prevMessage) : nil)
}
case let .changeUsername(prev, new):
@ -183,7 +183,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var previousAttributes: [MessageAttribute] = []
@ -201,8 +201,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)]))
}
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil)
}
case let .changeUsernames(prev, new):
@ -233,7 +233,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action: TelegramMediaActionType = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var previousAttributes: [MessageAttribute] = []
@ -270,8 +270,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
attributes.append(TextEntitiesMessageAttribute(entities: [MessageTextEntity(range: 0 ..< text.count, type: .Italic)]))
}
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let prevMessage = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: prevText, attributes: previousAttributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.isEmpty ? .eventLogPreviousLink(prevMessage) : nil)
}
case let .changePhoto(_, new):
@ -290,7 +290,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.photoUpdated(image: photo)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleInvites(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -317,7 +317,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleSignatures(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -344,7 +344,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .updatePinned(message):
switch self.id.contentIndex {
@ -375,7 +375,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
if let message = message {
@ -393,7 +393,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
} else {
var peers = SimpleDictionary<PeerId, Peer>()
@ -415,7 +415,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 0), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
}
@ -460,7 +460,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -477,7 +477,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: filterOriginalMessageFlags(message), read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: !prev.text.isEmpty || !message.text.isEmpty ? .eventLogPreviousMessage(filterOriginalMessageFlags(prev)) : nil)
}
case let .deleteMessage(message):
@ -503,7 +503,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -530,7 +530,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
if let peer = self.entry.peers[self.entry.event.peerId] {
peers[peer.id] = peer
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: message.id.id), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: message.id.id), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case .participantJoin, .participantLeave:
@ -548,7 +548,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
} else {
action = TelegramMediaActionType.removedMembers(peerIds: [self.entry.event.peerId])
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantInvite(participant):
var peers = SimpleDictionary<PeerId, Peer>()
@ -565,7 +565,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action: TelegramMediaActionType
action = TelegramMediaActionType.addedMembers(peerIds: [participant.peer.id])
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantToggleBan(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -696,7 +696,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantToggleAdmin(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -930,7 +930,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeStickerPack(_, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -959,7 +959,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .togglePreHistoryHidden(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -989,7 +989,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .updateDefaultBannedRights(prev, new):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1048,7 +1048,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: attributes, media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .pollStopped(message):
switch self.id.contentIndex {
@ -1076,7 +1076,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -1093,7 +1093,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.author, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: filterOriginalMessageFlags(message), read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil), additionalContent: nil)
}
case let .linkedPeerUpdated(previous, updated):
@ -1149,7 +1149,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeGeoLocation(_, updated):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1171,12 +1171,12 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let mediaMap = TelegramMediaMap(latitude: updated.latitude, longitude: updated.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: text, attributes: [], media: [mediaMap], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
} else {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case let .updateSlowmode(_, newValue):
@ -1207,7 +1207,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .startGroupCall, .endGroupCall:
var peers = SimpleDictionary<PeerId, Peer>()
@ -1244,7 +1244,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .groupCallUpdateParticipantMuteStatus(participantId, isMuted):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1278,7 +1278,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .updateGroupCallSettings(joinMuted):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1307,7 +1307,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .groupCallUpdateParticipantVolume(participantId, volume):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1338,7 +1338,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .deleteExportedInvitation(invite):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1364,7 +1364,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .revokeExportedInvitation(invite):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1390,7 +1390,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .editExportedInvitation(_, updatedInvite):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1416,7 +1416,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantJoinedViaInvite(invite, joinedViaFolderLink):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1447,7 +1447,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeHistoryTTL(_, updatedValue):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1478,7 +1478,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeAvailableReactions(_, updatedValue):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1520,7 +1520,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .changeTheme(_, updatedValue):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1551,7 +1551,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .participantJoinByRequest(invite, approvedBy):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1591,7 +1591,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleCopyProtection(value):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1618,7 +1618,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .sendMessage(message):
switch self.id.contentIndex {
@ -1643,7 +1643,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.headerStableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: 1), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case .content:
var peers = SimpleDictionary<PeerId, Peer>()
@ -1660,7 +1660,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
}
}
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: message.effectiveAuthor, text: message.text, attributes: attributes, media: message.media, peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
case let .createTopic(info):
@ -1680,7 +1680,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
return []
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .deleteTopic(info):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1701,7 +1701,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .editTopic(prevInfo, newInfo):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1780,7 +1780,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .pinTopic(prevInfo, newInfo):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1818,7 +1818,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleForum(isForum):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1839,7 +1839,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
case let .toggleAntiSpam(isEnabled):
var peers = SimpleDictionary<PeerId, Peer>()
@ -1860,7 +1860,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
}, to: &text, entities: &entities)
let action = TelegramMediaActionType.customText(text: text, entities: entities)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: self.entry.stableId, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(bitPattern: self.entry.stableId)), globallyUniqueId: self.entry.event.id, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: self.entry.event.date, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: author, text: "", attributes: [], media: [TelegramMediaAction(action: action)], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
return ChatMessageItem(presentationData: self.presentationData, context: context, chatLocation: .peer(id: peer.id), associatedData: ChatMessageItemAssociatedData(automaticDownloadPeerType: .channel, automaticDownloadPeerId: nil, automaticDownloadNetworkType: .cellular, isRecentActions: true, availableReactions: nil, defaultReaction: nil, isPremium: false, accountPeer: nil), controllerInteraction: controllerInteraction, content: .message(message: message, read: true, selection: .none, attributes: ChatMessageEntryAttributes(), location: nil))
}
}

View File

@ -292,7 +292,7 @@ final class ContactMultiselectionControllerNode: ASDisplayNode {
combinedInsets.right += layout.safeInsets.right
let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition)
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: layout.size, insets: combinedInsets, headerInsets: headerInsets, duration: duration, curve: curve)
chatsNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, visibleTopInset: updateSizeAndInsets.insets.top, originalTopInset: updateSizeAndInsets.insets.top, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0)
chatsNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, visibleTopInset: updateSizeAndInsets.insets.top, originalTopInset: updateSizeAndInsets.insets.top, storiesInset: 0.0, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0)
}
self.contentNode.node.frame = CGRect(origin: CGPoint(), size: layout.size)

View File

@ -67,7 +67,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
params.dismissInput()
let controllerParams = LocationViewParams(sendLiveLocation: { location in
let outMessage: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
let outMessage: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: location), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
params.enqueueMessage(outMessage)
}, stopLiveLocation: { messageId in
params.context.liveLocationManager?.cancelLiveLocation(peerId: messageId?.peerId ?? params.message.id.peerId)

View File

@ -169,6 +169,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
}, scrollToMessageId: { _ in
}, navigateToStory: { _, _ in
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil))
self.dimNode = ASDisplayNode()

View File

@ -2837,6 +2837,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
}, scrollToMessageId: { _ in
}, navigateToStory: { _, _ in
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil))
self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().start(next: { [weak self] ids in
@ -6193,7 +6194,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
if case let .user(peer) = peer, let _ = peer.botInfo {
strongSelf.activeActionDisposable.set(strongSelf.context.engine.privacy.requestUpdatePeerIsBlocked(peerId: peer.id, isBlocked: block).start())
if !block {
let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: "/start", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
if let navigationController = strongSelf.controller?.navigationController as? NavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer))))
}
@ -6618,7 +6619,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
case .help:
text = "/help"
}
let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
let _ = enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: [.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
if let peer = strongSelf.data?.peer, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(EnginePeer(peer))))
@ -6807,7 +6808,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, openPeer: { _ in
}, showAll: false)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil)
let message = Message(stableId: 0, stableVersion: 0, id: MessageId(peerId: peer.id, namespace: 0, id: 0), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 0, flags: [], tags: [], globalTags: [], localTags: [], forwardInfo: nil, author: peer, text: "", attributes: [], media: [map], peers: SimpleDictionary(), associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
let controller = LocationViewController(context: context, updatedPresentationData: self.controller?.updatedPresentationData, subject: EngineMessage(message), params: controllerParams)
self.controller?.push(controller)
@ -8235,7 +8236,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
result.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
}
}
}

View File

@ -948,7 +948,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
if let mainContainerNode = self.mainContainerNode {
transition.updateFrame(node: mainContainerNode, frame: CGRect(origin: CGPoint(), size: layout.size))
mainContainerNode.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: actualNavigationBarHeight, originalNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: navigationBarHeight, insets: insets, isReorderingFilters: false, isEditing: false, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0, transition: transition)
mainContainerNode.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: actualNavigationBarHeight, originalNavigationHeight: navigationBarHeight, cleanNavigationBarHeight: navigationBarHeight, insets: insets, isReorderingFilters: false, isEditing: false, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0, storiesInset: 0.0, transition: transition)
}
if let requestPeerTypes = self.requestPeerType, let requestPeerType = requestPeerTypes.first {
@ -1062,7 +1062,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, headerInsets: headerInsets, duration: duration, curve: curve)
if let chatListNode = self.chatListNode {
chatListNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, visibleTopInset: updateSizeAndInsets.insets.top, originalTopInset: updateSizeAndInsets.insets.top, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0)
chatListNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets, visibleTopInset: updateSizeAndInsets.insets.top, originalTopInset: updateSizeAndInsets.insets.top, storiesInset: 0.0, inlineNavigationLocation: nil, inlineNavigationTransitionFraction: 0.0)
}
if let contactListNode = self.contactListNode {

View File

@ -1368,7 +1368,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
if !found {
let controllerParams = LocationViewParams(sendLiveLocation: { location in
//let outMessage: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: location), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)
//let outMessage: EnqueueMessage = .message(text: "", attributes: [], mediaReference: .standalone(media: location), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil)
// params.enqueueMessage(outMessage)
}, stopLiveLocation: { messageId in
if let messageId = messageId {
@ -1536,6 +1536,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {
}, scrollToMessageId: { _ in
}, navigateToStory: { _, _ in
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: backgroundNode as? WallpaperBackgroundNode))

View File

@ -83,11 +83,17 @@ private final class DownloadedMediaStoreContext {
} else {
let peerTypeValue: MediaAutoSaveSettings.PeerType
switch peer {
case .user, .secretChat:
case .user:
peerTypeValue = .users
case .secretChat:
return false
case .legacyGroup:
peerTypeValue = .groups
case let .channel(channel):
if channel.flags.contains(.copyProtectionEnabled) {
return false
}
if case .broadcast = channel.info {
peerTypeValue = .channels
} else {

View File

@ -199,17 +199,17 @@ final class WatchSendMessageHandler: WatchRequestHandler {
if args.replyToMid != 0, let peerId = peerId {
replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: args.replyToMid)
}
messageSignal = .single((.message(text: args.text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId))
messageSignal = .single((.message(text: args.text, attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId))
} else if let args = subscription as? TGBridgeSendLocationMessageSubscription, let location = args.location {
let peerId = makePeerIdFromBridgeIdentifier(args.peerId)
let map = TelegramMediaMap(latitude: location.latitude, longitude: location.longitude, heading: nil, accuracyRadius: nil, geoPlace: nil, venue: makeVenue(from: location.venue), liveBroadcastingTimeout: nil, liveProximityNotificationRadius: nil)
messageSignal = .single((.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: map), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId))
messageSignal = .single((.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: map), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId))
} else if let args = subscription as? TGBridgeSendStickerMessageSubscription {
let peerId = makePeerIdFromBridgeIdentifier(args.peerId)
messageSignal = mediaForSticker(documentId: args.document.documentId, account: context.account)
|> map({ media -> (EnqueueMessage?, PeerId?) in
if let media = media {
return (.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId)
return (.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []), peerId)
} else {
return (nil, nil)
}
@ -720,7 +720,7 @@ final class WatchAudioHandler: WatchRequestHandler {
replyMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToMid)
}
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
let _ = enqueueMessages(account: context.account, peerId: peerId, messages: [.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: randomId), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: "audio/ogg", size: Int64(data.count), attributes: [.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])), replyToMessageId: replyMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]).start()
}
})
} else {