mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-03 21:16:35 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios
This commit is contained in:
commit
ddda0f35ac
@ -31,7 +31,7 @@ public final class OpenChatMessageParams {
|
|||||||
public let modal: Bool
|
public let modal: Bool
|
||||||
public let dismissInput: () -> Void
|
public let dismissInput: () -> Void
|
||||||
public let present: (ViewController, Any?) -> Void
|
public let present: (ViewController, Any?) -> Void
|
||||||
public let transitionNode: (MessageId, Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
public let transitionNode: (MessageId, Media, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
public let addToTransitionSurface: (UIView) -> Void
|
public let addToTransitionSurface: (UIView) -> Void
|
||||||
public let openUrl: (String) -> Void
|
public let openUrl: (String) -> Void
|
||||||
public let openPeer: (Peer, ChatControllerInteractionNavigateToPeer) -> Void
|
public let openPeer: (Peer, ChatControllerInteractionNavigateToPeer) -> Void
|
||||||
@ -60,7 +60,7 @@ public final class OpenChatMessageParams {
|
|||||||
modal: Bool = false,
|
modal: Bool = false,
|
||||||
dismissInput: @escaping () -> Void,
|
dismissInput: @escaping () -> Void,
|
||||||
present: @escaping (ViewController, Any?) -> Void,
|
present: @escaping (ViewController, Any?) -> Void,
|
||||||
transitionNode: @escaping (MessageId, Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?,
|
transitionNode: @escaping (MessageId, Media, Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?,
|
||||||
addToTransitionSurface: @escaping (UIView) -> Void,
|
addToTransitionSurface: @escaping (UIView) -> Void,
|
||||||
openUrl: @escaping (String) -> Void,
|
openUrl: @escaping (String) -> Void,
|
||||||
openPeer: @escaping (Peer, ChatControllerInteractionNavigateToPeer) -> Void,
|
openPeer: @escaping (Peer, ChatControllerInteractionNavigateToPeer) -> Void,
|
||||||
|
|||||||
@ -1253,7 +1253,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let storyContent = StoryContentContextImpl(context: self.context, includeHidden: false, focusedPeerId: peerId, singlePeer: false)
|
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: peerId, singlePeer: false)
|
||||||
let _ = (storyContent.state
|
let _ = (storyContent.state
|
||||||
|> filter { $0.slice != nil }
|
|> filter { $0.slice != nil }
|
||||||
|> take(1)
|
|> take(1)
|
||||||
@ -1744,7 +1744,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|> distinctUntilChanged
|
|> distinctUntilChanged
|
||||||
|
|
||||||
self.preloadStorySubscriptionsDisposable = (combineLatest(queue: .mainQueue(),
|
self.preloadStorySubscriptionsDisposable = (combineLatest(queue: .mainQueue(),
|
||||||
self.context.engine.messages.preloadStorySubscriptions(includeHidden: false),
|
self.context.engine.messages.preloadStorySubscriptions(isHidden: false),
|
||||||
self.context.sharedContext.automaticMediaDownloadSettings,
|
self.context.sharedContext.automaticMediaDownloadSettings,
|
||||||
automaticDownloadNetworkType
|
automaticDownloadNetworkType
|
||||||
)
|
)
|
||||||
@ -1790,7 +1790,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.preloadStoryResourceDisposables.removeValue(forKey: id)
|
self.preloadStoryResourceDisposables.removeValue(forKey: id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(includeHidden: false)
|
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: false)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
@ -2391,7 +2391,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let storyContent = StoryContentContextImpl(context: self.context, includeHidden: false, focusedPeerId: peer?.id, singlePeer: false)
|
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: peer?.id, singlePeer: false)
|
||||||
let _ = (storyContent.state
|
let _ = (storyContent.state
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
||||||
|
|||||||
@ -2069,7 +2069,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
interaction.dismissInput()
|
interaction.dismissInput()
|
||||||
}, present: { c, a in
|
}, present: { c, a in
|
||||||
interaction.present(c, a)
|
interaction.present(c, a)
|
||||||
}, transitionNode: { messageId, media in
|
}, transitionNode: { messageId, media, _ in
|
||||||
return transitionNodeImpl?(messageId, EngineMedia(media))
|
return transitionNodeImpl?(messageId, EngineMedia(media))
|
||||||
}, addToTransitionSurface: { view in
|
}, addToTransitionSurface: { view in
|
||||||
addToTransitionSurfaceImpl?(view)
|
addToTransitionSurfaceImpl?(view)
|
||||||
@ -2204,12 +2204,12 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
interaction.dismissInput()
|
interaction.dismissInput()
|
||||||
}, present: { c, a in
|
}, present: { c, a in
|
||||||
interaction.present(c, a)
|
interaction.present(c, a)
|
||||||
}, transitionNode: { messageId, media in
|
}, transitionNode: { messageId, media, _ in
|
||||||
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.listNode.forEachItemNode { itemNode in
|
strongSelf.listNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ListMessageNode {
|
if let itemNode = itemNode as? ListMessageNode {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3031,7 +3031,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||||||
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
self.listNode.forEachItemNode { itemNode in
|
self.listNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ListMessageNode {
|
if let itemNode = itemNode as? ListMessageNode {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media._asMedia()) {
|
if let result = itemNode.transitionNode(id: messageId, media: media._asMedia(), adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -515,7 +515,7 @@ public class ContactsController: ViewController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let storyContent = StoryContentContextImpl(context: self.context, includeHidden: true, focusedPeerId: peer?.id, singlePeer: false)
|
let storyContent = StoryContentContextImpl(context: self.context, isHidden: true, focusedPeerId: peer?.id, singlePeer: false)
|
||||||
let _ = (storyContent.state
|
let _ = (storyContent.state
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
||||||
|
|||||||
@ -227,7 +227,7 @@ final class ContactsControllerNode: ASDisplayNode {
|
|||||||
return self.contentScrollingEnded(listView: listView)
|
return self.contentScrollingEnded(listView: listView)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(includeHidden: true)
|
self.storySubscriptionsDisposable = (self.context.engine.messages.storySubscriptions(isHidden: true)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -1398,7 +1398,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func transitionNode(id: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if let item = self.item, let message = item.message, message.id == id, self.iconImageNode.supernode != nil {
|
if let item = self.item, let message = item.message, message.id == id, self.iconImageNode.supernode != nil {
|
||||||
let iconImageNode = self.iconImageNode
|
let iconImageNode = self.iconImageNode
|
||||||
return (self.iconImageNode, self.iconImageNode.bounds, { [weak iconImageNode] in
|
return (self.iconImageNode, self.iconImageNode.bounds, { [weak iconImageNode] in
|
||||||
|
|||||||
@ -28,7 +28,7 @@ public class ListMessageNode: ListViewItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func transitionNode(id: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -775,7 +775,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override public func transitionNode(id: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override public func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if let item = self.item, item.message?.id == id, self.iconImageNode.supernode != nil {
|
if let item = self.item, item.message?.id == id, self.iconImageNode.supernode != nil {
|
||||||
let iconImageNode = self.iconImageNode
|
let iconImageNode = self.iconImageNode
|
||||||
return (self.iconImageNode, self.iconImageNode.bounds, { [weak iconImageNode] in
|
return (self.iconImageNode, self.iconImageNode.bounds, { [weak iconImageNode] in
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public enum PostboxStorySubscriptionsKey: Int32 {
|
public enum PostboxStorySubscriptionsKey: Int32 {
|
||||||
case all = 0
|
case hidden = 0
|
||||||
case filtered = 1
|
case filtered = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ private func presentLiveLocationController(context: AccountContext, peerId: Peer
|
|||||||
controller?.view.endEditing(true)
|
controller?.view.endEditing(true)
|
||||||
}, present: { c, a in
|
}, present: { c, a in
|
||||||
controller?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
controller?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
||||||
}, transitionNode: { _, _ in
|
}, transitionNode: { _, _, _ in
|
||||||
return nil
|
return nil
|
||||||
}, addToTransitionSurface: { _ in
|
}, addToTransitionSurface: { _ in
|
||||||
}, openUrl: { _ in
|
}, openUrl: { _ in
|
||||||
|
|||||||
@ -975,7 +975,7 @@ public class Account {
|
|||||||
let networkStatsContext: NetworkStatsContext
|
let networkStatsContext: NetworkStatsContext
|
||||||
|
|
||||||
public let filteredStorySubscriptionsContext: StorySubscriptionsContext?
|
public let filteredStorySubscriptionsContext: StorySubscriptionsContext?
|
||||||
public let allStorySubscriptionsContext: StorySubscriptionsContext?
|
public let hiddenStorySubscriptionsContext: StorySubscriptionsContext?
|
||||||
|
|
||||||
public init(accountManager: AccountManager<TelegramAccountManagerTypes>, id: AccountRecordId, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, networkArguments: NetworkInitializationArguments, peerId: PeerId, auxiliaryMethods: AccountAuxiliaryMethods, supplementary: Bool) {
|
public init(accountManager: AccountManager<TelegramAccountManagerTypes>, id: AccountRecordId, basePath: String, testingEnvironment: Bool, postbox: Postbox, network: Network, networkArguments: NetworkInitializationArguments, peerId: PeerId, auxiliaryMethods: AccountAuxiliaryMethods, supplementary: Bool) {
|
||||||
self.accountManager = accountManager
|
self.accountManager = accountManager
|
||||||
@ -995,11 +995,11 @@ public class Account {
|
|||||||
self.peerInputActivityManager = PeerInputActivityManager()
|
self.peerInputActivityManager = PeerInputActivityManager()
|
||||||
|
|
||||||
if !supplementary {
|
if !supplementary {
|
||||||
self.filteredStorySubscriptionsContext = StorySubscriptionsContext(accountPeerId: peerId, postbox: postbox, network: network, includesHidden: false)
|
self.filteredStorySubscriptionsContext = StorySubscriptionsContext(accountPeerId: peerId, postbox: postbox, network: network, isHidden: false)
|
||||||
self.allStorySubscriptionsContext = StorySubscriptionsContext(accountPeerId: peerId, postbox: postbox, network: network, includesHidden: true)
|
self.hiddenStorySubscriptionsContext = StorySubscriptionsContext(accountPeerId: peerId, postbox: postbox, network: network, isHidden: true)
|
||||||
} else {
|
} else {
|
||||||
self.filteredStorySubscriptionsContext = nil
|
self.filteredStorySubscriptionsContext = nil
|
||||||
self.allStorySubscriptionsContext = nil
|
self.hiddenStorySubscriptionsContext = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
self.callSessionManager = CallSessionManager(postbox: postbox, network: network, maxLayer: networkArguments.voipMaxLayer, versions: networkArguments.voipVersions, addUpdates: { [weak self] updates in
|
self.callSessionManager = CallSessionManager(postbox: postbox, network: network, maxLayer: networkArguments.voipMaxLayer, versions: networkArguments.voipVersions, addUpdates: { [weak self] updates in
|
||||||
|
|||||||
@ -212,6 +212,7 @@ struct AccountMutableState {
|
|||||||
var insertedPeers: [PeerId: Peer] = [:]
|
var insertedPeers: [PeerId: Peer] = [:]
|
||||||
|
|
||||||
var preCachedResources: [(MediaResource, Data)] = []
|
var preCachedResources: [(MediaResource, Data)] = []
|
||||||
|
var preCachedStories: [StoryId: Api.StoryItem] = [:]
|
||||||
|
|
||||||
var updatedMaxMessageId: Int32?
|
var updatedMaxMessageId: Int32?
|
||||||
var updatedQts: Int32?
|
var updatedQts: Int32?
|
||||||
@ -281,6 +282,11 @@ struct AccountMutableState {
|
|||||||
self.apiChats[chat.peerId] = chat
|
self.apiChats[chat.peerId] = chat
|
||||||
}
|
}
|
||||||
self.preCachedResources.append(contentsOf: other.preCachedResources)
|
self.preCachedResources.append(contentsOf: other.preCachedResources)
|
||||||
|
|
||||||
|
for (id, story) in other.preCachedStories {
|
||||||
|
self.preCachedStories[id] = story
|
||||||
|
}
|
||||||
|
|
||||||
self.externallyUpdatedPeerId.formUnion(other.externallyUpdatedPeerId)
|
self.externallyUpdatedPeerId.formUnion(other.externallyUpdatedPeerId)
|
||||||
for (peerId, namespaces) in other.namespacesWithHolesFromPreviousState {
|
for (peerId, namespaces) in other.namespacesWithHolesFromPreviousState {
|
||||||
if self.namespacesWithHolesFromPreviousState[peerId] == nil {
|
if self.namespacesWithHolesFromPreviousState[peerId] == nil {
|
||||||
@ -305,6 +311,10 @@ struct AccountMutableState {
|
|||||||
self.preCachedResources.append((resource, data))
|
self.preCachedResources.append((resource, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutating func addPreCachedStory(id: StoryId, story: Api.StoryItem) {
|
||||||
|
self.preCachedStories[id] = story
|
||||||
|
}
|
||||||
|
|
||||||
mutating func addExternallyUpdatedPeerId(_ peerId: PeerId) {
|
mutating func addExternallyUpdatedPeerId(_ peerId: PeerId) {
|
||||||
self.externallyUpdatedPeerId.insert(peerId)
|
self.externallyUpdatedPeerId.insert(peerId)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -727,6 +727,11 @@ func finalStateWithDifference(accountPeerId: PeerId, postbox: Postbox, network:
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = message.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
var peerIsForum = false
|
var peerIsForum = false
|
||||||
if let peerId = message.peerId {
|
if let peerId = message.peerId {
|
||||||
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
peerIsForum = updatedState.isPeerForum(peerId: peerId)
|
||||||
@ -954,6 +959,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
var attributes = message.attributes
|
var attributes = message.attributes
|
||||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||||
updatedState.editMessage(messageId, message: message.withUpdatedAttributes(attributes))
|
updatedState.editMessage(messageId, message: message.withUpdatedAttributes(attributes))
|
||||||
@ -1020,6 +1030,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
updatedState.editMessage(messageId, message: message)
|
updatedState.editMessage(messageId, message: message)
|
||||||
for media in message.media {
|
for media in message.media {
|
||||||
if let media = media as? TelegramMediaAction {
|
if let media = media as? TelegramMediaAction {
|
||||||
@ -1050,6 +1065,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
var attributes = message.attributes
|
var attributes = message.attributes
|
||||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||||
updatedState.addMessages([message.withUpdatedAttributes(attributes)], location: .UpperHistoryBlock)
|
updatedState.addMessages([message.withUpdatedAttributes(attributes)], location: .UpperHistoryBlock)
|
||||||
@ -1082,6 +1102,11 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
||||||
}
|
}
|
||||||
case let .updateServiceNotification(flags, date, type, text, media, entities):
|
case let .updateServiceNotification(flags, date, type, text, media, entities):
|
||||||
@ -1715,7 +1740,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||||||
|> mapToSignal { finalState in
|
|> mapToSignal { finalState in
|
||||||
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
||||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: finalState)
|
||||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||||
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
||||||
|> map { resultingState, resolveError -> AccountFinalState in
|
|> map { resultingState, resolveError -> AccountFinalState in
|
||||||
@ -2073,16 +2098,102 @@ func resolveForumThreads(postbox: Postbox, network: Network, fetchedChatList: Fe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveAssociatedStories(postbox: Postbox, network: Network, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
func resolveStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, storyIds: Set<StoryId>, additionalPeers: [PeerId: Peer], result: T) -> Signal<T, NoError> {
|
||||||
|
var storyBuckets: [PeerId: [Int32]] = [:]
|
||||||
|
for id in storyIds {
|
||||||
|
if storyBuckets[id.peerId] == nil {
|
||||||
|
storyBuckets[id.peerId] = []
|
||||||
|
}
|
||||||
|
storyBuckets[id.peerId]?.append(id.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
var signals: [Signal<Never, NoError>] = []
|
||||||
|
for (peerId, allIds) in storyBuckets {
|
||||||
|
var idOffset = 0
|
||||||
|
while idOffset < allIds.count {
|
||||||
|
let bucketLength = min(100, allIds.count - idOffset)
|
||||||
|
let ids = Array(allIds[idOffset ..< (idOffset + bucketLength)])
|
||||||
|
signals.append(_internal_getStoriesById(accountPeerId: accountPeerId, postbox: postbox, source: source, peerId: peerId, peerReference: additionalPeers[peerId].flatMap(PeerReference.init), ids: ids)
|
||||||
|
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||||
|
return postbox.transaction { transaction -> Void in
|
||||||
|
for id in ids {
|
||||||
|
let current = transaction.getStory(id: StoryId(peerId: peerId, id: id))
|
||||||
|
var updated: CodableEntry?
|
||||||
|
if let updatedItem = result.first(where: { $0.id == id }) {
|
||||||
|
if let entry = CodableEntry(updatedItem) {
|
||||||
|
updated = entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if current != updated {
|
||||||
|
transaction.setStory(id: StoryId(peerId: peerId, id: id), value: updated ?? CodableEntry(data: Data()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
})
|
||||||
|
idOffset += bucketLength
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combineLatest(signals)
|
||||||
|
|> ignoreValues
|
||||||
|
|> map { _ -> T in
|
||||||
|
}
|
||||||
|
|> then(.single(result))
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveAssociatedStories(postbox: Postbox, network: Network, accountPeerId: PeerId, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
|
||||||
return postbox.transaction { transaction -> Signal<AccountMutableState, NoError> in
|
return postbox.transaction { transaction -> Signal<AccountMutableState, NoError> in
|
||||||
return .single(state)
|
var missingStoryIds = Set<StoryId>()
|
||||||
|
|
||||||
|
for operation in state.operations {
|
||||||
|
switch operation {
|
||||||
|
case let .AddMessages(messages, _):
|
||||||
|
for message in messages {
|
||||||
|
for media in message.media {
|
||||||
|
for id in media.storyIds {
|
||||||
|
if let existing = transaction.getStory(id: id), case .item = existing.get(Stories.StoredItem.self) {
|
||||||
|
} else if state.preCachedStories[id] != nil {
|
||||||
|
} else {
|
||||||
|
missingStoryIds.insert(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !missingStoryIds.isEmpty {
|
||||||
|
return resolveStories(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, storyIds: missingStoryIds, additionalPeers: state.insertedPeers, result: state)
|
||||||
|
} else {
|
||||||
|
return .single(state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|> switchToLatest
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveAssociatedStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, messages: [StoreMessage], result: T) -> Signal<T, NoError> {
|
func resolveAssociatedStories<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, messages: [StoreMessage], additionalPeers: [PeerId: Peer], result: T) -> Signal<T, NoError> {
|
||||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||||
return .single(result)
|
var missingStoryIds = Set<StoryId>()
|
||||||
|
|
||||||
|
for message in messages {
|
||||||
|
for media in message.media {
|
||||||
|
for id in media.storyIds {
|
||||||
|
if let existing = transaction.getStory(id: id), case .item = existing.get(Stories.StoredItem.self) {
|
||||||
|
} else {
|
||||||
|
missingStoryIds.insert(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !missingStoryIds.isEmpty {
|
||||||
|
return resolveStories(postbox: postbox, source: source, accountPeerId: accountPeerId, storyIds: missingStoryIds, additionalPeers: additionalPeers, result: result)
|
||||||
|
} else {
|
||||||
|
return .single(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|> switchToLatest
|
|> switchToLatest
|
||||||
}
|
}
|
||||||
@ -2420,7 +2531,7 @@ func pollChannelOnce(accountPeerId: PeerId, postbox: Postbox, network: Network,
|
|||||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Int32, NoError> in
|
|> mapToSignal { (finalState, _, timeout) -> Signal<Int32, NoError> in
|
||||||
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
||||||
|> mapToSignal { resultingState -> Signal<AccountMutableState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountMutableState, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: finalState)
|
||||||
}
|
}
|
||||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||||
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
||||||
@ -2477,7 +2588,7 @@ public func standalonePollChannelOnce(accountPeerId: PeerId, postbox: Postbox, n
|
|||||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Never, NoError> in
|
|> mapToSignal { (finalState, _, timeout) -> Signal<Never, NoError> in
|
||||||
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
|
||||||
|> mapToSignal { resultingState -> Signal<AccountMutableState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountMutableState, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, network: network, state: finalState)
|
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: finalState)
|
||||||
}
|
}
|
||||||
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountFinalState, NoError> in
|
||||||
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
return resolveMissingPeerChatInfos(network: network, state: resultingState)
|
||||||
@ -2687,7 +2798,7 @@ func resetChannels(accountPeerId: PeerId, postbox: Postbox, network: Network, pe
|
|||||||
// TODO: delete messages later than top
|
// TODO: delete messages later than top
|
||||||
return resolveAssociatedMessages(postbox: postbox, network: network, state: updatedState)
|
return resolveAssociatedMessages(postbox: postbox, network: network, state: updatedState)
|
||||||
|> mapToSignal { resultingState -> Signal<AccountMutableState, NoError> in
|
|> mapToSignal { resultingState -> Signal<AccountMutableState, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, network: network, state: updatedState)
|
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: updatedState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2758,6 +2869,11 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
||||||
if case let .Id(id) = message.id {
|
if case let .Id(id) = message.id {
|
||||||
updatedState.updateChannelSynchronizedUntilMessage(id.peerId, id: id.id)
|
updatedState.updateChannelSynchronizedUntilMessage(id.peerId, id: id.id)
|
||||||
@ -2787,6 +2903,11 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
var attributes = message.attributes
|
var attributes = message.attributes
|
||||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||||
updatedState.editMessage(messageId, message: message.withUpdatedAttributes(attributes))
|
updatedState.editMessage(messageId, message: message.withUpdatedAttributes(attributes))
|
||||||
@ -2837,7 +2958,7 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
|
|
||||||
return resolveForumThreads(postbox: postbox, network: network, state: updatedState)
|
return resolveForumThreads(postbox: postbox, network: network, state: updatedState)
|
||||||
|> mapToSignal { updatedState in
|
|> mapToSignal { updatedState in
|
||||||
return resolveAssociatedStories(postbox: postbox, network: network, state: updatedState)
|
return resolveAssociatedStories(postbox: postbox, network: network, accountPeerId: accountPeerId, state: updatedState)
|
||||||
|> map { updatedState -> (AccountMutableState, Bool, Int32?) in
|
|> map { updatedState -> (AccountMutableState, Bool, Int32?) in
|
||||||
return (updatedState, true, apiTimeout)
|
return (updatedState, true, apiTimeout)
|
||||||
}
|
}
|
||||||
@ -2904,6 +3025,11 @@ private func pollChannel(accountPeerId: PeerId, postbox: Postbox, network: Netwo
|
|||||||
updatedState.addPreCachedResource(resource, data: data)
|
updatedState.addPreCachedResource(resource, data: data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let preCachedStories = apiMessage.preCachedStories {
|
||||||
|
for (id, story) in preCachedStories {
|
||||||
|
updatedState.addPreCachedStory(id: id, story: story)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let location: AddMessagesLocation
|
let location: AddMessagesLocation
|
||||||
if case let .Id(id) = message.id, id.id == topMessage {
|
if case let .Id(id) = message.id, id.id == topMessage {
|
||||||
@ -3167,6 +3293,16 @@ func replayFinalState(
|
|||||||
var holesFromPreviousStateMessageIds: [MessageId] = []
|
var holesFromPreviousStateMessageIds: [MessageId] = []
|
||||||
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
|
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
|
||||||
|
|
||||||
|
for (id, story) in finalState.state.preCachedStories {
|
||||||
|
if let storyItem = Stories.StoredItem(apiStoryItem: story, peerId: id.peerId, transaction: transaction) {
|
||||||
|
if let entry = CodableEntry(storyItem) {
|
||||||
|
transaction.setStory(id: id, value: entry)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transaction.setStory(id: id, value: CodableEntry(data: Data()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (peerId, namespaces) in finalState.state.namespacesWithHolesFromPreviousState {
|
for (peerId, namespaces) in finalState.state.namespacesWithHolesFromPreviousState {
|
||||||
for (namespace, namespaceState) in namespaces {
|
for (namespace, namespaceState) in namespaces {
|
||||||
if let pts = namespaceState.validateChannelPts {
|
if let pts = namespaceState.validateChannelPts {
|
||||||
|
|||||||
@ -100,7 +100,7 @@ func resolveUnknownEmojiFiles<T>(postbox: Postbox, source: FetchMessageHistoryHo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal<T, NoError> {
|
func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, accountPeerId: PeerId, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal<T, NoError> {
|
||||||
return postbox.transaction { transaction -> Signal<T, NoError> in
|
return postbox.transaction { transaction -> Signal<T, NoError> in
|
||||||
var storedIds = Set<MessageId>()
|
var storedIds = Set<MessageId>()
|
||||||
var referencedReplyIds = ReferencedReplyMessageIds()
|
var referencedReplyIds = ReferencedReplyMessageIds()
|
||||||
@ -129,7 +129,7 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
|||||||
if referencedReplyIds.isEmpty && referencedGeneralIds.isEmpty {
|
if referencedReplyIds.isEmpty && referencedGeneralIds.isEmpty {
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, source: source, messages: storeMessages, result: Void())
|
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: peers, result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return postbox.transaction { transaction -> T in
|
return postbox.transaction { transaction -> T in
|
||||||
return f(transaction, [], [])
|
return f(transaction, [], [])
|
||||||
@ -227,7 +227,14 @@ func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHis
|
|||||||
|
|
||||||
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages + additionalMessages, reactions: [], result: Void())
|
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages + additionalMessages, reactions: [], result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return resolveAssociatedStories(postbox: postbox, source: source, messages: storeMessages + additionalMessages, result: Void())
|
var additionalPeerMap: [PeerId: Peer] = [:]
|
||||||
|
for (_, peer) in peers {
|
||||||
|
additionalPeerMap[peer.id] = peer
|
||||||
|
}
|
||||||
|
for peer in additionalPeers {
|
||||||
|
additionalPeerMap[peer.id] = peer
|
||||||
|
}
|
||||||
|
return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: additionalPeerMap, result: Void())
|
||||||
|> mapToSignal { _ -> Signal<T, NoError> in
|
|> mapToSignal { _ -> Signal<T, NoError> in
|
||||||
return postbox.transaction { transaction -> T in
|
return postbox.transaction { transaction -> T in
|
||||||
return f(transaction, additionalPeers, additionalMessages)
|
return f(transaction, additionalPeers, additionalMessages)
|
||||||
@ -669,7 +676,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return withResolvedAssociatedMessages(postbox: postbox, source: source, peers: Dictionary(peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: storeMessages, { transaction, additionalPeers, additionalMessages -> FetchMessageHistoryHoleResult? in
|
return withResolvedAssociatedMessages(postbox: postbox, source: source, accountPeerId: accountPeerId, peers: Dictionary(peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: storeMessages, { transaction, additionalPeers, additionalMessages -> FetchMessageHistoryHoleResult? in
|
||||||
let _ = transaction.addMessages(storeMessages, location: .Random)
|
let _ = transaction.addMessages(storeMessages, location: .Random)
|
||||||
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
let _ = transaction.addMessages(additionalMessages, location: .Random)
|
||||||
var filledRange: ClosedRange<MessageId.Id>
|
var filledRange: ClosedRange<MessageId.Id>
|
||||||
@ -805,7 +812,7 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
|
|||||||
}
|
}
|
||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
}
|
}
|
||||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
||||||
updatePeers(transaction: transaction, peers: fetchedChats.peers + additionalPeers, update: { _, updated -> Peer in
|
updatePeers(transaction: transaction, peers: fetchedChats.peers + additionalPeers, update: { _, updated -> Peer in
|
||||||
return updated
|
return updated
|
||||||
})
|
})
|
||||||
|
|||||||
@ -14,7 +14,7 @@ func _internal_resetAccountState(postbox: Postbox, network: Network, accountPeer
|
|||||||
guard let fetchedChats = fetchedChats else {
|
guard let fetchedChats = fetchedChats else {
|
||||||
return .never()
|
return .never()
|
||||||
}
|
}
|
||||||
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), accountPeerId: accountPeerId, peers: Dictionary(fetchedChats.peers.map({ ($0.id, $0) }), uniquingKeysWith: { lhs, _ in lhs }), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages -> Void in
|
||||||
for peerId in transaction.chatListGetAllPeerIds() {
|
for peerId in transaction.chatListGetAllPeerIds() {
|
||||||
if peerId.namespace != Namespaces.Peer.SecretChat {
|
if peerId.namespace != Namespaces.Peer.SecretChat {
|
||||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded)
|
||||||
|
|||||||
@ -85,6 +85,19 @@ extension Api.MessageMedia {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var preCachedStories: [StoryId: Api.StoryItem]? {
|
||||||
|
switch self {
|
||||||
|
case let .messageMediaStory(_, userId, id, story):
|
||||||
|
if let story = story {
|
||||||
|
return [StoryId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), id: id): story]
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Api.Message {
|
extension Api.Message {
|
||||||
@ -142,10 +155,19 @@ extension Api.Message {
|
|||||||
|
|
||||||
var preCachedResources: [(MediaResource, Data)]? {
|
var preCachedResources: [(MediaResource, Data)]? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
return media?.preCachedResources
|
return media?.preCachedResources
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var preCachedStories: [StoryId: Api.StoryItem]? {
|
||||||
|
switch self {
|
||||||
|
case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
||||||
|
return media?.preCachedStories
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1263,16 +1263,16 @@ func _internal_getStoriesById(accountPeerId: PeerId, postbox: Postbox, network:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_getStoriesById(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, ids: [Int32]) -> Signal<[Stories.StoredItem], NoError> {
|
func _internal_getStoriesById(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, peerId: PeerId, peerReference: PeerReference?, ids: [Int32]) -> Signal<[Stories.StoredItem], NoError> {
|
||||||
return postbox.transaction { transaction -> Api.InputUser? in
|
return postbox.transaction { transaction -> Api.InputUser? in
|
||||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||||
}
|
}
|
||||||
|> mapToSignal { inputUser -> Signal<[Stories.StoredItem], NoError> in
|
|> mapToSignal { inputUser -> Signal<[Stories.StoredItem], NoError> in
|
||||||
guard let inputUser = inputUser else {
|
guard let inputUser = inputUser ?? peerReference?.inputUser else {
|
||||||
return .single([])
|
return .single([])
|
||||||
}
|
}
|
||||||
|
|
||||||
return network.request(Api.functions.stories.getStoriesByID(userId: inputUser, id: ids))
|
return source.request(Api.functions.stories.getStoriesByID(userId: inputUser, id: ids))
|
||||||
|> map(Optional.init)
|
|> map(Optional.init)
|
||||||
|> `catch` { _ -> Signal<Api.stories.Stories?, NoError> in
|
|> `catch` { _ -> Signal<Api.stories.Stories?, NoError> in
|
||||||
return .single(nil)
|
return .single(nil)
|
||||||
@ -1685,7 +1685,7 @@ func _internal_exportStoryLink(account: Account, peerId: EnginePeer.Id, id: Int3
|
|||||||
}
|
}
|
||||||
|
|
||||||
func _internal_refreshStories(account: Account, peerId: PeerId, ids: [Int32]) -> Signal<Never, NoError> {
|
func _internal_refreshStories(account: Account, peerId: PeerId, ids: [Int32]) -> Signal<Never, NoError> {
|
||||||
return _internal_getStoriesById(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, peerId: peerId, ids: ids)
|
return _internal_getStoriesById(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), peerId: peerId, peerReference: nil, ids: ids)
|
||||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||||
return account.postbox.transaction { transaction -> Void in
|
return account.postbox.transaction { transaction -> Void in
|
||||||
var currentItems = transaction.getStoryItems(peerId: peerId)
|
var currentItems = transaction.getStoryItems(peerId: peerId)
|
||||||
|
|||||||
@ -144,7 +144,7 @@ public final class StorySubscriptionsContext {
|
|||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
private let postbox: Postbox
|
private let postbox: Postbox
|
||||||
private let network: Network
|
private let network: Network
|
||||||
private let includesHidden: Bool
|
private let isHidden: Bool
|
||||||
|
|
||||||
private var taskState = TaskState()
|
private var taskState = TaskState()
|
||||||
|
|
||||||
@ -155,12 +155,12 @@ public final class StorySubscriptionsContext {
|
|||||||
private let loadMoreDisposable = MetaDisposable()
|
private let loadMoreDisposable = MetaDisposable()
|
||||||
private let refreshTimerDisposable = MetaDisposable()
|
private let refreshTimerDisposable = MetaDisposable()
|
||||||
|
|
||||||
init(queue: Queue, accountPeerId: PeerId, postbox: Postbox, network: Network, includesHidden: Bool) {
|
init(queue: Queue, accountPeerId: PeerId, postbox: Postbox, network: Network, isHidden: Bool) {
|
||||||
self.accountPeerId = accountPeerId
|
self.accountPeerId = accountPeerId
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.postbox = postbox
|
self.postbox = postbox
|
||||||
self.network = network
|
self.network = network
|
||||||
self.includesHidden = includesHidden
|
self.isHidden = isHidden
|
||||||
|
|
||||||
self.taskState.isRefreshScheduled = true
|
self.taskState.isRefreshScheduled = true
|
||||||
|
|
||||||
@ -183,7 +183,7 @@ public final class StorySubscriptionsContext {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let subscriptionsKey: PostboxStorySubscriptionsKey = self.includesHidden ? .all : .filtered
|
let subscriptionsKey: PostboxStorySubscriptionsKey = self.isHidden ? .hidden : .filtered
|
||||||
|
|
||||||
if self.taskState.isRefreshScheduled {
|
if self.taskState.isRefreshScheduled {
|
||||||
self.isLoading = true
|
self.isLoading = true
|
||||||
@ -244,7 +244,7 @@ public final class StorySubscriptionsContext {
|
|||||||
private func loadImpl(isRefresh: Bool, stateMark: OpaqueStateMark) {
|
private func loadImpl(isRefresh: Bool, stateMark: OpaqueStateMark) {
|
||||||
var flags: Int32 = 0
|
var flags: Int32 = 0
|
||||||
|
|
||||||
if self.includesHidden {
|
if self.isHidden {
|
||||||
flags |= 1 << 2
|
flags |= 1 << 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,8 +270,8 @@ public final class StorySubscriptionsContext {
|
|||||||
|
|
||||||
let accountPeerId = self.accountPeerId
|
let accountPeerId = self.accountPeerId
|
||||||
|
|
||||||
let includesHidden = self.includesHidden
|
let isHidden = self.isHidden
|
||||||
let subscriptionsKey: PostboxStorySubscriptionsKey = self.includesHidden ? .all : .filtered
|
let subscriptionsKey: PostboxStorySubscriptionsKey = self.isHidden ? .hidden : .filtered
|
||||||
|
|
||||||
self.loadMoreDisposable.set((self.network.request(Api.functions.stories.getAllStories(flags: flags, state: state))
|
self.loadMoreDisposable.set((self.network.request(Api.functions.stories.getAllStories(flags: flags, state: state))
|
||||||
|> deliverOn(self.queue)).start(next: { [weak self] result in
|
|> deliverOn(self.queue)).start(next: { [weak self] result in
|
||||||
@ -343,7 +343,7 @@ public final class StorySubscriptionsContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isRefresh {
|
if isRefresh {
|
||||||
if !includesHidden {
|
if !isHidden {
|
||||||
if !peerEntries.contains(where: { $0 == accountPeerId }) {
|
if !peerEntries.contains(where: { $0 == accountPeerId }) {
|
||||||
transaction.setStoryItems(peerId: accountPeerId, items: [])
|
transaction.setStoryItems(peerId: accountPeerId, items: [])
|
||||||
}
|
}
|
||||||
@ -396,10 +396,10 @@ public final class StorySubscriptionsContext {
|
|||||||
private let queue = Queue(name: "StorySubscriptionsContext")
|
private let queue = Queue(name: "StorySubscriptionsContext")
|
||||||
private let impl: QueueLocalObject<Impl>
|
private let impl: QueueLocalObject<Impl>
|
||||||
|
|
||||||
init(accountPeerId: PeerId, postbox: Postbox, network: Network, includesHidden: Bool) {
|
init(accountPeerId: PeerId, postbox: Postbox, network: Network, isHidden: Bool) {
|
||||||
let queue = self.queue
|
let queue = self.queue
|
||||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||||
Impl(queue: queue, accountPeerId: accountPeerId, postbox: postbox, network: network, includesHidden: includesHidden)
|
Impl(queue: queue, accountPeerId: accountPeerId, postbox: postbox, network: network, isHidden: isHidden)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -592,7 +592,7 @@ public extension TelegramEngine {
|
|||||||
}).start()
|
}).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func storySubscriptions(includeHidden: Bool) -> Signal<EngineStorySubscriptions, NoError> {
|
public func storySubscriptions(isHidden: Bool) -> Signal<EngineStorySubscriptions, NoError> {
|
||||||
let debugTimerSignal: Signal<Bool, NoError>
|
let debugTimerSignal: Signal<Bool, NoError>
|
||||||
#if DEBUG && false
|
#if DEBUG && false
|
||||||
debugTimerSignal = Signal<Bool, NoError>.single(true)
|
debugTimerSignal = Signal<Bool, NoError>.single(true)
|
||||||
@ -609,7 +609,7 @@ public extension TelegramEngine {
|
|||||||
debugTimerSignal = .single(true)
|
debugTimerSignal = .single(true)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
let subscriptionsKey: PostboxStorySubscriptionsKey = includeHidden ? .all : .filtered
|
let subscriptionsKey: PostboxStorySubscriptionsKey = isHidden ? .hidden : .filtered
|
||||||
|
|
||||||
let basicPeerKey = PostboxViewKey.basicPeer(self.account.peerId)
|
let basicPeerKey = PostboxViewKey.basicPeer(self.account.peerId)
|
||||||
let storySubscriptionsKey = PostboxViewKey.storySubscriptions(key: subscriptionsKey)
|
let storySubscriptionsKey = PostboxViewKey.storySubscriptions(key: subscriptionsKey)
|
||||||
@ -759,9 +759,9 @@ public extension TelegramEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func preloadStorySubscriptions(includeHidden: Bool) -> Signal<[EngineMediaResource.Id: StoryPreloadInfo], NoError> {
|
public func preloadStorySubscriptions(isHidden: Bool) -> Signal<[EngineMediaResource.Id: StoryPreloadInfo], NoError> {
|
||||||
let basicPeerKey = PostboxViewKey.basicPeer(self.account.peerId)
|
let basicPeerKey = PostboxViewKey.basicPeer(self.account.peerId)
|
||||||
let subscriptionsKey: PostboxStorySubscriptionsKey = includeHidden ? .all : .filtered
|
let subscriptionsKey: PostboxStorySubscriptionsKey = isHidden ? .hidden : .filtered
|
||||||
let storySubscriptionsKey = PostboxViewKey.storySubscriptions(key: subscriptionsKey)
|
let storySubscriptionsKey = PostboxViewKey.storySubscriptions(key: subscriptionsKey)
|
||||||
return self.account.postbox.combinedView(keys: [
|
return self.account.postbox.combinedView(keys: [
|
||||||
basicPeerKey,
|
basicPeerKey,
|
||||||
|
|||||||
@ -60,12 +60,25 @@ public func updatePeers(transaction: Transaction, peers: [Peer], update: (Peer?,
|
|||||||
peerIds.removeAll(where: { $0 == updated.id })
|
peerIds.removeAll(where: { $0 == updated.id })
|
||||||
transaction.replaceAllStorySubscriptions(key: .filtered, state: state, peerIds: peerIds)
|
transaction.replaceAllStorySubscriptions(key: .filtered, state: state, peerIds: peerIds)
|
||||||
}
|
}
|
||||||
|
if transaction.storySubscriptionsContains(key: .hidden, peerId: updated.id) {
|
||||||
|
var (state, peerIds) = transaction.getAllStorySubscriptions(key: .filtered)
|
||||||
|
if !peerIds.contains(updated.id) {
|
||||||
|
peerIds.append(updated.id)
|
||||||
|
transaction.replaceAllStorySubscriptions(key: .hidden, state: state, peerIds: peerIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if transaction.storySubscriptionsContains(key: .all, peerId: updated.id) && !transaction.storySubscriptionsContains(key: .filtered, peerId: updated.id) {
|
if transaction.storySubscriptionsContains(key: .hidden, peerId: updated.id) {
|
||||||
var (state, peerIds) = transaction.getAllStorySubscriptions(key: .all)
|
var (state, peerIds) = transaction.getAllStorySubscriptions(key: .filtered)
|
||||||
peerIds.removeAll(where: { $0 == updated.id })
|
peerIds.removeAll(where: { $0 == updated.id })
|
||||||
peerIds.append(updated.id)
|
transaction.replaceAllStorySubscriptions(key: .hidden, state: state, peerIds: peerIds)
|
||||||
transaction.replaceAllStorySubscriptions(key: .filtered, state: state, peerIds: peerIds)
|
}
|
||||||
|
if transaction.storySubscriptionsContains(key: .filtered, peerId: updated.id) {
|
||||||
|
var (state, peerIds) = transaction.getAllStorySubscriptions(key: .filtered)
|
||||||
|
if !peerIds.contains(updated.id) {
|
||||||
|
peerIds.append(updated.id)
|
||||||
|
transaction.replaceAllStorySubscriptions(key: .filtered, state: state, peerIds: peerIds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -829,7 +829,7 @@ public final class ChatListHeaderComponent: Component {
|
|||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
strings: component.strings,
|
strings: component.strings,
|
||||||
sideInset: component.sideInset,
|
sideInset: component.sideInset,
|
||||||
includesHidden: component.storiesIncludeHidden,
|
useHiddenList: component.storiesIncludeHidden,
|
||||||
storySubscriptions: storySubscriptions,
|
storySubscriptions: storySubscriptions,
|
||||||
collapseFraction: 1.0 - component.storiesFraction,
|
collapseFraction: 1.0 - component.storiesFraction,
|
||||||
unlockedFraction: 1.0 - component.storiesUnlockedFraction,
|
unlockedFraction: 1.0 - component.storiesUnlockedFraction,
|
||||||
|
|||||||
@ -891,6 +891,8 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
private var presentationDataDisposable: Disposable?
|
private var presentationDataDisposable: Disposable?
|
||||||
|
|
||||||
private weak var pendingOpenListContext: PeerStoryListContentContextImpl?
|
private weak var pendingOpenListContext: PeerStoryListContentContextImpl?
|
||||||
|
|
||||||
|
private var preloadArchiveListContext: PeerStoryListContext?
|
||||||
|
|
||||||
public init(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, navigationController: @escaping () -> NavigationController?, listContext: PeerStoryListContext?) {
|
public init(context: AccountContext, peerId: PeerId, chatLocation: ChatLocation, contentType: ContentType, captureProtected: Bool, isSaved: Bool, isArchive: Bool, navigationController: @escaping () -> NavigationController?, listContext: PeerStoryListContext?) {
|
||||||
self.context = context
|
self.context = context
|
||||||
@ -1448,6 +1450,10 @@ public final class PeerInfoStoryPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScr
|
|||||||
})
|
})
|
||||||
|
|
||||||
self.requestHistoryAroundVisiblePosition(synchronous: false, reloadAtTop: false)
|
self.requestHistoryAroundVisiblePosition(synchronous: false, reloadAtTop: false)
|
||||||
|
|
||||||
|
if peerId == context.account.peerId {
|
||||||
|
self.preloadArchiveListContext = PeerStoryListContext(account: context.account, peerId: peerId, isArchived: true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
|||||||
@ -2722,7 +2722,7 @@ final class StorageUsageScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
self.controller?()?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
self.controller?()?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
||||||
},
|
},
|
||||||
transitionNode: { [weak self] messageId, media in
|
transitionNode: { [weak self] messageId, media, _ in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,7 @@ swift_library(
|
|||||||
"//submodules/PresentationDataUtils",
|
"//submodules/PresentationDataUtils",
|
||||||
"//submodules/UrlEscaping",
|
"//submodules/UrlEscaping",
|
||||||
"//submodules/OverlayStatusController",
|
"//submodules/OverlayStatusController",
|
||||||
|
"//submodules/Utils/VolumeButtons",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -16,6 +16,7 @@ import EntityKeyboard
|
|||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
import AttachmentUI
|
import AttachmentUI
|
||||||
import simd
|
import simd
|
||||||
|
import VolumeButtons
|
||||||
|
|
||||||
func hasFirstResponder(_ view: UIView) -> Bool {
|
func hasFirstResponder(_ view: UIView) -> Bool {
|
||||||
if view.isFirstResponder {
|
if view.isFirstResponder {
|
||||||
@ -173,6 +174,9 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
|
|
||||||
private var transitionCloneMasterView: UIView
|
private var transitionCloneMasterView: UIView
|
||||||
|
|
||||||
|
private var volumeButtonsListener: VolumeButtonsListener?
|
||||||
|
private let volumeButtonsListenerShouldBeActvie = ValuePromise<Bool>(false, ignoreRepeated: true)
|
||||||
|
|
||||||
private var isAnimatingOut: Bool = false
|
private var isAnimatingOut: Bool = false
|
||||||
private var didAnimateOut: Bool = false
|
private var didAnimateOut: Bool = false
|
||||||
|
|
||||||
@ -570,6 +574,24 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
self.didAnimateOut = true
|
self.didAnimateOut = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updateVolumeButtonMonitoring() {
|
||||||
|
if self.volumeButtonsListener == nil {
|
||||||
|
self.volumeButtonsListener = VolumeButtonsListener(shouldBeActive: self.volumeButtonsListenerShouldBeActvie.get(), valueChanged: { [weak self] in
|
||||||
|
guard let self, self.storyItemSharedState.useAmbientMode else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.storyItemSharedState.useAmbientMode = false
|
||||||
|
self.volumeButtonsListenerShouldBeActvie.set(false)
|
||||||
|
|
||||||
|
for (_, itemSetView) in self.visibleItemSetViews {
|
||||||
|
if let componentView = itemSetView.view.view as? StoryItemSetContainerComponent.View {
|
||||||
|
componentView.leaveAmbientMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func update(component: StoryContainerScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: Transition) -> CGSize {
|
func update(component: StoryContainerScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: Transition) -> CGSize {
|
||||||
if self.didAnimateOut {
|
if self.didAnimateOut {
|
||||||
return availableSize
|
return availableSize
|
||||||
@ -588,11 +610,22 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
if update {
|
if update {
|
||||||
var focusedItemId: StoryId?
|
var focusedItemId: StoryId?
|
||||||
|
var isVideo = false
|
||||||
if let slice = component.content.stateValue?.slice {
|
if let slice = component.content.stateValue?.slice {
|
||||||
focusedItemId = StoryId(peerId: slice.peer.id, id: slice.item.storyItem.id)
|
focusedItemId = StoryId(peerId: slice.peer.id, id: slice.item.storyItem.id)
|
||||||
|
if case .file = slice.item.storyItem.media {
|
||||||
|
isVideo = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.focusedItem.set(focusedItemId)
|
self.focusedItem.set(focusedItemId)
|
||||||
|
|
||||||
|
if self.storyItemSharedState.useAmbientMode {
|
||||||
|
self.volumeButtonsListenerShouldBeActvie.set(isVideo)
|
||||||
|
if isVideo {
|
||||||
|
self.updateVolumeButtonMonitoring()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if component.content.stateValue?.slice == nil {
|
if component.content.stateValue?.slice == nil {
|
||||||
self.environment?.controller()?.dismiss()
|
self.environment?.controller()?.dismiss()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -25,6 +25,9 @@ public final class StoryContentItem {
|
|||||||
|
|
||||||
open func rewind() {
|
open func rewind() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open func leaveAmbientMode() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class Environment: Equatable {
|
public final class Environment: Equatable {
|
||||||
|
|||||||
@ -225,9 +225,6 @@ final class StoryContentCaptionComponent: Component {
|
|||||||
let expandDistance: CGFloat = 50.0
|
let expandDistance: CGFloat = 50.0
|
||||||
var expandFraction: CGFloat = self.scrollView.contentOffset.y / expandDistance
|
var expandFraction: CGFloat = self.scrollView.contentOffset.y / expandDistance
|
||||||
expandFraction = max(0.0, min(1.0, expandFraction))
|
expandFraction = max(0.0, min(1.0, expandFraction))
|
||||||
if self.scrollView.contentSize.height < self.scrollView.bounds.height + expandDistance {
|
|
||||||
expandFraction = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
let isExpanded = expandFraction > 0.0
|
let isExpanded = expandFraction > 0.0
|
||||||
|
|
||||||
|
|||||||
@ -468,6 +468,18 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func leaveAmbientMode() {
|
||||||
|
guard let component = self.component else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let visibleItem = self.visibleItems[component.slice.item.id] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let itemView = visibleItem.view.view as? StoryContentItem.View {
|
||||||
|
itemView.leaveAmbientMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
@objc public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||||
if otherGestureRecognizer is UIPanGestureRecognizer {
|
if otherGestureRecognizer is UIPanGestureRecognizer {
|
||||||
return true
|
return true
|
||||||
@ -1439,8 +1451,13 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
})))
|
})))
|
||||||
items.append(.action(ContextMenuActionItem(text: "Share", icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: "Share", icon: { theme in
|
||||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor)
|
||||||
}, action: { _, a in
|
}, action: { [weak self] _, a in
|
||||||
a(.default)
|
a(.default)
|
||||||
|
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.sendMessageContext.performShareAction(view: self)
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1732,9 +1749,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
let captionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentFrame.height - captionSize.height), size: captionSize)
|
let captionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentFrame.height - captionSize.height), size: captionSize)
|
||||||
if let captionItemView = captionItem.view.view {
|
if let captionItemView = captionItem.view.view {
|
||||||
if captionItemView.superview == nil {
|
if captionItemView.superview == nil {
|
||||||
if self.contentContainerView.subviews.count >= 1 {
|
self.contentContainerView.insertSubview(captionItemView, aboveSubview: self.contentDimView)
|
||||||
self.contentContainerView.insertSubview(captionItemView, at: 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
captionItemTransition.setFrame(view: captionItemView, frame: captionFrame)
|
captionItemTransition.setFrame(view: captionItemView, frame: captionFrame)
|
||||||
captionItemTransition.setAlpha(view: captionItemView, alpha: (component.hideUI || self.displayViewList || self.inputPanelExternalState.isEditing) ? 0.0 : 1.0)
|
captionItemTransition.setAlpha(view: captionItemView, alpha: (component.hideUI || self.displayViewList || self.inputPanelExternalState.isEditing) ? 0.0 : 1.0)
|
||||||
|
|||||||
@ -23,7 +23,6 @@ swift_library(
|
|||||||
"//submodules/TelegramUniversalVideoContent",
|
"//submodules/TelegramUniversalVideoContent",
|
||||||
"//submodules/AvatarNode",
|
"//submodules/AvatarNode",
|
||||||
"//submodules/Components/HierarchyTrackingLayer",
|
"//submodules/Components/HierarchyTrackingLayer",
|
||||||
"//submodules/Utils/VolumeButtons",
|
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@ -358,7 +358,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let includeHidden: Bool
|
private let isHidden: Bool
|
||||||
|
|
||||||
public private(set) var stateValue: StoryContentContextState?
|
public private(set) var stateValue: StoryContentContextState?
|
||||||
public var state: Signal<StoryContentContextState, NoError> {
|
public var state: Signal<StoryContentContextState, NoError> {
|
||||||
@ -394,12 +394,12 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
includeHidden: Bool,
|
isHidden: Bool,
|
||||||
focusedPeerId: EnginePeer.Id?,
|
focusedPeerId: EnginePeer.Id?,
|
||||||
singlePeer: Bool
|
singlePeer: Bool
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.includeHidden = includeHidden
|
self.isHidden = isHidden
|
||||||
if let focusedPeerId {
|
if let focusedPeerId {
|
||||||
self.focusedItem = (focusedPeerId, nil)
|
self.focusedItem = (focusedPeerId, nil)
|
||||||
}
|
}
|
||||||
@ -493,7 +493,7 @@ public final class StoryContentContextImpl: StoryContentContext {
|
|||||||
self.updatePeerContexts()
|
self.updatePeerContexts()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
self.storySubscriptionsDisposable = (context.engine.messages.storySubscriptions(includeHidden: includeHidden)
|
self.storySubscriptionsDisposable = (context.engine.messages.storySubscriptions(isHidden: isHidden)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
|> deliverOnMainQueue).start(next: { [weak self] storySubscriptions in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import UniversalMediaPlayer
|
|||||||
import TelegramUniversalVideoContent
|
import TelegramUniversalVideoContent
|
||||||
import StoryContainerScreen
|
import StoryContainerScreen
|
||||||
import HierarchyTrackingLayer
|
import HierarchyTrackingLayer
|
||||||
import VolumeButtons
|
|
||||||
|
|
||||||
final class StoryItemContentComponent: Component {
|
final class StoryItemContentComponent: Component {
|
||||||
typealias EnvironmentType = StoryContentItem.Environment
|
typealias EnvironmentType = StoryContentItem.Environment
|
||||||
@ -94,8 +93,6 @@ final class StoryItemContentComponent: Component {
|
|||||||
private let imageNode: TransformImageNode
|
private let imageNode: TransformImageNode
|
||||||
private var videoNode: UniversalVideoNode?
|
private var videoNode: UniversalVideoNode?
|
||||||
|
|
||||||
private var volumeButtonsListener: VolumeButtonsListener?
|
|
||||||
|
|
||||||
private var currentMessageMedia: EngineMedia?
|
private var currentMessageMedia: EngineMedia?
|
||||||
private var fetchDisposable: Disposable?
|
private var fetchDisposable: Disposable?
|
||||||
|
|
||||||
@ -197,19 +194,6 @@ final class StoryItemContentComponent: Component {
|
|||||||
if update {
|
if update {
|
||||||
self.state?.updated(transition: .immediate)
|
self.state?.updated(transition: .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.volumeButtonsListener == nil, let sharedState = self.environment?.sharedState, sharedState.useAmbientMode {
|
|
||||||
self.volumeButtonsListener = VolumeButtonsListener(shouldBeActive: .single(true), valueChanged: { [weak self] in
|
|
||||||
guard let self, let sharedState = self.environment?.sharedState, sharedState.useAmbientMode else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
sharedState.useAmbientMode = false
|
|
||||||
if let videoNode = self.videoNode {
|
|
||||||
videoNode.continueWithOverridingAmbientMode()
|
|
||||||
}
|
|
||||||
self.volumeButtonsListener = nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,6 +214,12 @@ final class StoryItemContentComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func leaveAmbientMode() {
|
||||||
|
if let videoNode = self.videoNode {
|
||||||
|
videoNode.continueWithOverridingAmbientMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func updateIsProgressPaused() {
|
private func updateIsProgressPaused() {
|
||||||
if let videoNode = self.videoNode {
|
if let videoNode = self.videoNode {
|
||||||
var canPlay = !self.isProgressPaused && self.contentLoaded && self.hierarchyTrackingLayer.isInHierarchy
|
var canPlay = !self.isProgressPaused && self.contentLoaded && self.hierarchyTrackingLayer.isInHierarchy
|
||||||
|
|||||||
@ -24,7 +24,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
public let theme: PresentationTheme
|
public let theme: PresentationTheme
|
||||||
public let strings: PresentationStrings
|
public let strings: PresentationStrings
|
||||||
public let sideInset: CGFloat
|
public let sideInset: CGFloat
|
||||||
public let includesHidden: Bool
|
public let useHiddenList: Bool
|
||||||
public let storySubscriptions: EngineStorySubscriptions?
|
public let storySubscriptions: EngineStorySubscriptions?
|
||||||
public let collapseFraction: CGFloat
|
public let collapseFraction: CGFloat
|
||||||
public let unlockedFraction: CGFloat
|
public let unlockedFraction: CGFloat
|
||||||
@ -38,7 +38,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
strings: PresentationStrings,
|
strings: PresentationStrings,
|
||||||
sideInset: CGFloat,
|
sideInset: CGFloat,
|
||||||
includesHidden: Bool,
|
useHiddenList: Bool,
|
||||||
storySubscriptions: EngineStorySubscriptions?,
|
storySubscriptions: EngineStorySubscriptions?,
|
||||||
collapseFraction: CGFloat,
|
collapseFraction: CGFloat,
|
||||||
unlockedFraction: CGFloat,
|
unlockedFraction: CGFloat,
|
||||||
@ -51,7 +51,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.sideInset = sideInset
|
self.sideInset = sideInset
|
||||||
self.includesHidden = includesHidden
|
self.useHiddenList = useHiddenList
|
||||||
self.storySubscriptions = storySubscriptions
|
self.storySubscriptions = storySubscriptions
|
||||||
self.collapseFraction = collapseFraction
|
self.collapseFraction = collapseFraction
|
||||||
self.unlockedFraction = unlockedFraction
|
self.unlockedFraction = unlockedFraction
|
||||||
@ -73,7 +73,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
if lhs.sideInset != rhs.sideInset {
|
if lhs.sideInset != rhs.sideInset {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.includesHidden != rhs.includesHidden {
|
if lhs.useHiddenList != rhs.useHiddenList {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if lhs.storySubscriptions != rhs.storySubscriptions {
|
if lhs.storySubscriptions != rhs.storySubscriptions {
|
||||||
@ -269,7 +269,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
}
|
}
|
||||||
let _ = hasStories
|
let _ = hasStories
|
||||||
|
|
||||||
let collapseStartIndex = component.includesHidden ? 0 : 1
|
let collapseStartIndex = component.useHiddenList ? 0 : 1
|
||||||
|
|
||||||
let collapsedItemWidth: CGFloat = 24.0
|
let collapsedItemWidth: CGFloat = 24.0
|
||||||
let collapsedItemDistance: CGFloat = 14.0
|
let collapsedItemDistance: CGFloat = 14.0
|
||||||
@ -510,8 +510,8 @@ public final class StoryPeerListComponent: Component {
|
|||||||
if self.requestedLoadMoreToken != hasMoreToken {
|
if self.requestedLoadMoreToken != hasMoreToken {
|
||||||
self.requestedLoadMoreToken = hasMoreToken
|
self.requestedLoadMoreToken = hasMoreToken
|
||||||
|
|
||||||
if component.includesHidden {
|
if component.useHiddenList {
|
||||||
if let storySubscriptionsContext = component.context.account.allStorySubscriptionsContext {
|
if let storySubscriptionsContext = component.context.account.hiddenStorySubscriptionsContext {
|
||||||
storySubscriptionsContext.loadMore()
|
storySubscriptionsContext.loadMore()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -526,7 +526,7 @@ public final class StoryPeerListComponent: Component {
|
|||||||
|
|
||||||
self.sortedItems.removeAll(keepingCapacity: true)
|
self.sortedItems.removeAll(keepingCapacity: true)
|
||||||
if let storySubscriptions = component.storySubscriptions {
|
if let storySubscriptions = component.storySubscriptions {
|
||||||
if !component.includesHidden, let accountItem = storySubscriptions.accountItem {
|
if !component.useHiddenList, let accountItem = storySubscriptions.accountItem {
|
||||||
self.sortedItems.append(accountItem)
|
self.sortedItems.append(accountItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -947,7 +947,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageItemView {
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
if let result = itemNode.transitionNode(id: message.id, media: image) {
|
if let result = itemNode.transitionNode(id: message.id, media: image, adjustRect: false) {
|
||||||
selectedNode = result
|
selectedNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1001,12 +1001,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self?.chatDisplayNode.dismissInput()
|
self?.chatDisplayNode.dismissInput()
|
||||||
}, present: { c, a in
|
}, present: { c, a in
|
||||||
self?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
self?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
||||||
}, transitionNode: { messageId, media in
|
}, transitionNode: { messageId, media, adjustRect in
|
||||||
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageItemView {
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: adjustRect) {
|
||||||
selectedNode = result
|
selectedNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18243,7 +18243,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageItemView {
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
selectedNode = result
|
selectedNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -362,15 +362,15 @@ final class ChatHistorySearchContainerNode: SearchDisplayControllerContentNode {
|
|||||||
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
self.listNode.forEachItemNode { itemNode in
|
self.listNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageItemView {
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
} else if let itemNode = itemNode as? ListMessageNode {
|
} else if let itemNode = itemNode as? ListMessageNode {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
} else if let itemNode = itemNode as? GridMessageItemNode {
|
} else if let itemNode = itemNode as? GridMessageItemNode {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,7 +89,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
super.didLoad()
|
super.didLoad()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if let imageNode = self.imageNode, self.item?.message.id == messageId {
|
if let imageNode = self.imageNode, self.item?.message.id == messageId {
|
||||||
return (imageNode, imageNode.bounds, { [weak self] in
|
return (imageNode, imageNode.bounds, { [weak self] in
|
||||||
guard let strongSelf = self, let imageNode = strongSelf.imageNode else {
|
guard let strongSelf = self, let imageNode = strongSelf.imageNode else {
|
||||||
|
|||||||
@ -199,7 +199,7 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4028,9 +4028,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
return super.hitTest(point, with: event)
|
return super.hitTest(point, with: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(id: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
for contentNode in self.contentNodes {
|
for contentNode in self.contentNodes {
|
||||||
if let result = contentNode.transitionNode(messageId: id, media: media) {
|
if let result = contentNode.transitionNode(messageId: id, media: media, adjustRect: adjustRect) {
|
||||||
if self.contentNodes.count == 1 && self.contentNodes.first is ChatMessageMediaBubbleContentNode && self.nameNode == nil && self.adminBadgeNode == nil && self.forwardInfoNode == nil && self.replyInfoNode == nil {
|
if self.contentNodes.count == 1 && self.contentNodes.first is ChatMessageMediaBubbleContentNode && self.nameNode == nil && self.adminBadgeNode == nil && self.forwardInfoNode == nil && self.replyInfoNode == nil {
|
||||||
return (result.0, result.1, { [weak self] in
|
return (result.0, result.1, { [weak self] in
|
||||||
guard let strongSelf = self, let resultView = result.2().0 else {
|
guard let strongSelf = self, let resultView = result.2().0 else {
|
||||||
|
|||||||
@ -104,7 +104,7 @@ final class ChatMessageEventLogPreviousDescriptionContentNode: ChatMessageBubble
|
|||||||
return self.contentNode.updateHiddenMedia(media)
|
return self.contentNode.updateHiddenMedia(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id != messageId {
|
if self.item?.message.id != messageId {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,7 +99,7 @@ final class ChatMessageEventLogPreviousLinkContentNode: ChatMessageBubbleContent
|
|||||||
return self.contentNode.updateHiddenMedia(media)
|
return self.contentNode.updateHiddenMedia(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id != messageId {
|
if self.item?.message.id != messageId {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,7 +106,7 @@ final class ChatMessageEventLogPreviousMessageContentNode: ChatMessageBubbleCont
|
|||||||
return self.contentNode.updateHiddenMedia(media)
|
return self.contentNode.updateHiddenMedia(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id != messageId {
|
if self.item?.message.id != messageId {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -183,7 +183,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id == messageId {
|
if self.item?.message.id == messageId {
|
||||||
return self.interactiveFileNode.transitionNode(media: media)
|
return self.interactiveFileNode.transitionNode(media: media)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -133,7 +133,7 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
return self.contentNode.updateHiddenMedia(media)
|
return self.contentNode.updateHiddenMedia(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id != messageId {
|
if self.item?.message.id != messageId {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -364,7 +364,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1686,6 +1686,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isStory: Bool = false
|
||||||
|
|
||||||
var game: TelegramMediaGame?
|
var game: TelegramMediaGame?
|
||||||
var webpage: TelegramMediaWebpage?
|
var webpage: TelegramMediaWebpage?
|
||||||
var invoice: TelegramMediaInvoice?
|
var invoice: TelegramMediaInvoice?
|
||||||
@ -1696,6 +1698,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
invoice = media
|
invoice = media
|
||||||
} else if let media = media as? TelegramMediaGame {
|
} else if let media = media as? TelegramMediaGame {
|
||||||
game = media
|
game = media
|
||||||
|
} else if let _ = media as? TelegramMediaStory {
|
||||||
|
isStory = true
|
||||||
|
automaticPlayback = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,6 +1722,8 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
} else if let file = content.file, file.isVideo, !file.isAnimated && !file.isVideoSticker {
|
} else if let file = content.file, file.isVideo, !file.isAnimated && !file.isVideoSticker {
|
||||||
progressRequired = true
|
progressRequired = true
|
||||||
}
|
}
|
||||||
|
} else if isStory {
|
||||||
|
progressRequired = true
|
||||||
}
|
}
|
||||||
case .Remote, .Fetching, .Paused:
|
case .Remote, .Fetching, .Paused:
|
||||||
if let webpage = webpage, let automaticDownload = self.automaticDownload, case .full = automaticDownload, case let .Loaded(content) = webpage.content {
|
if let webpage = webpage, let automaticDownload = self.automaticDownload, case .full = automaticDownload, case let .Loaded(content) = webpage.content {
|
||||||
@ -1953,7 +1960,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
state = .customIcon(secretProgressIcon)
|
state = .customIcon(secretProgressIcon)
|
||||||
} else if let file = media as? TelegramMediaFile, !file.isVideoSticker {
|
} else if let file = media as? TelegramMediaFile, !file.isVideoSticker {
|
||||||
let isInlinePlayableVideo = file.isVideo && !isSecretMedia && (self.automaticPlayback ?? false)
|
let isInlinePlayableVideo = file.isVideo && !isSecretMedia && (self.automaticPlayback ?? false)
|
||||||
if !isInlinePlayableVideo && file.isVideo {
|
if (!isInlinePlayableVideo || isStory) && file.isVideo {
|
||||||
state = .play(messageTheme.mediaOverlayControlColors.foregroundColor)
|
state = .play(messageTheme.mediaOverlayControlColors.foregroundColor)
|
||||||
} else {
|
} else {
|
||||||
state = .none
|
state = .none
|
||||||
@ -2208,14 +2215,18 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func transitionNode() -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
func transitionNode(adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
let bounds: CGRect
|
var bounds: CGRect
|
||||||
if let currentImageArguments = self.currentImageArguments {
|
if let currentImageArguments = self.currentImageArguments {
|
||||||
bounds = currentImageArguments.imageRect
|
if adjustRect {
|
||||||
|
bounds = currentImageArguments.drawingRect
|
||||||
|
} else {
|
||||||
|
bounds = currentImageArguments.imageRect
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bounds = self.bounds
|
bounds = self.bounds
|
||||||
}
|
}
|
||||||
return (self, bounds, { [weak self] in
|
return (adjustRect ? self.imageNode : self, bounds, { [weak self] in
|
||||||
var badgeNodeHidden: Bool?
|
var badgeNodeHidden: Bool?
|
||||||
if let badgeNode = self?.badgeNode {
|
if let badgeNode = self?.badgeNode {
|
||||||
badgeNodeHidden = badgeNode.isHidden
|
badgeNodeHidden = badgeNode.isHidden
|
||||||
|
|||||||
@ -129,7 +129,7 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
return self.contentNode.updateHiddenMedia(media)
|
return self.contentNode.updateHiddenMedia(media)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id != messageId {
|
if self.item?.message.id != messageId {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -782,7 +782,7 @@ public class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func transitionNode(id: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -476,7 +476,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id == messageId, let currentMedia = self.media, currentMedia.isEqual(to: media) {
|
if self.item?.message.id == messageId, let currentMedia = self.media, currentMedia.isEqual(to: media) {
|
||||||
let imageNode = self.imageNode
|
let imageNode = self.imageNode
|
||||||
return (self.imageNode, self.imageNode.bounds, { [weak imageNode] in
|
return (self.imageNode, self.imageNode.bounds, { [weak imageNode] in
|
||||||
|
|||||||
@ -398,13 +398,13 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id == messageId, var currentMedia = self.media {
|
if self.item?.message.id == messageId, var currentMedia = self.media {
|
||||||
if let invoice = currentMedia as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia, case let .full(fullMedia) = extendedMedia {
|
if let invoice = currentMedia as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia, case let .full(fullMedia) = extendedMedia {
|
||||||
currentMedia = fullMedia
|
currentMedia = fullMedia
|
||||||
}
|
}
|
||||||
if currentMedia.isSemanticallyEqual(to: media) {
|
if currentMedia.isSemanticallyEqual(to: media) {
|
||||||
return self.interactiveImageNode.transitionNode()
|
return self.interactiveImageNode.transitionNode(adjustRect: adjustRect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -92,7 +92,7 @@ class ChatMessageProfilePhotoSuggestionContentNode: ChatMessageBubbleContentNode
|
|||||||
self.fetchDisposable.dispose()
|
self.fetchDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id == messageId {
|
if self.item?.message.id == messageId {
|
||||||
return (self.imageNode, self.imageNode.bounds, { [weak self] in
|
return (self.imageNode, self.imageNode.bounds, { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
|
|||||||
@ -130,7 +130,7 @@ class ChatMessageWallpaperBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
item.context.account.pendingPeerMediaUploadManager.cancel(peerId: item.message.id.peerId)
|
item.context.account.pendingPeerMediaUploadManager.cancel(peerId: item.message.id.peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id == messageId {
|
if self.item?.message.id == messageId {
|
||||||
return (self.imageNode, self.imageNode.bounds, { [weak self] in
|
return (self.imageNode, self.imageNode.bounds, { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
|
|||||||
@ -76,7 +76,11 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let webpage = webPageContent {
|
if let webpage = webPageContent {
|
||||||
item.controllerInteraction.openUrl(webpage.url, false, nil, nil)
|
if webpage.story != nil {
|
||||||
|
let _ = item.controllerInteraction.openMessage(item.message, .default)
|
||||||
|
} else {
|
||||||
|
item.controllerInteraction.openUrl(webpage.url, false, nil, nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,7 +330,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
case "telegram_chatlist":
|
case "telegram_chatlist":
|
||||||
actionTitle = item.presentationData.strings.Conversation_OpenChatFolder
|
actionTitle = item.presentationData.strings.Conversation_OpenChatFolder
|
||||||
case "telegram_story":
|
case "telegram_story":
|
||||||
actionTitle = "Open Story"
|
actionTitle = "OPEN STORY"
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -523,7 +527,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func transitionNode(messageId: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
override func transitionNode(messageId: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.item?.message.id != messageId {
|
if self.item?.message.id != messageId {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -212,12 +212,12 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
//self?.chatDisplayNode.dismissInput()
|
//self?.chatDisplayNode.dismissInput()
|
||||||
}, present: { c, a in
|
}, present: { c, a in
|
||||||
self?.presentController(c, .window(.root), a)
|
self?.presentController(c, .window(.root), a)
|
||||||
}, transitionNode: { messageId, media in
|
}, transitionNode: { messageId, media, adjustRect in
|
||||||
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.listNode.forEachItemNode { itemNode in
|
strongSelf.listNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageItemView {
|
if let itemNode = itemNode as? ChatMessageItemView {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: adjustRect) {
|
||||||
selectedNode = result
|
selectedNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -380,7 +380,7 @@ final class GridMessageItemNode: GridItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func transitionNode(id: MessageId, media: Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
func transitionNode(id: MessageId, media: Media, adjustRect: Bool) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? {
|
||||||
if self.messageId == id {
|
if self.messageId == id {
|
||||||
let imageNode = self.imageNode
|
let imageNode = self.imageNode
|
||||||
return (self.imageNode, self.imageNode.bounds, { [weak self, weak imageNode] in
|
return (self.imageNode, self.imageNode.bounds, { [weak self, weak imageNode] in
|
||||||
|
|||||||
@ -45,7 +45,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
var transitionIn: StoryContainerScreen.TransitionIn? = nil
|
var transitionIn: StoryContainerScreen.TransitionIn? = nil
|
||||||
|
|
||||||
var selectedTransitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedTransitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
selectedTransitionNode = params.transitionNode(params.message.id, story)
|
selectedTransitionNode = params.transitionNode(params.message.id, story, true)
|
||||||
|
|
||||||
if let selectedTransitionNode {
|
if let selectedTransitionNode {
|
||||||
transitionIn = StoryContainerScreen.TransitionIn(
|
transitionIn = StoryContainerScreen.TransitionIn(
|
||||||
@ -66,7 +66,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
var transitionOut: StoryContainerScreen.TransitionOut? = nil
|
var transitionOut: StoryContainerScreen.TransitionOut? = nil
|
||||||
|
|
||||||
var selectedTransitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedTransitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
selectedTransitionNode = params.transitionNode(params.message.id, story)
|
selectedTransitionNode = params.transitionNode(params.message.id, story, true)
|
||||||
if let selectedTransitionNode {
|
if let selectedTransitionNode {
|
||||||
transitionOut = StoryContainerScreen.TransitionOut(
|
transitionOut = StoryContainerScreen.TransitionOut(
|
||||||
destinationView: selectedTransitionNode.0.view,
|
destinationView: selectedTransitionNode.0.view,
|
||||||
@ -92,9 +92,9 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
let scale = toScale.interpolate(to: fromScale, amount: state.progress)
|
let scale = toScale.interpolate(to: fromScale, amount: state.progress)
|
||||||
transition.setTransform(view: view, transform: CATransform3DMakeScale(scale, scale, 1.0))
|
transition.setTransform(view: view, transform: CATransform3DMakeScale(scale, scale, 1.0))
|
||||||
},
|
},
|
||||||
insertCloneTransitionView: { view in
|
insertCloneTransitionView: nil/*{ view in
|
||||||
params.addToTransitionSurface(view)
|
params.addToTransitionSurface(view)
|
||||||
}
|
}*/
|
||||||
),
|
),
|
||||||
destinationRect: selectedTransitionNode.1,
|
destinationRect: selectedTransitionNode.1,
|
||||||
destinationCornerRadius: 0.0,
|
destinationCornerRadius: 0.0,
|
||||||
@ -145,7 +145,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
params.present(gallery, InstantPageGalleryControllerPresentationArguments(transitionArguments: { entry in
|
params.present(gallery, InstantPageGalleryControllerPresentationArguments(transitionArguments: { entry in
|
||||||
var selectedTransitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var selectedTransitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
if entry.index == centralIndex {
|
if entry.index == centralIndex {
|
||||||
selectedTransitionNode = params.transitionNode(params.message.id, galleryMedia)
|
selectedTransitionNode = params.transitionNode(params.message.id, galleryMedia, false)
|
||||||
}
|
}
|
||||||
if let selectedTransitionNode = selectedTransitionNode {
|
if let selectedTransitionNode = selectedTransitionNode {
|
||||||
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
||||||
@ -277,7 +277,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
params.centralItemUpdated?(messageId)
|
params.centralItemUpdated?(messageId)
|
||||||
}
|
}
|
||||||
params.present(gallery, GalleryControllerPresentationArguments(transitionArguments: { messageId, media in
|
params.present(gallery, GalleryControllerPresentationArguments(transitionArguments: { messageId, media in
|
||||||
let selectedTransitionNode = params.transitionNode(messageId, media)
|
let selectedTransitionNode = params.transitionNode(messageId, media, false)
|
||||||
if let selectedTransitionNode = selectedTransitionNode {
|
if let selectedTransitionNode = selectedTransitionNode {
|
||||||
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
||||||
}
|
}
|
||||||
@ -288,7 +288,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
case let .secretGallery(gallery):
|
case let .secretGallery(gallery):
|
||||||
params.dismissInput()
|
params.dismissInput()
|
||||||
params.present(gallery, GalleryControllerPresentationArguments(transitionArguments: { messageId, media in
|
params.present(gallery, GalleryControllerPresentationArguments(transitionArguments: { messageId, media in
|
||||||
let selectedTransitionNode = params.transitionNode(messageId, media)
|
let selectedTransitionNode = params.transitionNode(messageId, media, false)
|
||||||
if let selectedTransitionNode = selectedTransitionNode {
|
if let selectedTransitionNode = selectedTransitionNode {
|
||||||
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
||||||
}
|
}
|
||||||
@ -332,7 +332,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
|
|||||||
}, media)
|
}, media)
|
||||||
|
|
||||||
params.present(controller, AvatarGalleryControllerPresentationArguments(transitionArguments: { entry in
|
params.present(controller, AvatarGalleryControllerPresentationArguments(transitionArguments: { entry in
|
||||||
if let selectedTransitionNode = params.transitionNode(params.message.id, media) {
|
if let selectedTransitionNode = params.transitionNode(params.message.id, media, false) {
|
||||||
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
return GalleryTransitionArguments(transitionNode: selectedTransitionNode, addToTransitionSurface: params.addToTransitionSurface)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -296,7 +296,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
if let location = strongSelf.playlistLocation as? PeerMessagesPlaylistLocation, case let .custom(messages, _, loadMore) = location {
|
if let location = strongSelf.playlistLocation as? PeerMessagesPlaylistLocation, case let .custom(messages, _, loadMore) = location {
|
||||||
playlistLocation = .custom(messages: messages, at: id, loadMore: loadMore)
|
playlistLocation = .custom(messages: messages, at: id, loadMore: loadMore)
|
||||||
}
|
}
|
||||||
return strongSelf.context.sharedContext.openChatMessage(OpenChatMessageParams(context: strongSelf.context, chatLocation: nil, chatLocationContextHolder: nil, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: nil, dismissInput: { }, present: { _, _ in }, transitionNode: { _, _ in return nil }, addToTransitionSurface: { _ in }, openUrl: { _ in }, openPeer: { _, _ in }, callPeer: { _, _ in }, enqueueMessage: { _ in }, sendSticker: nil, sendEmoji: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in }, playlistLocation: playlistLocation))
|
return strongSelf.context.sharedContext.openChatMessage(OpenChatMessageParams(context: strongSelf.context, chatLocation: nil, chatLocationContextHolder: nil, message: message, standalone: false, reverseMessageGalleryOrder: false, navigationController: nil, dismissInput: { }, present: { _, _ in }, transitionNode: { _, _, _ in return nil }, addToTransitionSurface: { _ in }, openUrl: { _ in }, openPeer: { _, _ in }, callPeer: { _, _ in }, enqueueMessage: { _ in }, sendSticker: nil, sendEmoji: nil, setupTemporaryHiddenMedia: { _, _, _ in }, chatAvatarHiddenMedia: { _, _ in }, playlistLocation: playlistLocation))
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -502,7 +502,7 @@ final class PeerInfoListPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
|||||||
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?
|
||||||
self.listNode.forEachItemNode { itemNode in
|
self.listNode.forEachItemNode { itemNode in
|
||||||
if let itemNode = itemNode as? ListMessageNode {
|
if let itemNode = itemNode as? ListMessageNode {
|
||||||
if let result = itemNode.transitionNode(id: messageId, media: media) {
|
if let result = itemNode.transitionNode(id: messageId, media: media, adjustRect: false) {
|
||||||
transitionNode = result
|
transitionNode = result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4094,7 +4094,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
private func openStories(fromAvatar: Bool) {
|
private func openStories(fromAvatar: Bool) {
|
||||||
if let expiringStoryList = self.expiringStoryList, let expiringStoryListState = self.expiringStoryListState, !expiringStoryListState.items.isEmpty {
|
if let expiringStoryList = self.expiringStoryList, let expiringStoryListState = self.expiringStoryListState, !expiringStoryListState.items.isEmpty {
|
||||||
let _ = expiringStoryList
|
let _ = expiringStoryList
|
||||||
let storyContent = StoryContentContextImpl(context: self.context, includeHidden: false, focusedPeerId: self.peerId, singlePeer: true)
|
let storyContent = StoryContentContextImpl(context: self.context, isHidden: false, focusedPeerId: self.peerId, singlePeer: true)
|
||||||
let _ = (storyContent.state
|
let _ = (storyContent.state
|
||||||
|> take(1)
|
|> take(1)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
|> deliverOnMainQueue).start(next: { [weak self] storyContentState in
|
||||||
@ -4174,7 +4174,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
self?.view.endEditing(true)
|
self?.view.endEditing(true)
|
||||||
}, present: { [weak self] c, a in
|
}, present: { [weak self] c, a in
|
||||||
self?.controller?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
self?.controller?.present(c, in: .window(.root), with: a, blockInteraction: true)
|
||||||
}, transitionNode: { [weak self] messageId, media in
|
}, transitionNode: { [weak self] messageId, media, _ in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user