Various improvements

This commit is contained in:
Ilya Laktyushin 2026-03-29 22:18:19 +02:00
parent 8d7b84caac
commit f3c18e1436
17 changed files with 261 additions and 67 deletions

View file

@ -211,17 +211,17 @@ public final class ListMessageFileItemNode: ListMessageNode {
self.addSubnode(self.descriptionNode)
}
func asyncLayout() -> (_ context: AccountContext, _ constrainedWidth: CGFloat, _ theme: PresentationTheme, _ authorTitle: NSAttributedString?, _ topic: (title: NSAttributedString, showIcon: Bool, iconId: Int64?, iconColor: Int32)?) -> (CGSize, () -> Void) {
func asyncLayout() -> (_ context: AccountContext, _ constrainedWidth: CGFloat, _ theme: PresentationTheme, _ authorTitle: NSAttributedString?, _ truncateType: CTLineTruncationType, _ topic: (title: NSAttributedString, showIcon: Bool, iconId: Int64?, iconColor: Int32)?) -> (CGSize, () -> Void) {
let makeDescriptionLayout = TextNode.asyncLayout(self.descriptionNode)
let makeTopicTitleLayout = TextNode.asyncLayout(self.topicTitleNode)
return { [weak self] context, constrainedWidth, theme, authorTitle, topic in
return { [weak self] context, constrainedWidth, theme, authorTitle, truncateType, topic in
var maxTitleWidth = constrainedWidth
if let _ = topic {
maxTitleWidth = floor(constrainedWidth * 0.7)
}
let descriptionLayout = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: authorTitle, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .middle, constrainedSize: CGSize(width: maxTitleWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0)))
let descriptionLayout = makeDescriptionLayout(TextNodeLayoutArguments(attributedString: authorTitle, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: truncateType, constrainedSize: CGSize(width: maxTitleWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0)))
var remainingWidth = constrainedWidth - descriptionLayout.0.size.width
@ -1040,15 +1040,15 @@ public final class ListMessageFileItemNode: ListMessageNode {
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
let dateText = stringForRelativeTimestamp(strings: item.presentationData.strings, relativeTimestamp: item.message?.timestamp ?? 0, relativeTo: timestamp, dateTimeFormat: item.presentationData.dateTimeFormat)
let dateAttributedString = NSAttributedString(string: dateText, font: dateFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)
let dateAttributedString = !item.isGlobalSearchResult ? NSAttributedString() : NSAttributedString(string: dateText, font: dateFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)
let (dateNodeLayout, dateNodeApply) = dateNodeMakeLayout(TextNodeLayoutArguments(attributedString: dateAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftOffset - contentRightInset - 12.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleNodeLayout, titleNodeApply) = titleNodeMakeLayout(item.context, params.width - leftInset - leftOffset - contentRightInset - dateNodeLayout.size.width - 4.0, item.presentationData.theme.theme, titleText, titleExtraData)
let (titleNodeLayout, titleNodeApply) = titleNodeMakeLayout(item.context, params.width - leftInset - leftOffset - contentRightInset - dateNodeLayout.size.width - 4.0, item.presentationData.theme.theme, titleText, isAudio ? .end : .middle, titleExtraData)
let (textNodeLayout, textNodeApply) = textNodeMakeLayout(TextNodeLayoutArguments(attributedString: captionText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - leftOffset - contentRightInset - 30.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (descriptionNodeLayout, descriptionNodeApply) = descriptionNodeMakeLayout(item.context, params.width - leftInset - leftOffset - contentRightInset - 30.0, item.presentationData.theme.theme, descriptionText, descriptionExtraData)
let (descriptionNodeLayout, descriptionNodeApply) = descriptionNodeMakeLayout(item.context, params.width - leftInset - leftOffset - contentRightInset - 30.0, item.presentationData.theme.theme, descriptionText, .middle, descriptionExtraData)
var (extensionTextLayout, extensionTextApply) = extensionIconTextMakeLayout(TextNodeLayoutArguments(attributedString: extensionText, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 38.0, height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
if extensionTextLayout.truncated, let text = extensionText?.string {
@ -1168,7 +1168,7 @@ public final class ListMessageFileItemNode: ListMessageNode {
strongSelf.backgroundNode = backgroundNode
strongSelf.insertSubnode(backgroundNode, at: 0)
}
backgroundNode.backgroundColor = item.canReorder ? item.presentationData.theme.theme.list.plainBackgroundColor : item.presentationData.theme.theme.list.itemBlocksBackgroundColor
backgroundNode.backgroundColor = item.canReorder ? item.presentationData.theme.theme.list.itemModalBlocksBackgroundColor : item.presentationData.theme.theme.list.itemBlocksBackgroundColor
}
strongSelf.separatorNode.backgroundColor = item.presentationData.theme.theme.list.itemPlainSeparatorColor

View file

@ -672,7 +672,7 @@ public final class ListMessageSnippetItemNode: ListMessageNode {
}
let authorText = NSAttributedString(string: authorString, font: authorFont, textColor: item.presentationData.theme.theme.list.itemSecondaryTextColor)
let (authorNodeLayout, authorNodeApply) = authorNodeMakeLayout(item.context, params.width - leftInset - leftOffset - contentRightInset - 30.0, item.presentationData.theme.theme, authorText, forumThreadTitle)
let (authorNodeLayout, authorNodeApply) = authorNodeMakeLayout(item.context, params.width - leftInset - leftOffset - contentRightInset - 30.0, item.presentationData.theme.theme, authorText, .middle, forumThreadTitle)
var contentHeight = 9.0 + titleNodeLayout.size.height + 10.0 + descriptionNodeLayout.size.height + linkNodeLayout.size.height
if !authorString.isEmpty {

View file

@ -5457,6 +5457,7 @@ func replayFinalState(
isMy: item.isMy,
myReaction: updatedReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -5492,6 +5493,7 @@ func replayFinalState(
isMy: item.isMy,
myReaction: MessageReaction.Reaction(apiReaction: reaction),
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))

View file

@ -354,6 +354,7 @@ private final class StoryStatsPublicForwardsContextImpl {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)

View file

@ -563,6 +563,7 @@ public final class EngineStoryViewListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
),
@ -604,6 +605,7 @@ public final class EngineStoryViewListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -645,6 +647,7 @@ public final class EngineStoryViewListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -767,6 +770,7 @@ public final class EngineStoryViewListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
),

View file

@ -112,8 +112,9 @@ public extension Stories {
case period
case randomId
case forwardInfo
case uploadInfo
case folders
case music
case uploadInfo
}
public let target: PendingTarget
@ -131,6 +132,7 @@ public extension Stories {
public let randomId: Int64
public let forwardInfo: PendingForwardInfo?
public let folders: [Int64]
public let music: TelegramMediaFile?
public let uploadInfo: StoryUploadInfo?
public init(
@ -149,6 +151,7 @@ public extension Stories {
randomId: Int64,
forwardInfo: PendingForwardInfo?,
folders: [Int64],
music: TelegramMediaFile?,
uploadInfo: StoryUploadInfo?
) {
self.target = target
@ -166,6 +169,7 @@ public extension Stories {
self.randomId = randomId
self.forwardInfo = forwardInfo
self.folders = folders
self.music = music
self.uploadInfo = uploadInfo
}
@ -197,6 +201,9 @@ public extension Stories {
self.folders = try container.decodeIfPresent([Int64].self, forKey: .folders) ?? []
let musicData = try container.decode(Data.self, forKey: .music)
self.music = PostboxDecoder(buffer: MemoryBuffer(data: musicData)).decodeRootObject() as? TelegramMediaFile
self.uploadInfo = try container.decodeIfPresent(StoryUploadInfo.self, forKey: .uploadInfo)
}
@ -226,6 +233,13 @@ public extension Stories {
try container.encode(self.period, forKey: .period)
try container.encode(self.randomId, forKey: .randomId)
try container.encodeIfPresent(self.forwardInfo, forKey: .forwardInfo)
if let music = self.music {
let musicEncoder = PostboxEncoder()
musicEncoder.encodeRootObject(music)
try container.encode(musicEncoder.makeData(), forKey: .music)
}
try container.encode(self.folders, forKey: .folders)
try container.encodeIfPresent(self.uploadInfo, forKey: .uploadInfo)
}
@ -270,6 +284,9 @@ public extension Stories {
if lhs.folders != rhs.folders {
return false
}
if lhs.music != rhs.music {
return false
}
if lhs.uploadInfo != rhs.uploadInfo {
return false
}
@ -519,7 +536,7 @@ final class PendingStoryManager {
let partTotalProgress = 1.0 / Float(uploadInfo.total)
pendingItemContext.progress = Float(uploadInfo.index) * partTotalProgress
}
pendingItemContext.disposable = (_internal_uploadStoryImpl(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, stateManager: self.stateManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, revalidationContext: self.revalidationContext, auxiliaryMethods: self.auxiliaryMethods, toPeerId: toPeerId, stableId: stableId, media: firstItem.media, mediaAreas: firstItem.mediaAreas, text: firstItem.text, entities: firstItem.entities, embeddedStickers: firstItem.embeddedStickers, pin: firstItem.pin, privacy: firstItem.privacy, isForwardingDisabled: firstItem.isForwardingDisabled, period: Int(firstItem.period), folders: firstItem.folders, randomId: firstItem.randomId, forwardInfo: firstItem.forwardInfo)
pendingItemContext.disposable = (_internal_uploadStoryImpl(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, stateManager: self.stateManager, messageMediaPreuploadManager: self.messageMediaPreuploadManager, revalidationContext: self.revalidationContext, auxiliaryMethods: self.auxiliaryMethods, toPeerId: toPeerId, stableId: stableId, media: firstItem.media, mediaAreas: firstItem.mediaAreas, text: firstItem.text, entities: firstItem.entities, embeddedStickers: firstItem.embeddedStickers, pin: firstItem.pin, privacy: firstItem.privacy, isForwardingDisabled: firstItem.isForwardingDisabled, period: Int(firstItem.period), folders: firstItem.folders, music: firstItem.music, randomId: firstItem.randomId, forwardInfo: firstItem.forwardInfo)
|> deliverOn(self.queue)).start(next: { [weak self] event in
guard let `self` = self else {
return

View file

@ -262,6 +262,7 @@ public enum Stories {
case isMy
case myReaction
case forwardInfo
case music
case authorId
case folderIds
}
@ -287,6 +288,7 @@ public enum Stories {
public let isMy: Bool
public let myReaction: MessageReaction.Reaction?
public let forwardInfo: ForwardInfo?
public let music: TelegramMediaFile?
public let authorId: PeerId?
public let folderIds: [Int64]?
@ -316,6 +318,7 @@ public enum Stories {
isMy: Bool,
myReaction: MessageReaction.Reaction?,
forwardInfo: ForwardInfo?,
music: TelegramMediaFile?,
authorId: PeerId?,
folderIds: [Int64]?
) {
@ -340,6 +343,7 @@ public enum Stories {
self.isMy = isMy
self.myReaction = myReaction
self.forwardInfo = forwardInfo
self.music = music
self.authorId = authorId
self.folderIds = folderIds
}
@ -388,6 +392,13 @@ public enum Stories {
self.isMy = try container.decodeIfPresent(Bool.self, forKey: .isMy) ?? false
self.myReaction = try container.decodeIfPresent(MessageReaction.Reaction.self, forKey: .myReaction)
self.forwardInfo = try container.decodeIfPresent(ForwardInfo.self, forKey: .forwardInfo)
if let musicData = try container.decodeIfPresent(Data.self, forKey: .music) {
self.music = PostboxDecoder(buffer: MemoryBuffer(data: musicData)).decodeRootObject() as? TelegramMediaFile
} else {
self.music = nil
}
self.authorId = try container.decodeIfPresent(Int64.self, forKey: .authorId).flatMap { PeerId($0) }
self.folderIds = try container.decodeIfPresent([Int64].self, forKey: .folderIds)
}
@ -430,6 +441,14 @@ public enum Stories {
try container.encode(self.isMy, forKey: .isMy)
try container.encodeIfPresent(self.myReaction, forKey: .myReaction)
try container.encodeIfPresent(self.forwardInfo, forKey: .forwardInfo)
if let music = self.music {
let encoder = PostboxEncoder()
encoder.encodeRootObject(music)
let musicData = encoder.makeData()
try container.encode(musicData, forKey: .music)
}
try container.encodeIfPresent(self.authorId?.toInt64(), forKey: .authorId)
try container.encodeIfPresent(self.folderIds, forKey: .folderIds)
}
@ -504,6 +523,15 @@ public enum Stories {
if lhs.forwardInfo != rhs.forwardInfo {
return false
}
if let lhsMusic = lhs.music, let rhsMusic = rhs.music {
if !lhsMusic.isEqual(to: rhsMusic) {
return false
}
} else {
if (lhs.music == nil) != (rhs.music == nil) {
return false
}
}
if lhs.authorId != rhs.authorId {
return false
}
@ -1035,7 +1063,23 @@ public struct StoryUploadInfo: Codable, Equatable {
}
}
func _internal_uploadStory(account: Account, target: Stories.PendingTarget, media: EngineStoryInputMedia, mediaAreas: [MediaArea], text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, isForwardingDisabled: Bool, period: Int, randomId: Int64, forwardInfo: Stories.PendingForwardInfo?, folders: [Int64], uploadInfo: StoryUploadInfo? = nil) -> Signal<Int32, NoError> {
func _internal_uploadStory(
account: Account,
target: Stories.PendingTarget,
media: EngineStoryInputMedia,
mediaAreas: [MediaArea],
text: String,
entities: [MessageTextEntity],
pin: Bool,
privacy: EngineStoryPrivacy,
isForwardingDisabled: Bool,
period: Int,
randomId: Int64,
forwardInfo: Stories.PendingForwardInfo?,
folders: [Int64],
music: TelegramMediaFile?,
uploadInfo: StoryUploadInfo? = nil
) -> Signal<Int32, NoError> {
let inputMedia = prepareUploadStoryContent(account: account, media: media)
return (account.postbox.transaction { transaction in
@ -1065,6 +1109,7 @@ func _internal_uploadStory(account: Account, target: Stories.PendingTarget, medi
randomId: randomId,
forwardInfo: forwardInfo,
folders: folders,
music: music,
uploadInfo: uploadInfo
))
transaction.setLocalStoryState(state: CodableEntry(currentState))
@ -1113,6 +1158,7 @@ func _internal_cancelStoryUpload(account: Account, stableId: Int32) {
randomId: currentState.items[i].randomId,
forwardInfo: currentState.items[i].forwardInfo,
folders: currentState.items[i].folders,
music: currentState.items[i].music,
uploadInfo: StoryUploadInfo(
groupingId: groupingId,
index: newIndex,
@ -1203,6 +1249,7 @@ func _internal_beginStoryLivestream(account: Account, peerId: EnginePeer.Id, rtm
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -1279,6 +1326,7 @@ func _internal_uploadStoryImpl(
isForwardingDisabled: Bool,
period: Int,
folders: [Int64],
music: TelegramMediaFile?,
randomId: Int64,
forwardInfo: Stories.PendingForwardInfo?
) -> Signal<PendingStoryUploadResult, NoError> {
@ -1373,7 +1421,11 @@ func _internal_uploadStoryImpl(
flags |= 1 << 8
}
//var apiMusic: Api.InputDocument?
var apiMusic: Api.InputDocument?
if let resource = music?.resource as? CloudDocumentMediaResource, let fileReference = resource.fileReference {
flags |= 1 << 9
apiMusic = .inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: fileReference)))
}
return network.request(Api.functions.stories.sendStory(
flags: flags,
@ -1388,7 +1440,7 @@ func _internal_uploadStoryImpl(
fwdFromId: fwdFromId,
fwdFromStory: fwdFromStory,
albums: folders.isEmpty ? nil : folders.map(Int32.init(clamping:)),
music: nil
music: apiMusic
))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
@ -1441,6 +1493,7 @@ func _internal_uploadStoryImpl(
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: fromId?.peerId,
folderIds: item.folderIds
)
@ -1861,6 +1914,7 @@ func _internal_editStoryPrivacy(account: Account, id: Int32, privacy: EngineStor
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
)
@ -1894,6 +1948,7 @@ func _internal_editStoryPrivacy(account: Account, id: Int32, privacy: EngineStor
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
)
@ -2092,6 +2147,7 @@ func _internal_updateStoriesArePinned(account: Account, peerId: PeerId, ids: [In
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
)
@ -2124,6 +2180,7 @@ func _internal_updateStoriesArePinned(account: Account, peerId: PeerId, ids: [In
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
)
@ -2251,7 +2308,7 @@ extension Stories.StoredItem {
init?(apiStoryItem: Api.StoryItem, existingItem: Stories.Item? = nil, peerId: PeerId, transaction: Transaction) {
switch apiStoryItem {
case let .storyItem(storyItemData):
let (flags, id, date, fromId, forwardFrom, expireDate, caption, entities, media, mediaAreas, privacy, views, sentReaction, albums) = (storyItemData.flags, storyItemData.id, storyItemData.date, storyItemData.fromId, storyItemData.fwdFrom, storyItemData.expireDate, storyItemData.caption, storyItemData.entities, storyItemData.media, storyItemData.mediaAreas, storyItemData.privacy, storyItemData.views, storyItemData.sentReaction, storyItemData.albums)
let (flags, id, date, fromId, forwardFrom, expireDate, caption, entities, media, mediaAreas, privacy, views, sentReaction, albums, music) = (storyItemData.flags, storyItemData.id, storyItemData.date, storyItemData.fromId, storyItemData.fwdFrom, storyItemData.expireDate, storyItemData.caption, storyItemData.entities, storyItemData.media, storyItemData.mediaAreas, storyItemData.privacy, storyItemData.views, storyItemData.sentReaction, storyItemData.albums, storyItemData.music)
var folderIds: [Int64]?
if let albums {
folderIds = albums.map(Int64.init)
@ -2350,6 +2407,12 @@ extension Stories.StoredItem {
break
}
var parsedMusic: TelegramMediaFile?
if let music {
parsedMusic = telegramMediaFileFromApiDocument(music, altDocuments: nil)
}
let item = Stories.Item(
id: id,
timestamp: date,
@ -2372,6 +2435,7 @@ extension Stories.StoredItem {
isMy: mergedIsMy,
myReaction: mergedMyReaction,
forwardInfo: mergedForwardInfo,
music: parsedMusic,
authorId: fromId?.peerId,
folderIds: folderIds
)
@ -2453,6 +2517,7 @@ func _internal_getStoryById(accountPeerId: PeerId, postbox: Postbox, network: Ne
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -2953,6 +3018,7 @@ func _internal_setStoryReaction(account: Account, peerId: EnginePeer.Id, id: Int
isMy: item.isMy,
myReaction: reaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -2988,6 +3054,7 @@ func _internal_setStoryReaction(account: Account, peerId: EnginePeer.Id, id: Int
isMy: item.isMy,
myReaction: reaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -3065,6 +3132,7 @@ func _internal_sendStoryStars(account: Account, peerId: EnginePeer.Id, id: Int32
isMy: item.isMy,
myReaction: .stars,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -3100,6 +3168,7 @@ func _internal_sendStoryStars(account: Account, peerId: EnginePeer.Id, id: Int32
isMy: item.isMy,
myReaction: .stars,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))

View file

@ -85,10 +85,37 @@ public final class EngineStoryItem: Equatable {
public let isMy: Bool
public let myReaction: MessageReaction.Reaction?
public let forwardInfo: ForwardInfo?
public let music: EngineMedia?
public let author: EnginePeer?
public let folderIds: [Int64]?
public init(id: Int32, timestamp: Int32, expirationTimestamp: Int32, media: EngineMedia, alternativeMediaList: [EngineMedia], mediaAreas: [MediaArea], text: String, entities: [MessageTextEntity], views: Views?, privacy: EngineStoryPrivacy?, isPinned: Bool, isExpired: Bool, isPublic: Bool, isPending: Bool, isCloseFriends: Bool, isContacts: Bool, isSelectedContacts: Bool, isForwardingDisabled: Bool, isEdited: Bool, isMy: Bool, myReaction: MessageReaction.Reaction?, forwardInfo: ForwardInfo?, author: EnginePeer?, folderIds: [Int64]?) {
public init(
id: Int32,
timestamp: Int32,
expirationTimestamp: Int32,
media: EngineMedia,
alternativeMediaList: [EngineMedia],
mediaAreas: [MediaArea],
text: String,
entities: [MessageTextEntity],
views: Views?,
privacy: EngineStoryPrivacy?,
isPinned: Bool,
isExpired: Bool,
isPublic: Bool,
isPending: Bool,
isCloseFriends: Bool,
isContacts: Bool,
isSelectedContacts: Bool,
isForwardingDisabled: Bool,
isEdited: Bool,
isMy: Bool,
myReaction: MessageReaction.Reaction?,
forwardInfo: ForwardInfo?,
music: EngineMedia?,
author: EnginePeer?,
folderIds: [Int64]?
) {
self.id = id
self.timestamp = timestamp
self.expirationTimestamp = expirationTimestamp
@ -111,6 +138,7 @@ public final class EngineStoryItem: Equatable {
self.isMy = isMy
self.myReaction = myReaction
self.forwardInfo = forwardInfo
self.music = music
self.author = author
self.folderIds = folderIds
}
@ -182,6 +210,9 @@ public final class EngineStoryItem: Equatable {
if lhs.forwardInfo != rhs.forwardInfo {
return false
}
if lhs.music != rhs.music {
return false
}
if lhs.author != rhs.author {
return false
}
@ -239,9 +270,9 @@ public extension EngineStoryItem {
isForwardingDisabled: self.isForwardingDisabled,
isEdited: self.isEdited,
isMy: self.isMy,
myReaction: self.myReaction,
forwardInfo: self.forwardInfo?.storedForwardInfo,
music: self.music?._asMedia() as? TelegramMediaFile,
authorId: self.author?.id,
folderIds: self.folderIds
)
@ -744,6 +775,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -966,6 +998,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -1161,6 +1194,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: item.folderIds
), peer: nil)
@ -1211,6 +1245,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: item.folderIds
), peer: nil)
@ -1263,6 +1298,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: item.folderIds
), peer: nil))
@ -1321,6 +1357,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: item.folderIds
), peer: nil))
@ -1656,6 +1693,7 @@ public final class PeerStoryListContext: StoryListContext {
return .unknown(name: name, isModified: isModified)
}
},
music: item.music?._asMedia() as? TelegramMediaFile,
authorId: item.author?.id,
folderIds: item.folderIds
)
@ -2001,6 +2039,7 @@ public final class PeerStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -2201,6 +2240,7 @@ public final class SearchStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -2351,6 +2391,7 @@ public final class SearchStoryListContext: StoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, peers: peers) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: item.folderIds
),
@ -2413,6 +2454,7 @@ public final class SearchStoryListContext: StoryListContext {
isMy: item.storyItem.isMy,
myReaction: reaction,
forwardInfo: item.storyItem.forwardInfo,
music: item.storyItem.music,
author: item.storyItem.author,
folderIds: item.storyItem.folderIds
),
@ -2543,6 +2585,7 @@ public final class PeerExpiringStoryListContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -3008,6 +3051,7 @@ public final class BotPreviewStoryListContext: StoryListContext {
isMy: false,
myReaction: nil,
forwardInfo: nil,
music: nil,
author: nil,
folderIds: nil
),
@ -3058,6 +3102,7 @@ public final class BotPreviewStoryListContext: StoryListContext {
isMy: false,
myReaction: nil,
forwardInfo: nil,
music: nil,
author: nil,
folderIds: nil
),
@ -3171,6 +3216,7 @@ public final class BotPreviewStoryListContext: StoryListContext {
isMy: false,
myReaction: nil,
forwardInfo: nil,
music: nil,
author: nil,
folderIds: nil
),
@ -3249,6 +3295,7 @@ public final class BotPreviewStoryListContext: StoryListContext {
isMy: false,
myReaction: nil,
forwardInfo: nil,
music: nil,
author: nil,
folderIds: nil
),
@ -3313,6 +3360,7 @@ public final class BotPreviewStoryListContext: StoryListContext {
isMy: false,
myReaction: nil,
forwardInfo: nil,
music: nil,
author: nil,
folderIds: nil
),

View file

@ -1469,6 +1469,7 @@ public extension TelegramEngine {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo,
music: item.music,
authorId: item.authorId,
folderIds: item.folderIds
))
@ -1484,8 +1485,8 @@ public extension TelegramEngine {
}
}
public func uploadStory(target: Stories.PendingTarget, media: EngineStoryInputMedia, mediaAreas: [MediaArea], text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, isForwardingDisabled: Bool, period: Int, randomId: Int64, forwardInfo: Stories.PendingForwardInfo?, folders: [Int64], uploadInfo: StoryUploadInfo? = nil) -> Signal<Int32, NoError> {
return _internal_uploadStory(account: self.account, target: target, media: media, mediaAreas: mediaAreas, text: text, entities: entities, pin: pin, privacy: privacy, isForwardingDisabled: isForwardingDisabled, period: period, randomId: randomId, forwardInfo: forwardInfo, folders: folders, uploadInfo: uploadInfo)
public func uploadStory(target: Stories.PendingTarget, media: EngineStoryInputMedia, mediaAreas: [MediaArea], text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, isForwardingDisabled: Bool, period: Int, randomId: Int64, forwardInfo: Stories.PendingForwardInfo?, folders: [Int64], music: TelegramMediaFile?, uploadInfo: StoryUploadInfo? = nil) -> Signal<Int32, NoError> {
return _internal_uploadStory(account: self.account, target: target, media: media, mediaAreas: mediaAreas, text: text, entities: entities, pin: pin, privacy: privacy, isForwardingDisabled: isForwardingDisabled, period: period, randomId: randomId, forwardInfo: forwardInfo, folders: folders, music: music, uploadInfo: uploadInfo)
}
public func beginStoryLivestream(peerId: EnginePeer.Id, rtmp: Bool, privacy: EngineStoryPrivacy, isForwardingDisabled: Bool, messagesEnabled: Bool, sendPaidMessageStars: Int64?) -> Signal<EngineStoryItem?, NoError> {

View file

@ -500,12 +500,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
let searchQuery = self.searchQuery.get()
|> mapToSignal { query -> Signal<String?, NoError> in
if let query = query, !query.isEmpty {
return (.complete() |> delay(0.6, queue: Queue.mainQueue()))
|> then(.single(query))
} else {
return .single(query)
}
return .single(query)
}
let expandedSectionsPromise = self.expandedSectionsPromise
@ -525,6 +520,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
shared = .single(nil)
|> then(
context.engine.messages.searchMessages(location: .sentMedia(tags: [.file]), query: query, state: nil)
|> delay(0.6, queue: Queue.mainQueue())
|> map { result -> [Message]? in
return result.0.messages
}
@ -535,13 +531,15 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
shared = .single(nil)
|> then(
context.engine.messages.searchMessages(location: .general(scope: .everywhere, tags: [.music], minDate: nil, maxDate: nil), query: query, state: nil)
|> delay(0.6, queue: Queue.mainQueue())
|> map { result -> [Message]? in
return result.0.messages
return result.0.messages.filter { !$0.isRestricted(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) }
}
)
savedMusic = .single(nil)
|> then(
savedMusicContext!.state
|> delay(0.6, queue: Queue.mainQueue())
|> map { state in
let peerId = context.account.peerId
var messages: [Message] = []
@ -571,13 +569,12 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
return messages
}
)
let trimmedQuery = query.trimmingCharacters(in: .whitespacesAndNewlines)
if let data = context.currentAppConfiguration.with({ $0 }).data, let searchBot = data["music_search_username"] as? String, !searchBot.isEmpty, trimmedQuery.count >= 3 {
if let data = context.currentAppConfiguration.with({ $0 }).data, let searchBot = data["music_search_username"] as? String, !searchBot.isEmpty, query.count >= 3 {
globalMusic = .single(nil)
|> then(
context.engine.peers.resolvePeerByName(name: searchBot, referrer: nil)
|> delay(0.6, queue: Queue.mainQueue())
|> mapToSignal { result -> Signal<EnginePeer?, NoError> in
guard case let .result(result) = result else {
return .complete()
@ -588,7 +585,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
guard let peer = peer else {
return .single(nil)
}
return context.engine.messages.requestChatContextResults(botId: peer.id, peerId: context.account.peerId, query: trimmedQuery, offset: "")
return context.engine.messages.requestChatContextResults(botId: peer.id, peerId: context.account.peerId, query: query, offset: "")
|> map { results -> ChatContextResultCollection? in
return results?.results
}
@ -618,7 +615,7 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
}
)
} else {
globalMusic = .single(nil)
globalMusic = .single([])
}
}
@ -670,13 +667,22 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
}
}
if let globalMusic, !globalMusic.isEmpty {
index = 0
section += 1
entries.append(.header(title: presentationData.strings.Attachment_PublicMusic, section: section))
for message in globalMusic {
entries.append(.file(index: index, message: message, section: section))
if let globalMusic {
if !globalMusic.isEmpty {
index = 0
section += 1
entries.append(.header(title: presentationData.strings.Attachment_PublicMusic, section: section))
for message in globalMusic {
entries.append(.file(index: index, message: message, section: section))
index += 1
}
}
} else if messages.isEmpty {
entries.append(.header(title: " ", section: 0))
var index: Int32 = 0
for _ in 0 ..< 16 {
entries.append(.file(index: index, message: nil, section: 0))
index += 1
}
}
@ -694,6 +700,8 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
}
let previousSearchItems = Atomic<[AttachmentFileSearchEntry]?>(value: nil)
let previousHadSharedItems = Atomic<Bool>(value: false)
let previousHadSavedItems = Atomic<Bool>(value: false)
let previousHadGlobalItems = Atomic<Bool>(value: false)
self.searchDisposable.set((combineLatest(searchQuery, foundItems, self.presentationDataPromise.get())
|> deliverOnMainQueue).startStrict(next: { [weak self] query, entries, presentationData in
@ -702,17 +710,30 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
updateActivity(false)
let firstTime = previousEntries == nil
var hasSharedItems = false
var hasSavedItems = false
var hasGlobalItems = false
if let entries {
for entry in entries {
if case let .header(_, section) = entry, section == 2 {
hasGlobalItems = true
if case let .header(title, section) = entry, title != " " {
if section == 0 {
hasSharedItems = true
}
if section == 1 {
hasSavedItems = true
}
if section == 2 {
hasGlobalItems = true
}
}
}
}
let hadSharedItems = previousHadSharedItems.swap(hasSharedItems)
let hadSavedItems = previousHadSavedItems.swap(hasSavedItems)
let hadGlobalItems = previousHadGlobalItems.swap(hasGlobalItems)
let crossfade = hadGlobalItems != hasGlobalItems
let crossfade = hadSharedItems != hasSharedItems || hadSavedItems != hasSavedItems || hadGlobalItems != hasGlobalItems
let transition = attachmentFileSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, isEmpty: entries?.isEmpty ?? false, query: query ?? "", context: context, presentationData: presentationData, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, interaction: interaction, mode: mode, crossfade: crossfade)
strongSelf.enqueueTransition(transition, firstTime: firstTime)
@ -751,7 +772,8 @@ public final class AttachmentFileSearchContainerNode: SearchDisplayControllerCon
}
override public func searchTextUpdated(text: String) {
self.searchQuery.set(.single(!text.isEmpty ? text : nil))
let trimmedText = text.trimmingCharacters(in: .whitespacesAndNewlines)
self.searchQuery.set(.single(!trimmedText.isEmpty ? trimmedText : nil))
}
private func enqueueTransition(_ transition: AttachmentFileSearchContainerTransition, firstTime: Bool) {

View file

@ -6706,6 +6706,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
public let coverTimestamp: Double?
public let options: MediaEditorResultPrivacy
public let stickers: [TelegramMediaFile]
public let music: TelegramMediaFile?
public let randomId: Int64
init() {
@ -6715,6 +6716,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
self.coverTimestamp = nil
self.options = MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false, folderIds: [])
self.stickers = []
self.music = nil
self.randomId = 0
}
@ -6725,6 +6727,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
coverTimestamp: Double? = nil,
options: MediaEditorResultPrivacy = MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false, folderIds: []),
stickers: [TelegramMediaFile] = [],
music: TelegramMediaFile? = nil,
randomId: Int64 = 0
) {
self.media = media
@ -6733,6 +6736,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
self.coverTimestamp = coverTimestamp
self.options = options
self.stickers = stickers
self.music = music
self.randomId = randomId
}
}
@ -7766,6 +7770,7 @@ public final class MediaEditorScreenImpl: ViewController, MediaEditorScreen, UID
coverTimestamp: nil,
options: MediaEditorResultPrivacy(sendAsPeerId: nil, privacy: EngineStoryPrivacy(base: .everyone, additionallyIncludePeers: []), timeout: 0, isForwardingDisabled: false, pin: false, folderIds: []),
stickers: [],
music: nil,
randomId: 0
)], { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in

View file

@ -129,7 +129,7 @@ extension MediaEditorScreenImpl {
if self.isEmbeddedEditor && !(hasAnyChanges || hasEntityChanges) {
self.saveDraft(id: randomId, isEdit: true)
self.completion([MediaEditorScreenImpl.Result(media: nil, mediaAreas: [], caption: caption, coverTimestamp: mediaEditor.values.coverImageTimestamp, options: self.state.privacy, stickers: stickers, randomId: randomId)], { [weak self] finished in
self.completion([MediaEditorScreenImpl.Result(media: nil, mediaAreas: [], caption: caption, coverTimestamp: mediaEditor.values.coverImageTimestamp, options: self.state.privacy, stickers: stickers, music: nil, randomId: randomId)], { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()
Queue.mainQueue().justDispatch {
@ -464,7 +464,7 @@ extension MediaEditorScreenImpl {
return
}
Logger.shared.log("MediaEditor", "Completed with video \(videoResult)")
self.completion([MediaEditorScreenImpl.Result(media: .video(video: videoResult, coverImage: coverImage, values: values, duration: duration, dimensions: values.resultDimensions), mediaAreas: mediaAreas, caption: caption, coverTimestamp: values.coverImageTimestamp, options: self.state.privacy, stickers: stickers, randomId: randomId)], { [weak self] finished in
self.completion([MediaEditorScreenImpl.Result(media: .video(video: videoResult, coverImage: coverImage, values: values, duration: duration, dimensions: values.resultDimensions), mediaAreas: mediaAreas, caption: caption, coverTimestamp: values.coverImageTimestamp, options: self.state.privacy, stickers: stickers, music: nil, randomId: randomId)], { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()
Queue.mainQueue().justDispatch {
@ -506,7 +506,7 @@ extension MediaEditorScreenImpl {
return
}
Logger.shared.log("MediaEditor", "Completed with image \(resultImage)")
self.completion([MediaEditorScreenImpl.Result(media: .image(image: resultImage, dimensions: PixelDimensions(resultImage.size)), mediaAreas: mediaAreas, caption: caption, coverTimestamp: nil, options: self.state.privacy, stickers: stickers, randomId: randomId)], { [weak self] finished in
self.completion([MediaEditorScreenImpl.Result(media: .image(image: resultImage, dimensions: PixelDimensions(resultImage.size)), mediaAreas: mediaAreas, caption: caption, coverTimestamp: nil, options: self.state.privacy, stickers: stickers, music: nil, randomId: randomId)], { [weak self] finished in
self?.node.animateOut(finished: true, saveDraft: false, completion: { [weak self] in
self?.dismiss()
Queue.mainQueue().justDispatch {
@ -683,6 +683,7 @@ extension MediaEditorScreenImpl {
coverTimestamp: itemMediaEditor.values.coverImageTimestamp,
options: self.state.privacy,
stickers: stickers,
music: nil,
randomId: randomId
)
completion(result)
@ -765,6 +766,7 @@ extension MediaEditorScreenImpl {
coverTimestamp: nil,
options: self.state.privacy,
stickers: stickers,
music: nil,
randomId: randomId
)
completion(result)
@ -852,12 +854,11 @@ extension MediaEditorScreenImpl {
coverTimestamp: nil,
options: self.state.privacy,
stickers: [],
music: nil,
randomId: randomId
)
}
func updateMediaEditorEntities() {
guard let mediaEditor = self.node.mediaEditor else {
return

View file

@ -318,6 +318,7 @@ public final class StoryContentContextImpl: StoryContentContext {
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: forwardInfo,
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: item.folderIds
)
@ -356,6 +357,7 @@ public final class StoryContentContextImpl: StoryContentContext {
isMy: true,
myReaction: nil,
forwardInfo: pendingForwardsInfo[item.randomId],
music: item.music.flatMap(EngineMedia.init),
author: nil,
folderIds: item.folders
))
@ -1367,6 +1369,7 @@ public final class SingleStoryContentContextImpl: StoryContentContext {
isMy: itemValue.isMy,
myReaction: itemValue.myReaction,
forwardInfo: forwardInfo,
music: itemValue.music.flatMap(EngineMedia.init),
author: itemValue.authorId.flatMap { peers[$0].flatMap(EnginePeer.init) },
folderIds: itemValue.folderIds
)
@ -2308,6 +2311,7 @@ private func getCachedStory(storyId: StoryId, transaction: Transaction) -> Engin
isMy: item.isMy,
myReaction: item.myReaction,
forwardInfo: item.forwardInfo.flatMap { EngineStoryItem.ForwardInfo($0, transaction: transaction) },
music: item.music.flatMap(EngineMedia.init),
author: item.authorId.flatMap { transaction.getPeer($0).flatMap(EnginePeer.init) },
folderIds: item.folderIds
)

View file

@ -62,6 +62,7 @@ final class StoryContentCaptionComponent: Component {
let author: EnginePeer
let forwardInfo: EngineStoryItem.ForwardInfo?
let forwardInfoStory: Signal<EngineStoryItem?, NoError>?
let music: EngineMedia?
let entities: [MessageTextEntity]
let entityFiles: [EngineMedia.Id: TelegramMediaFile]
let action: (Action) -> Void
@ -79,6 +80,7 @@ final class StoryContentCaptionComponent: Component {
author: EnginePeer,
forwardInfo: EngineStoryItem.ForwardInfo?,
forwardInfoStory: Signal<EngineStoryItem?, NoError>?,
music: EngineMedia?,
entities: [MessageTextEntity],
entityFiles: [EngineMedia.Id: TelegramMediaFile],
action: @escaping (Action) -> Void,
@ -94,6 +96,7 @@ final class StoryContentCaptionComponent: Component {
self.author = author
self.forwardInfo = forwardInfo
self.forwardInfoStory = forwardInfoStory
self.music = music
self.text = text
self.entities = entities
self.entityFiles = entityFiles
@ -123,6 +126,9 @@ final class StoryContentCaptionComponent: Component {
if lhs.forwardInfo != rhs.forwardInfo {
return false
}
if lhs.music != rhs.music {
return false
}
if lhs.text != rhs.text {
return false
}

View file

@ -4557,6 +4557,7 @@ public final class StoryItemSetContainerComponent: Component {
author: component.slice.effectivePeer,
forwardInfo: component.slice.item.storyItem.forwardInfo,
forwardInfoStory: forwardInfoStory,
music: component.slice.item.storyItem.music,
entities: enableEntities ? component.slice.item.storyItem.entities : [],
entityFiles: component.slice.item.entityFiles,
action: { [weak self] action in

View file

@ -868,7 +868,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listNodeSize, insets: insets, itemOffsetInsets: itemOffsetInsets, duration: duration, curve: curve)
self.historyNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets)
if let replacementHistoryNode = self.replacementHistoryNode {
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listNodeSize, insets: insets, duration: 0.0, curve: .Default(duration: nil))
transition.updateFrame(node: replacementHistoryNode, frame: CGRect(origin: CGPoint(x: 0.0, y: listTopInset), size: listNodeSize))
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listNodeSize, insets: insets, itemOffsetInsets: itemOffsetInsets, duration: 0.0, curve: .Default(duration: nil))
replacementHistoryNode.updateLayout(transition: transition, updateSizeAndInsets: updateSizeAndInsets)
}
@ -1091,13 +1092,13 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
let leftOverlayFrame = CGRect(origin: CGPoint(x: 0.0, y: topOverlayFrame.maxY - 1.0), size: CGSize(width: sideInset, height: layout.size.height))
let rightOverlayFrame = CGRect(origin: CGPoint(x: layout.size.width - sideInset, y: topOverlayFrame.maxY - 1.0), size: CGSize(width: sideInset, height: layout.size.height))
self.historyFrameNode.frame = frameFrame
transition.updateFrame(node: self.historyFrameNode, frame: frameFrame)
self.historyFrameTopOverlayClipNode.frame = topOverlayFrame
self.historyFrameTopOverlayNode.frame = CGRect(origin: .zero, size: CGSize(width: topOverlayFrame.width, height: 78.0))
self.historyFrameLeftOverlayNode.frame = leftOverlayFrame
self.historyFrameRightOverlayNode.frame = rightOverlayFrame
if let image = self.historyFrameTopMaskNode.image {
self.historyFrameTopMaskNode.frame = CGRect(origin: CGPoint(x: sideInset, y: topOverlayFrame.maxY), size: CGSize(width: layout.size.width - sideInset * 2.0, height: image.size.height))
self.historyFrameTopMaskNode.frame = CGRect(origin: CGPoint(x: sideInset, y: topOverlayFrame.maxY - UIScreenPixel), size: CGSize(width: layout.size.width - sideInset * 2.0, height: image.size.height))
}
self.historyFrameTopMaskNode.isHidden = self.controlsNode.hasPlainBackground
@ -1157,23 +1158,33 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
historyNode.updateFloatingHeaderOffset = { [weak self] offset, _ in
self?.replacementHistoryNodeFloatingOffset = offset
}
self.replacementHistoryNodeFloatingOffset = nil
self.replacementHistoryNode = historyNode
if let layout = self.validLayout {
let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top)
let controlsHeight = self.controlsNode.frame.height
var insets = UIEdgeInsets()
insets.left = 16.0
insets.right = 16.0
insets.bottom = 0.0
let listTopInset = layoutTopInset
let listNodeSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset)
let headerHeight = self.effectiveHeaderHeight
let listTopInset = layoutTopInset + headerHeight
let listNodeSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - controlsHeight)
insets.top = max(0.0, listNodeSize.height - floor(62.0 * 3.5))
var itemOffsetInsets = insets
if let playlistLocation = self.playlistLocation as? PeerMessagesPlaylistLocation, case let .savedMusic(_, _, canReorder) = playlistLocation, canReorder {
itemOffsetInsets.top = 0.0
itemOffsetInsets.bottom = 0.0
insets = itemOffsetInsets
}
historyNode.frame = CGRect(origin: CGPoint(x: 0.0, y: listTopInset), size: listNodeSize)
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listNodeSize, insets: insets, duration: 0.0, curve: .Default(duration: nil))
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: listNodeSize, insets: insets, itemOffsetInsets: itemOffsetInsets, duration: 0.0, curve: .Default(duration: nil))
historyNode.updateLayout(transition: .immediate, updateSizeAndInsets: updateSizeAndInsets)
}
self.replacementHistoryNodeReadyDisposable.set((historyNode.historyState.get() |> take(1) |> deliverOnMainQueue).startStrict(next: { [weak self] _ in
@ -1194,21 +1205,15 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
self.setupReordering()
self.updateHistoryContentOffset(replacementHistoryNode.visibleContentOffset(), transition: .immediate)
if let validLayout = self.validLayout, let offset = self.replacementHistoryNodeFloatingOffset, let previousOffset = self.floatingHeaderOffset {
if let offset = self.replacementHistoryNodeFloatingOffset, let previousOffset = self.floatingHeaderOffset {
let offsetDelta = offset - previousOffset
let layoutTopInset: CGFloat = max(validLayout.statusBarHeight ?? 0.0, validLayout.safeInsets.top)
let controlsBottomOffset = max(layoutTopInset, offset)
let previousBackgroundNode = ASDisplayNode()
previousBackgroundNode.isLayerBacked = true
previousBackgroundNode.backgroundColor = self.historyBackgroundContentNode.backgroundColor
self.contentNode.insertSubnode(previousBackgroundNode, belowSubnode: previousHistoryNode)
previousBackgroundNode.frame = self.historyBackgroundNode.frame
previousBackgroundNode.layer.animateFrame(from: previousBackgroundNode.frame, to: CGRect(origin: CGPoint(x: 0.0, y: controlsBottomOffset), size: validLayout.size), duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false)
self.updateFloatingHeaderOffset(offset: offset, transition: .animated(duration: 0.4, curve: .spring))
previousHistoryNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousHistoryNode] _ in
previousHistoryNode?.removeFromSupernode()
@ -1237,8 +1242,12 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
}
switch strongSelf.historyNode.visibleContentOffset() {
case let .known(value):
if value <= -10.0 {
strongSelf.requestDismiss()
if let playlistLocation = strongSelf.playlistLocation as? PeerMessagesPlaylistLocation, case let .savedMusic(_, _, canReorder) = playlistLocation, canReorder {
} else {
if value <= -10.0 {
strongSelf.requestDismiss()
}
}
default:
break
@ -1251,14 +1260,16 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
if let layout = self.validLayout {
let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top)
let controlsHeight = self.controlsNode.frame.height
var insets = UIEdgeInsets()
insets.left = 16.0
insets.right = 16.0
insets.bottom = 0.0
let listTopInset = layoutTopInset
let listNodeSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset)
let headerHeight = self.effectiveHeaderHeight
let listTopInset = layoutTopInset + headerHeight
let listNodeSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - controlsHeight)
insets.top = max(0.0, listNodeSize.height - floor(62.0 * 3.5))
@ -1277,6 +1288,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
self.historyNode.recursivelyEnsureDisplaySynchronously(true)
}
self.replacementHistoryNodeFloatingOffset = nil
self.updateHistoryContentOffset(self.historyNode.visibleContentOffset(), transition: .immediate)
}
}

View file

@ -770,6 +770,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
randomId: result.randomId,
forwardInfo: forwardInfo,
folders: folders,
music: result.music,
uploadInfo: results.count > 1 ? StoryUploadInfo(groupingId: groupingId, index: index, total: Int32(results.count)) : nil
)
|> deliverOnMainQueue).startStandalone(next: { stableId in