mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
InstantPage rich messages: index embedded media into shared-media tags
Add InstantPage.allMedia() (recursive gatherer over the page's blocks — audio/collage/cover/details/image/list/slideshow/video — resolving each via the page's [MediaId: Media] dict) and feed it into tagsForStoreMessage, so a rich message's instant-page media is indexed into MessageTags (photo/photoOrVideo/video/gif/voice/file). Rich messages now appear in the per-peer shared-media tabs and tag-queried surfaces. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
41aef1c928
commit
c95e014681
2 changed files with 134 additions and 0 deletions
|
|
@ -7,6 +7,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
|
|||
var isSecret = false
|
||||
var isUnconsumedPersonalMention = false
|
||||
var hasUnseenReactions = false
|
||||
var richText: RichTextMessageAttribute?
|
||||
for attribute in attributes {
|
||||
if let timerAttribute = attribute as? AutoclearTimeoutMessageAttribute {
|
||||
if timerAttribute.timeout > 0 && (timerAttribute.timeout <= 60 || timerAttribute.timeout == viewOnceTimeout) {
|
||||
|
|
@ -22,6 +23,8 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
|
|||
}
|
||||
} else if let attribute = attribute as? ReactionsMessageAttribute, attribute.hasUnseen {
|
||||
hasUnseenReactions = true
|
||||
} else if let attribute = attribute as? RichTextMessageAttribute {
|
||||
richText = attribute
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +137,63 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
|
|||
tags.insert(.unseenPollVote)
|
||||
}
|
||||
|
||||
if let attribute = richText {
|
||||
//TODO:rewrite to take all media
|
||||
for media in attribute.instantPage.allMedia() {
|
||||
switch media {
|
||||
case _ as TelegramMediaImage:
|
||||
tags.insert(.photo)
|
||||
tags.insert(.photoOrVideo)
|
||||
case let file as TelegramMediaFile:
|
||||
var refinedTag: MessageTags? = .file
|
||||
var isAnimated = false
|
||||
inner: for attribute in file.attributes {
|
||||
switch attribute {
|
||||
case let .Video(_, _, flags, _, _, _):
|
||||
if flags.contains(.instantRoundVideo) {
|
||||
refinedTag = .voiceOrInstantVideo
|
||||
} else {
|
||||
if !isSecret {
|
||||
refinedTag = [.photoOrVideo, .video]
|
||||
} else {
|
||||
refinedTag = nil
|
||||
}
|
||||
}
|
||||
case let .Audio(isVoice, _, _, _, _):
|
||||
if isVoice {
|
||||
refinedTag = .voiceOrInstantVideo
|
||||
} else {
|
||||
if file.isInstantVideo {
|
||||
refinedTag = .voiceOrInstantVideo
|
||||
} else {
|
||||
refinedTag = .music
|
||||
}
|
||||
}
|
||||
break inner
|
||||
case .Sticker:
|
||||
refinedTag = nil
|
||||
break inner
|
||||
case .Animated:
|
||||
isAnimated = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
if isAnimated {
|
||||
refinedTag = .gif
|
||||
}
|
||||
if file.isAnimatedSticker {
|
||||
refinedTag = nil
|
||||
}
|
||||
if let refinedTag {
|
||||
tags.insert(refinedTag)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (tags, globalTags)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1652,6 +1652,80 @@ public final class InstantPage: PostboxCoding, Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
private extension InstantPageBlock {
|
||||
func allMedia(mediaDict: [MediaId: Media]) -> [Media] {
|
||||
switch self {
|
||||
case let .audio(id, _):
|
||||
if let file = mediaDict[id] {
|
||||
return [file]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
case let .collage(items, _):
|
||||
var result: [Media] = []
|
||||
for item in items {
|
||||
result.append(contentsOf: item.allMedia(mediaDict: mediaDict))
|
||||
}
|
||||
return result
|
||||
case let .cover(block):
|
||||
return block.allMedia(mediaDict: mediaDict)
|
||||
case let .details(_, blocks, _):
|
||||
var result: [Media] = []
|
||||
for item in blocks {
|
||||
result.append(contentsOf: item.allMedia(mediaDict: mediaDict))
|
||||
}
|
||||
return result
|
||||
case let .image(id, _, _, _):
|
||||
if let image = mediaDict[id] {
|
||||
return [image]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
case let .list(items, _):
|
||||
for item in items {
|
||||
switch item {
|
||||
case let .blocks(blocks, _, _):
|
||||
var result: [Media] = []
|
||||
for block in blocks {
|
||||
result.append(contentsOf: block.allMedia(mediaDict: mediaDict))
|
||||
}
|
||||
return result
|
||||
case .text, .unknown:
|
||||
break
|
||||
}
|
||||
}
|
||||
return []
|
||||
case let .slideshow(items, _):
|
||||
var result: [Media] = []
|
||||
for item in items {
|
||||
result.append(contentsOf: item.allMedia(mediaDict: mediaDict))
|
||||
}
|
||||
return result
|
||||
case let .video(id, _, _, _):
|
||||
if let video = mediaDict[id] {
|
||||
return [video]
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
default:
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension InstantPage {
|
||||
func allMedia() -> [Media] {
|
||||
if self.media.isEmpty {
|
||||
return []
|
||||
}
|
||||
var result: [Media] = []
|
||||
for block in self.blocks {
|
||||
result.append(contentsOf: block.allMedia(mediaDict: self.media))
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
public extension InstantPage {
|
||||
struct Accessor: Equatable {
|
||||
let _wrappedInstantPage: InstantPage?
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue