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 isSecret = false
|
||||||
var isUnconsumedPersonalMention = false
|
var isUnconsumedPersonalMention = false
|
||||||
var hasUnseenReactions = false
|
var hasUnseenReactions = false
|
||||||
|
var richText: RichTextMessageAttribute?
|
||||||
for attribute in attributes {
|
for attribute in attributes {
|
||||||
if let timerAttribute = attribute as? AutoclearTimeoutMessageAttribute {
|
if let timerAttribute = attribute as? AutoclearTimeoutMessageAttribute {
|
||||||
if timerAttribute.timeout > 0 && (timerAttribute.timeout <= 60 || timerAttribute.timeout == viewOnceTimeout) {
|
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 {
|
} else if let attribute = attribute as? ReactionsMessageAttribute, attribute.hasUnseen {
|
||||||
hasUnseenReactions = true
|
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)
|
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)
|
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 {
|
public extension InstantPage {
|
||||||
struct Accessor: Equatable {
|
struct Accessor: Equatable {
|
||||||
let _wrappedInstantPage: InstantPage?
|
let _wrappedInstantPage: InstantPage?
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue