Restore changes

This commit is contained in:
Ali 2023-07-04 12:12:16 +02:00
parent e0b11ea319
commit 624d0d49d5
16 changed files with 217 additions and 82 deletions

View File

@ -1243,7 +1243,7 @@ public final class ChatListNode: ListView {
super.init() super.init()
self.useMainQueueTransactions = true //self.useMainQueueTransactions = true
self.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor self.verticalScrollIndicatorColor = theme.list.scrollIndicatorColor
self.verticalScrollIndicatorFollowsOverscroll = true self.verticalScrollIndicatorFollowsOverscroll = true

View File

@ -840,8 +840,8 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
self.controlsContainerNode.addSubnode(self.stripContainerNode) self.controlsContainerNode.addSubnode(self.stripContainerNode)
self.controlsClippingNode.addSubnode(self.controlsContainerNode) self.controlsClippingNode.addSubnode(self.controlsContainerNode)
self.controlsClippingOffsetNode.addSubnode(self.controlsClippingNode) self.controlsClippingOffsetNode.addSubnode(self.controlsClippingNode)
self.stripContainerNode.addSubnode(self.setByYouNode) self.addSubnode(self.setByYouNode)
self.stripContainerNode.addSubnode(self.setByYouImageNode) self.addSubnode(self.setByYouImageNode)
self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -1435,7 +1435,7 @@ public final class PeerInfoAvatarListContainerNode: ASDisplayNode {
transition.updateAlpha(node: self.setByYouNode, alpha: 0.7) transition.updateAlpha(node: self.setByYouNode, alpha: 0.7)
self.setByYouNode.attributedText = NSAttributedString(string: photoTitle, font: Font.regular(12.0), textColor: UIColor.white) self.setByYouNode.attributedText = NSAttributedString(string: photoTitle, font: Font.regular(12.0), textColor: UIColor.white)
let setByYouSize = self.setByYouNode.updateLayout(size) let setByYouSize = self.setByYouNode.updateLayout(size)
self.setByYouNode.frame = CGRect(origin: CGPoint(x: size.width - setByYouSize.width - 14.0, y: size.height - setByYouSize.height - 58.0), size: setByYouSize) self.setByYouNode.frame = CGRect(origin: CGPoint(x: size.width - setByYouSize.width - 14.0, y: size.height - setByYouSize.height - 18.0), size: setByYouSize)
self.setByYouNode.isUserInteractionEnabled = hasLink self.setByYouNode.isUserInteractionEnabled = hasLink
} else { } else {
transition.updateAlpha(node: self.setByYouNode, alpha: 0.0) transition.updateAlpha(node: self.setByYouNode, alpha: 0.0)

View File

@ -284,6 +284,8 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
public var isReactionSearchActive: Bool = false public var isReactionSearchActive: Bool = false
public var reduceMotion: Bool = false
public static func randomGenericReactionEffect(context: AccountContext) -> Signal<String?, NoError> { public static func randomGenericReactionEffect(context: AccountContext) -> Signal<String?, NoError> {
return context.engine.stickers.loadedStickerPack(reference: .emojiGenericAnimations, forceActualized: false) return context.engine.stickers.loadedStickerPack(reference: .emojiGenericAnimations, forceActualized: false)
|> map { result -> [TelegramMediaFile]? in |> map { result -> [TelegramMediaFile]? in
@ -907,7 +909,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
} }
if animateIn { if animateIn {
itemNode.appear(animated: !self.context.sharedContext.currentPresentationData.with({ $0 }).reduceMotion) itemNode.appear(animated: !self.context.sharedContext.currentPresentationData.with({ $0 }).reduceMotion && !self.reduceMotion)
} }
if self.getEmojiContent != nil, i == itemLayout.visibleItemCount - 1, let itemNode = itemNode as? ReactionNode { if self.getEmojiContent != nil, i == itemLayout.visibleItemCount - 1, let itemNode = itemNode as? ReactionNode {
@ -1197,7 +1199,7 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
} }
} }
if let animateInFromAnchorRect = animateInFromAnchorRect { if let animateInFromAnchorRect = animateInFromAnchorRect, !self.reduceMotion {
let springDuration: Double = 0.5 let springDuration: Double = 0.5
let springDamping: CGFloat = 104.0 let springDamping: CGFloat = 104.0
let springScaleDelay: Double = 0.1 let springScaleDelay: Double = 0.1
@ -1606,11 +1608,13 @@ public final class ReactionContextNode: ASDisplayNode, UIScrollViewDelegate {
let mainCircleDelay: Double = 0.01 let mainCircleDelay: Double = 0.01
if !self.presentationData.reduceMotion && !self.reduceMotion {
self.backgroundNode.animateIn() self.backgroundNode.animateIn()
}
self.didAnimateIn = true self.didAnimateIn = true
if !self.presentationData.reduceMotion { if !self.presentationData.reduceMotion && !self.reduceMotion {
for i in 0 ..< self.items.count { for i in 0 ..< self.items.count {
guard let itemNode = self.visibleItemNodes[i] else { guard let itemNode = self.visibleItemNodes[i] else {
continue continue

View File

@ -466,17 +466,18 @@ public final class PeerStoryListContext {
self.peerId = peerId self.peerId = peerId
self.isArchived = isArchived self.isArchived = isArchived
self.stateValue = State(peerReference: nil, items: [], totalCount: 0, loadMoreToken: 0, isCached: true) self.stateValue = State(peerReference: nil, items: [], totalCount: 0, loadMoreToken: 0, isCached: true, allEntityFiles: [:])
let _ = (account.postbox.transaction { transaction -> (PeerReference?, [EngineStoryItem], Int) in let _ = (account.postbox.transaction { transaction -> (PeerReference?, [EngineStoryItem], Int, [MediaId: TelegramMediaFile]) in
let key = ValueBoxKey(length: 8 + 1) let key = ValueBoxKey(length: 8 + 1)
key.setInt64(0, value: peerId.toInt64()) key.setInt64(0, value: peerId.toInt64())
key.setInt8(8, value: isArchived ? 1 : 0) key.setInt8(8, value: isArchived ? 1 : 0)
let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerStoryListHeads, key: key))?.get(CachedPeerStoryListHead.self) let cached = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPeerStoryListHeads, key: key))?.get(CachedPeerStoryListHead.self)
guard let cached = cached else { guard let cached = cached else {
return (nil, [], 0) return (nil, [], 0, [:])
} }
var items: [EngineStoryItem] = [] var items: [EngineStoryItem] = []
var allEntityFiles: [MediaId: TelegramMediaFile] = [:]
for storedItem in cached.items { for storedItem in cached.items {
if case let .item(item) = storedItem, let media = item.media { if case let .item(item) = storedItem, let media = item.media {
let mappedItem = EngineStoryItem( let mappedItem = EngineStoryItem(
@ -504,19 +505,30 @@ public final class PeerStoryListContext {
isEdited: item.isEdited isEdited: item.isEdited
) )
items.append(mappedItem) items.append(mappedItem)
for entity in mappedItem.entities {
if case let .CustomEmoji(_, fileId) = entity.type {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if allEntityFiles[mediaId] == nil {
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
allEntityFiles[file.fileId] = file
}
}
}
}
} }
} }
let peerReference = transaction.getPeer(peerId).flatMap(PeerReference.init) let peerReference = transaction.getPeer(peerId).flatMap(PeerReference.init)
return (peerReference, items, Int(cached.totalCount)) return (peerReference, items, Int(cached.totalCount), allEntityFiles)
} }
|> deliverOn(self.queue)).start(next: { [weak self] peerReference, items, totalCount in |> deliverOn(self.queue)).start(next: { [weak self] peerReference, items, totalCount, allEntityFiles in
guard let `self` = self else { guard let `self` = self else {
return return
} }
self.stateValue = State(peerReference: peerReference, items: items, totalCount: totalCount, loadMoreToken: 0, isCached: true) self.stateValue = State(peerReference: peerReference, items: items, totalCount: totalCount, loadMoreToken: 0, isCached: true, allEntityFiles: allEntityFiles)
self.loadMore() self.loadMore()
}) })
} }
@ -828,19 +840,22 @@ public final class PeerStoryListContext {
public var totalCount: Int public var totalCount: Int
public var loadMoreToken: Int? public var loadMoreToken: Int?
public var isCached: Bool public var isCached: Bool
public var allEntityFiles: [MediaId: TelegramMediaFile]
init( init(
peerReference: PeerReference?, peerReference: PeerReference?,
items: [EngineStoryItem], items: [EngineStoryItem],
totalCount: Int, totalCount: Int,
loadMoreToken: Int?, loadMoreToken: Int?,
isCached: Bool isCached: Bool,
allEntityFiles: [MediaId: TelegramMediaFile]
) { ) {
self.peerReference = peerReference self.peerReference = peerReference
self.items = items self.items = items
self.totalCount = totalCount self.totalCount = totalCount
self.loadMoreToken = loadMoreToken self.loadMoreToken = loadMoreToken
self.isCached = isCached self.isCached = isCached
self.allEntityFiles = allEntityFiles
} }
} }

View File

@ -145,7 +145,7 @@ public final class ChatListNavigationBar: Component {
public static let searchScrollHeight: CGFloat = 52.0 public static let searchScrollHeight: CGFloat = 52.0
public static let storiesScrollHeight: CGFloat = { public static let storiesScrollHeight: CGFloat = {
return 79.0 return 83.0
}() }()
public final class View: UIView { public final class View: UIView {
@ -404,7 +404,7 @@ public final class ChatListNavigationBar: Component {
if component.statusBarHeight < 1.0 { if component.statusBarHeight < 1.0 {
headerContentY = 0.0 headerContentY = 0.0
} else { } else {
headerContentY = component.statusBarHeight + 12.0 headerContentY = component.statusBarHeight + 5.0
} }
} }
let headerContentFrame = CGRect(origin: CGPoint(x: 0.0, y: headerContentY), size: headerContentSize) let headerContentFrame = CGRect(origin: CGPoint(x: 0.0, y: headerContentY), size: headerContentSize)
@ -579,7 +579,7 @@ public final class ChatListNavigationBar: Component {
var contentHeight = component.statusBarHeight var contentHeight = component.statusBarHeight
if component.statusBarHeight >= 1.0 { if component.statusBarHeight >= 1.0 {
contentHeight += 10.0 contentHeight += 3.0
} }
contentHeight += 44.0 contentHeight += 44.0

View File

@ -63,9 +63,11 @@ public final class StoryContentContextImpl: StoryContentContext {
), ),
context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global()) context.engine.data.subscribe(TelegramEngine.EngineData.Item.NotificationSettings.Global())
) )
|> mapToSignal { _, views, globalNotificationSettings -> Signal<(CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings), NoError> in |> mapToSignal { _, views, globalNotificationSettings -> Signal<(CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings, [MediaId: TelegramMediaFile]), NoError> in
return context.account.postbox.transaction { transaction -> (CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings) in return context.account.postbox.transaction { transaction -> (CombinedView, [PeerId: Peer], EngineGlobalNotificationSettings, [MediaId: TelegramMediaFile]) in
var peers: [PeerId: Peer] = [:] var peers: [PeerId: Peer] = [:]
var allEntityFiles: [MediaId: TelegramMediaFile] = [:]
if let itemsView = views.views[PostboxViewKey.storyItems(peerId: peerId)] as? StoryItemsView { if let itemsView = views.views[PostboxViewKey.storyItems(peerId: peerId)] as? StoryItemsView {
for item in itemsView.items { for item in itemsView.items {
if let item = item.value.get(Stories.StoredItem.self), case let .item(itemValue) = item { if let item = item.value.get(Stories.StoredItem.self), case let .item(itemValue) = item {
@ -76,13 +78,24 @@ public final class StoryContentContextImpl: StoryContentContext {
} }
} }
} }
for entity in itemValue.entities {
if case let .CustomEmoji(_, fileId) = entity.type {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if allEntityFiles[mediaId] == nil {
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
allEntityFiles[file.fileId] = file
} }
} }
} }
return (views, peers, globalNotificationSettings)
} }
} }
|> deliverOnMainQueue).start(next: { [weak self] views, peers, globalNotificationSettings in }
}
return (views, peers, globalNotificationSettings, allEntityFiles)
}
}
|> deliverOnMainQueue).start(next: { [weak self] views, peers, globalNotificationSettings, allEntityFiles in
guard let self else { guard let self else {
return return
} }
@ -257,7 +270,8 @@ public final class StoryContentContextImpl: StoryContentContext {
return StoryContentItem( return StoryContentItem(
position: nil, position: nil,
peerId: peer.id, peerId: peer.id,
storyItem: item storyItem: item,
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: allEntityFiles)
) )
} }
@ -268,7 +282,8 @@ public final class StoryContentContextImpl: StoryContentContext {
item: StoryContentItem( item: StoryContentItem(
position: mappedFocusedIndex ?? focusedIndex, position: mappedFocusedIndex ?? focusedIndex,
peerId: peer.id, peerId: peer.id,
storyItem: mappedItem storyItem: mappedItem,
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles)
), ),
totalCount: totalCount, totalCount: totalCount,
previousItemId: previousItemId, previousItemId: previousItemId,
@ -907,11 +922,12 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: storyId.peerId), TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: storyId.peerId),
TelegramEngine.EngineData.Item.NotificationSettings.Global() TelegramEngine.EngineData.Item.NotificationSettings.Global()
), ),
context.account.postbox.transaction { transaction -> (Stories.StoredItem?, [PeerId: Peer]) in context.account.postbox.transaction { transaction -> (Stories.StoredItem?, [PeerId: Peer], [MediaId: TelegramMediaFile]) in
guard let item = transaction.getStory(id: storyId)?.get(Stories.StoredItem.self) else { guard let item = transaction.getStory(id: storyId)?.get(Stories.StoredItem.self) else {
return (nil, [:]) return (nil, [:], [:])
} }
var peers: [PeerId: Peer] = [:] var peers: [PeerId: Peer] = [:]
var allEntityFiles: [MediaId: TelegramMediaFile] = [:]
if case let .item(item) = item { if case let .item(item) = item {
if let views = item.views { if let views = item.views {
for id in views.seenPeerIds { for id in views.seenPeerIds {
@ -920,8 +936,18 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
} }
} }
} }
for entity in item.entities {
if case let .CustomEmoji(_, fileId) = entity.type {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if allEntityFiles[mediaId] == nil {
if let file = transaction.getMedia(mediaId) as? TelegramMediaFile {
allEntityFiles[file.fileId] = file
} }
return (item, peers) }
}
}
}
return (item, peers, allEntityFiles)
} }
) )
|> deliverOnMainQueue).start(next: { [weak self] data, itemAndPeers in |> deliverOnMainQueue).start(next: { [weak self] data, itemAndPeers in
@ -930,7 +956,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
} }
let (peer, areVoiceMessagesAvailable, notificationSettings, globalNotificationSettings) = data let (peer, areVoiceMessagesAvailable, notificationSettings, globalNotificationSettings) = data
let (item, peers) = itemAndPeers let (item, peers, allEntityFiles) = itemAndPeers
guard let peer else { guard let peer else {
return return
@ -981,7 +1007,8 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
let mainItem = StoryContentItem( let mainItem = StoryContentItem(
position: 0, position: 0,
peerId: peer.id, peerId: peer.id,
storyItem: mappedItem storyItem: mappedItem,
entityFiles: extractItemEntityFiles(item: mappedItem, allEntityFiles: allEntityFiles)
) )
let stateValue = StoryContentContextState( let stateValue = StoryContentContextState(
slice: StoryContentContextState.FocusedSlice( slice: StoryContentContextState.FocusedSlice(
@ -1130,7 +1157,8 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
return StoryContentItem( return StoryContentItem(
position: nil, position: nil,
peerId: peer.id, peerId: peer.id,
storyItem: stateItem storyItem: stateItem,
entityFiles: extractItemEntityFiles(item: stateItem, allEntityFiles: state.allEntityFiles)
) )
} }
@ -1141,7 +1169,8 @@ public final class PeerStoryListContentContextImpl: StoryContentContext {
item: StoryContentItem( item: StoryContentItem(
position: nil, position: nil,
peerId: peer.id, peerId: peer.id,
storyItem: item storyItem: item,
entityFiles: extractItemEntityFiles(item: item, allEntityFiles: state.allEntityFiles)
), ),
totalCount: state.totalCount, totalCount: state.totalCount,
previousItemId: focusedIndex == 0 ? nil : state.items[focusedIndex - 1].id, previousItemId: focusedIndex == 0 ? nil : state.items[focusedIndex - 1].id,
@ -1326,3 +1355,16 @@ public func preloadStoryMedia(context: AccountContext, peer: PeerReference, stor
return combineLatest(signals) |> ignoreValues return combineLatest(signals) |> ignoreValues
} }
func extractItemEntityFiles(item: EngineStoryItem, allEntityFiles: [MediaId: TelegramMediaFile]) -> [MediaId: TelegramMediaFile] {
var result: [MediaId: TelegramMediaFile] = [:]
for entity in item.entities {
if case let .CustomEmoji(_, fileId) = entity.type {
let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
if let file = allEntityFiles[mediaId] {
result[file.fileId] = file
}
}
}
return result
}

View File

@ -80,15 +80,18 @@ public final class StoryContentItem: Equatable {
public let position: Int? public let position: Int?
public let peerId: EnginePeer.Id? public let peerId: EnginePeer.Id?
public let storyItem: EngineStoryItem public let storyItem: EngineStoryItem
public let entityFiles: [EngineMedia.Id: TelegramMediaFile]
public init( public init(
position: Int?, position: Int?,
peerId: EnginePeer.Id?, peerId: EnginePeer.Id?,
storyItem: EngineStoryItem storyItem: EngineStoryItem,
entityFiles: [EngineMedia.Id: TelegramMediaFile]
) { ) {
self.position = position self.position = position
self.peerId = peerId self.peerId = peerId
self.storyItem = storyItem self.storyItem = storyItem
self.entityFiles = entityFiles
} }
public static func ==(lhs: StoryContentItem, rhs: StoryContentItem) -> Bool { public static func ==(lhs: StoryContentItem, rhs: StoryContentItem) -> Bool {
@ -101,6 +104,9 @@ public final class StoryContentItem: Equatable {
if lhs.storyItem != rhs.storyItem { if lhs.storyItem != rhs.storyItem {
return false return false
} }
if lhs.entityFiles != rhs.entityFiles {
return false
}
return true return true
} }
} }

View File

@ -43,6 +43,7 @@ final class StoryContentCaptionComponent: Component {
let context: AccountContext let context: AccountContext
let text: String let text: String
let entities: [MessageTextEntity] let entities: [MessageTextEntity]
let entityFiles: [EngineMedia.Id: TelegramMediaFile]
let action: (Action) -> Void let action: (Action) -> Void
init( init(
@ -50,12 +51,14 @@ final class StoryContentCaptionComponent: Component {
context: AccountContext, context: AccountContext,
text: String, text: String,
entities: [MessageTextEntity], entities: [MessageTextEntity],
entityFiles: [EngineMedia.Id: TelegramMediaFile],
action: @escaping (Action) -> Void action: @escaping (Action) -> Void
) { ) {
self.externalState = externalState self.externalState = externalState
self.context = context self.context = context
self.text = text self.text = text
self.entities = entities self.entities = entities
self.entityFiles = entityFiles
self.action = action self.action = action
} }
@ -72,6 +75,9 @@ final class StoryContentCaptionComponent: Component {
if lhs.entities != rhs.entities { if lhs.entities != rhs.entities {
return false return false
} }
if lhs.entityFiles != rhs.entityFiles {
return false
}
return true return true
} }
@ -359,7 +365,8 @@ final class StoryContentCaptionComponent: Component {
boldItalicFont: Font.semiboldItalic(16.0), boldItalicFont: Font.semiboldItalic(16.0),
fixedFont: Font.monospace(16.0), fixedFont: Font.monospace(16.0),
blockQuoteFont: Font.monospace(16.0), blockQuoteFont: Font.monospace(16.0),
message: nil message: nil,
entityFiles: component.entityFiles
) )
let makeLayout = TextNodeWithEntities.asyncLayout(self.textNode) let makeLayout = TextNodeWithEntities.asyncLayout(self.textNode)

View File

@ -2518,6 +2518,7 @@ public final class StoryItemSetContainerComponent: Component {
context: component.context, context: component.context,
text: component.slice.item.storyItem.text, text: component.slice.item.storyItem.text,
entities: component.slice.item.storyItem.entities, entities: component.slice.item.storyItem.entities,
entityFiles: component.slice.item.entityFiles,
action: { [weak self] action in action: { [weak self] action in
guard let self, let component = self.component else { guard let self, let component = self.component else {
return return
@ -2649,7 +2650,7 @@ public final class StoryItemSetContainerComponent: Component {
reactionContextNode.displayTail = false reactionContextNode.displayTail = false
self.reactionContextNode = reactionContextNode self.reactionContextNode = reactionContextNode
reactionContextNode.reactionSelected = { [weak self] updateReaction, _ in reactionContextNode.reactionSelected = { [weak self, weak reactionContextNode] updateReaction, _ in
guard let self, let component = self.component else { guard let self, let component = self.component else {
return return
} }
@ -2673,6 +2674,7 @@ public final class StoryItemSetContainerComponent: Component {
targetView.isUserInteractionEnabled = false targetView.isUserInteractionEnabled = false
self.addSubview(targetView) self.addSubview(targetView)
if let reactionContextNode {
reactionContextNode.willAnimateOutToReaction(value: updateReaction.reaction) reactionContextNode.willAnimateOutToReaction(value: updateReaction.reaction)
reactionContextNode.animateOutToReaction(value: updateReaction.reaction, targetView: targetView, hideNode: false, animateTargetContainer: nil, addStandaloneReactionAnimation: "".isEmpty ? nil : { [weak self] standaloneReactionAnimation in reactionContextNode.animateOutToReaction(value: updateReaction.reaction, targetView: targetView, hideNode: false, animateTargetContainer: nil, addStandaloneReactionAnimation: "".isEmpty ? nil : { [weak self] standaloneReactionAnimation in
guard let self else { guard let self else {
@ -2689,7 +2691,7 @@ public final class StoryItemSetContainerComponent: Component {
}) })
} }
}) })
}
if hasFirstResponder(self) { if hasFirstResponder(self) {
self.sendMessageContext.currentInputMode = .text self.sendMessageContext.currentInputMode = .text

View File

@ -345,7 +345,7 @@ public final class StorySetIndicatorComponent: Component {
if component.hasUnseen { if component.hasUnseen {
borderColors = [component.theme.chatList.storyUnseenColors.topColor.argb, component.theme.chatList.storyUnseenColors.bottomColor.argb] borderColors = [component.theme.chatList.storyUnseenColors.topColor.argb, component.theme.chatList.storyUnseenColors.bottomColor.argb]
} else { } else {
borderColors = [component.theme.chatList.storySeenColors.topColor.argb, component.theme.chatList.storySeenColors.bottomColor.argb] borderColors = [UIColor(white: 1.0, alpha: 0.3).argb, UIColor(white: 1.0, alpha: 0.3).argb]
} }
let imageSize = CGSize(width: maxItemsWidth, height: outerDiameter) let imageSize = CGSize(width: maxItemsWidth, height: outerDiameter)

View File

@ -254,6 +254,10 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
return nil return nil
} }
func targetForStoryTransition(id: StoryId) -> UIView? {
return nil
}
func getStatusNode() -> ASDisplayNode? { func getStatusNode() -> ASDisplayNode? {
return nil return nil
} }

View File

@ -4589,6 +4589,11 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
guard let item = self.item else { guard let item = self.item else {
return nil return nil
} }
for contentNode in self.contentNodes {
if let value = contentNode.targetForStoryTransition(id: id) {
return value
}
}
for attribute in item.message.attributes { for attribute in item.message.attributes {
if let attribute = attribute as? ReplyStoryAttribute { if let attribute = attribute as? ReplyStoryAttribute {
if attribute.storyId == id { if attribute.storyId == id {

View File

@ -429,6 +429,10 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
return nil return nil
} }
override func targetForStoryTransition(id: StoryId) -> UIView? {
return self.interactiveVideoNode.targetForStoryTransition(id: id)
}
override var disablesClipping: Bool { override var disablesClipping: Bool {
return true return true
} }

View File

@ -431,6 +431,8 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
} }
} }
var replyMessage: Message?
var replyStory: StoryId?
for attribute in item.message.attributes { for attribute in item.message.attributes {
if let attribute = attribute as? InlineBotMessageAttribute { if let attribute = attribute as? InlineBotMessageAttribute {
var inlineBotNameString: String? var inlineBotNameString: String?
@ -467,28 +469,34 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
} }
} }
if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] { if let replyAttribute = attribute as? ReplyMessageAttribute {
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId { if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
} else { } else {
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
}
} else if let attribute = attribute as? ReplyStoryAttribute {
replyStory = attribute.storyId
} else if let _ = attribute as? InlineBotMessageAttribute {
} else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty {
replyMarkup = attribute
}
}
if replyMessage != nil || replyStory != nil {
replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments( replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments(
presentationData: item.presentationData, presentationData: item.presentationData,
strings: item.presentationData.strings, strings: item.presentationData.strings,
context: item.context, context: item.context,
type: .standalone, type: .standalone,
message: replyMessage, message: replyMessage,
story: nil, story: replyStory,
parentMessage: item.message, parentMessage: item.message,
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude), constrainedSize: CGSize(width: max(0, availableWidth), height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache, animationCache: item.controllerInteraction.presentationContext.animationCache,
animationRenderer: item.controllerInteraction.presentationContext.animationRenderer, animationRenderer: item.controllerInteraction.presentationContext.animationRenderer,
associatedData: item.associatedData associatedData: item.associatedData
)) ))
} }
} else if let _ = attribute as? InlineBotMessageAttribute {
} else if let attribute = attribute as? ReplyMarkupMessageAttribute, attribute.flags.contains(.inline), !attribute.rows.isEmpty {
replyMarkup = attribute
}
}
var updatedShareButtonNode: ChatMessageShareButton? var updatedShareButtonNode: ChatMessageShareButton?
if needsShareButton { if needsShareButton {

View File

@ -316,6 +316,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
let availableContentWidth = width - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0 let availableContentWidth = width - bubbleEdgeInset * 2.0 - bubbleContentInsetsLeft - 20.0
if !ignoreHeaders { if !ignoreHeaders {
var replyMessage: Message?
var replyStory: StoryId?
for attribute in item.message.attributes { for attribute in item.message.attributes {
if let attribute = attribute as? InlineBotMessageAttribute { if let attribute = attribute as? InlineBotMessageAttribute {
var inlineBotNameString: String? var inlineBotNameString: String?
@ -338,8 +341,18 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
} }
} }
if let replyAttribute = attribute as? ReplyMessageAttribute, let replyMessage = item.message.associatedMessages[replyAttribute.messageId] { if let replyAttribute = attribute as? ReplyMessageAttribute {
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId { if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
} else {
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
}
} else if let attribute = attribute as? ReplyStoryAttribute {
replyStory = attribute.storyId
}
}
if replyMessage != nil || replyStory != nil {
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyMessage?.id {
} else { } else {
replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments( replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments(
presentationData: item.presentationData, presentationData: item.presentationData,
@ -347,7 +360,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
context: item.context, context: item.context,
type: .standalone, type: .standalone,
message: replyMessage, message: replyMessage,
story: nil, story: replyStory,
parentMessage: item.message, parentMessage: item.message,
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude), constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
animationCache: item.controllerInteraction.presentationContext.animationCache, animationCache: item.controllerInteraction.presentationContext.animationCache,
@ -357,7 +370,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
} }
} }
} }
}
if !ignoreSource && !ignoreHeaders, !item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) { if !ignoreSource && !ignoreHeaders, !item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
for attribute in item.message.attributes { for attribute in item.message.attributes {
@ -1259,6 +1271,9 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
if let attribute = attribute as? ReplyMessageAttribute { if let attribute = attribute as? ReplyMessageAttribute {
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId) item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId)
return return
} else if let attribute = attribute as? ReplyStoryAttribute {
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
return
} }
} }
} }
@ -1815,4 +1830,20 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
self.canAttachContent = false self.canAttachContent = false
} }
func targetForStoryTransition(id: StoryId) -> UIView? {
guard let item = self.item else {
return nil
}
for attribute in item.message.attributes {
if let attribute = attribute as? ReplyStoryAttribute {
if attribute.storyId == id {
if let replyInfoNode = self.replyInfoNode {
return replyInfoNode.mediaTransitionView()
}
}
}
}
return nil
}
} }

View File

@ -52,7 +52,7 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M
return string return string
} }
public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?) -> NSAttributedString { public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEntity], baseColor: UIColor, linkColor: UIColor, baseFont: UIFont, linkFont: UIFont, boldFont: UIFont, italicFont: UIFont, boldItalicFont: UIFont, fixedFont: UIFont, blockQuoteFont: UIFont, underlineLinks: Bool = true, external: Bool = false, message: Message?, entityFiles: [MediaId: TelegramMediaFile] = [:]) -> NSAttributedString {
var nsString: NSString? var nsString: NSString?
let string = NSMutableAttributedString(string: text, attributes: [NSAttributedString.Key.font: baseFont, NSAttributedString.Key.foregroundColor: baseColor]) let string = NSMutableAttributedString(string: text, attributes: [NSAttributedString.Key.font: baseFont, NSAttributedString.Key.foregroundColor: baseColor])
var skipEntity = false var skipEntity = false
@ -252,7 +252,14 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
} }
} }
case let .CustomEmoji(_, fileId): case let .CustomEmoji(_, fileId):
string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: message?.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile), range: range) let mediaId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
var emojiFile: TelegramMediaFile?
if let file = message?.associatedMedia[mediaId] as? TelegramMediaFile {
emojiFile = file
} else {
emojiFile = entityFiles[mediaId]
}
string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: fileId, file: emojiFile), range: range)
default: default:
break break
} }