mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 14:20:20 +00:00
Merge commit '73987dff5d4708433fe4e3527c4738a6d784915b'
# Conflicts: # submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift
This commit is contained in:
@@ -32,6 +32,7 @@ private class AdMessagesHistoryContextImpl {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case peer
|
||||
case invite
|
||||
case webPage
|
||||
}
|
||||
|
||||
struct Invite: Equatable, Codable {
|
||||
@@ -39,8 +40,14 @@ private class AdMessagesHistoryContextImpl {
|
||||
var joinHash: String
|
||||
}
|
||||
|
||||
struct WebPage: Equatable, Codable {
|
||||
var title: String
|
||||
var url: String
|
||||
}
|
||||
|
||||
case peer(PeerId)
|
||||
case invite(Invite)
|
||||
case webPage(WebPage)
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
@@ -49,6 +56,8 @@ private class AdMessagesHistoryContextImpl {
|
||||
self = .peer(PeerId(peer))
|
||||
} else if let invite = try container.decodeIfPresent(Invite.self, forKey: .invite) {
|
||||
self = .invite(invite)
|
||||
} else if let webPage = try container.decodeIfPresent(WebPage.self, forKey: .webPage) {
|
||||
self = .webPage(webPage)
|
||||
} else {
|
||||
throw DecodingError.generic
|
||||
}
|
||||
@@ -62,6 +71,8 @@ private class AdMessagesHistoryContextImpl {
|
||||
try container.encode(peerId.toInt64(), forKey: .peer)
|
||||
case let .invite(invite):
|
||||
try container.encode(invite, forKey: .invite)
|
||||
case let .webPage(webPage):
|
||||
try container.encode(webPage, forKey: .webPage)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,6 +216,8 @@ private class AdMessagesHistoryContextImpl {
|
||||
target = .peer(id: peerId, message: self.messageId, startParam: self.startParam)
|
||||
case let .invite(invite):
|
||||
target = .join(title: invite.title, joinHash: invite.joinHash)
|
||||
case let .webPage(webPage):
|
||||
target = .webPage(title: webPage.title, url: webPage.url)
|
||||
}
|
||||
let mappedMessageType: AdMessageAttribute.MessageType
|
||||
switch self.messageType {
|
||||
@@ -251,6 +264,23 @@ private class AdMessagesHistoryContextImpl {
|
||||
defaultBannedRights: nil,
|
||||
usernames: []
|
||||
)
|
||||
case let .webPage(webPage):
|
||||
author = TelegramChannel(
|
||||
id: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(1)),
|
||||
accessHash: nil,
|
||||
title: webPage.title,
|
||||
username: nil,
|
||||
photo: [],
|
||||
creationDate: 0,
|
||||
version: 0,
|
||||
participationStatus: .left,
|
||||
info: .broadcast(TelegramChannelBroadcastInfo(flags: [])),
|
||||
flags: [],
|
||||
restrictionInfo: nil,
|
||||
adminRights: nil,
|
||||
bannedRights: nil,
|
||||
defaultBannedRights: nil,
|
||||
usernames: [])
|
||||
}
|
||||
|
||||
messagePeers[author.id] = author
|
||||
@@ -471,8 +501,7 @@ private class AdMessagesHistoryContextImpl {
|
||||
|
||||
for message in messages {
|
||||
switch message {
|
||||
case let .sponsoredMessage(flags, randomId, fromId, chatInvite, chatInviteHash, channelPost, startParam, webpage, message, entities, sponsorInfo, additionalInfo):
|
||||
let _ = webpage
|
||||
case let .sponsoredMessage(flags, randomId, fromId, chatInvite, chatInviteHash, channelPost, startParam, webPage, message, entities, sponsorInfo, additionalInfo):
|
||||
var parsedEntities: [MessageTextEntity] = []
|
||||
if let entities = entities {
|
||||
parsedEntities = messageTextEntitiesFromApiEntities(entities)
|
||||
@@ -484,6 +513,11 @@ private class AdMessagesHistoryContextImpl {
|
||||
var target: CachedMessage.Target?
|
||||
if let fromId = fromId {
|
||||
target = .peer(fromId.peerId)
|
||||
} else if let webPage = webPage {
|
||||
if case let .sponsoredWebPage(_, url, siteName, photo) = webPage {
|
||||
let _ = photo
|
||||
target = .webPage(CachedMessage.Target.WebPage(title: siteName, url: url))
|
||||
}
|
||||
} else if let chatInvite = chatInvite, let chatInviteHash = chatInviteHash {
|
||||
switch chatInvite {
|
||||
case let .chatInvite(flags, title, _, photo, participantsCount, participants):
|
||||
|
||||
@@ -507,10 +507,10 @@ public final class EngineStorySubscriptions: Equatable {
|
||||
|
||||
public enum StoryUploadResult {
|
||||
case progress(Float)
|
||||
case completed
|
||||
case completed(Int32?)
|
||||
}
|
||||
|
||||
func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, period: Int) -> Signal<StoryUploadResult, NoError> {
|
||||
private func uploadedStoryContent(account: Account, media: EngineStoryInputMedia) -> (signal: Signal<PendingMessageUploadedContentResult?, NoError>, media: Media) {
|
||||
let originalMedia: Media
|
||||
let contentToUpload: MessageContentToUpload
|
||||
|
||||
@@ -589,48 +589,60 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
|
||||
contentSignal = signal
|
||||
}
|
||||
|
||||
return contentSignal
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<PendingMessageUploadedContentResult?, NoError> in
|
||||
return .single(nil)
|
||||
return (
|
||||
contentSignal
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<PendingMessageUploadedContentResult?, NoError> in
|
||||
return .single(nil)
|
||||
},
|
||||
originalMedia
|
||||
)
|
||||
}
|
||||
|
||||
private func apiInputPrivacyRules(privacy: EngineStoryPrivacy, transaction: Transaction) -> [Api.InputPrivacyRule] {
|
||||
var privacyRules: [Api.InputPrivacyRule]
|
||||
switch privacy.base {
|
||||
case .everyone:
|
||||
privacyRules = [.inputPrivacyValueAllowAll]
|
||||
case .contacts:
|
||||
privacyRules = [.inputPrivacyValueAllowContacts]
|
||||
case .closeFriends:
|
||||
privacyRules = [.inputPrivacyValueAllowCloseFriends]
|
||||
case .nobody:
|
||||
privacyRules = [.inputPrivacyValueDisallowAll]
|
||||
}
|
||||
var privacyUsers: [Api.InputUser] = []
|
||||
var privacyChats: [Int64] = []
|
||||
for peerId in privacy.additionallyIncludePeers {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let _ = peer as? TelegramUser {
|
||||
if let inputUser = apiInputUser(peer) {
|
||||
privacyUsers.append(inputUser)
|
||||
}
|
||||
} else if peer is TelegramGroup || peer is TelegramChannel {
|
||||
privacyChats.append(peer.id.id._internalGetInt64Value())
|
||||
}
|
||||
}
|
||||
}
|
||||
if !privacyUsers.isEmpty {
|
||||
privacyRules.append(.inputPrivacyValueAllowUsers(users: privacyUsers))
|
||||
}
|
||||
if !privacyChats.isEmpty {
|
||||
privacyRules.append(.inputPrivacyValueAllowChatParticipants(chats: privacyChats))
|
||||
}
|
||||
return privacyRules
|
||||
}
|
||||
|
||||
func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, period: Int, randomId: Int64) -> Signal<StoryUploadResult, NoError> {
|
||||
let (contentSignal, originalMedia) = uploadedStoryContent(account: account, media: media)
|
||||
return contentSignal
|
||||
|> mapToSignal { result -> Signal<StoryUploadResult, NoError> in
|
||||
return account.postbox.transaction { transaction -> Signal<StoryUploadResult, NoError> in
|
||||
switch result {
|
||||
case let .progress(progress):
|
||||
return .single(.progress(progress))
|
||||
case let .content(content):
|
||||
var privacyRules: [Api.InputPrivacyRule]
|
||||
switch privacy.base {
|
||||
case .everyone:
|
||||
privacyRules = [.inputPrivacyValueAllowAll]
|
||||
case .contacts:
|
||||
privacyRules = [.inputPrivacyValueAllowContacts]
|
||||
case .closeFriends:
|
||||
privacyRules = [.inputPrivacyValueAllowCloseFriends]
|
||||
case .nobody:
|
||||
privacyRules = [.inputPrivacyValueDisallowAll]
|
||||
}
|
||||
var privacyUsers: [Api.InputUser] = []
|
||||
var privacyChats: [Int64] = []
|
||||
for peerId in privacy.additionallyIncludePeers {
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let _ = peer as? TelegramUser {
|
||||
if let inputUser = apiInputUser(peer) {
|
||||
privacyUsers.append(inputUser)
|
||||
}
|
||||
} else if peer is TelegramGroup || peer is TelegramChannel {
|
||||
privacyChats.append(peer.id.id._internalGetInt64Value())
|
||||
}
|
||||
}
|
||||
}
|
||||
if !privacyUsers.isEmpty {
|
||||
privacyRules.append(.inputPrivacyValueAllowUsers(users: privacyUsers))
|
||||
}
|
||||
if !privacyChats.isEmpty {
|
||||
privacyRules.append(.inputPrivacyValueAllowChatParticipants(chats: privacyChats))
|
||||
}
|
||||
|
||||
switch result {
|
||||
case let .progress(progress):
|
||||
return .single(.progress(progress))
|
||||
case let .content(content):
|
||||
return account.postbox.transaction { transaction -> Signal<StoryUploadResult, NoError> in
|
||||
let privacyRules = apiInputPrivacyRules(privacy: privacy, transaction: transaction)
|
||||
switch content.content {
|
||||
case let .media(inputMedia, _):
|
||||
var flags: Int32 = 0
|
||||
@@ -640,7 +652,6 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
|
||||
if pin {
|
||||
flags |= 1 << 2
|
||||
}
|
||||
|
||||
if !text.isEmpty {
|
||||
flags |= 1 << 0
|
||||
apiCaption = text
|
||||
@@ -666,7 +677,7 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
|
||||
caption: apiCaption,
|
||||
entities: apiEntities,
|
||||
privacyRules: privacyRules,
|
||||
randomId: Int64.random(in: Int64.min ... Int64.max),
|
||||
randomId: randomId,
|
||||
period: Int32(period)
|
||||
))
|
||||
|> map(Optional.init)
|
||||
@@ -674,11 +685,13 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<StoryUploadResult, NoError> in
|
||||
var id: Int32?
|
||||
if let updates = updates {
|
||||
for update in updates.allUpdates {
|
||||
if case let .updateStory(_, story) = update {
|
||||
switch story {
|
||||
case let .storyItem(_, _, _, _, _, _, media, _, _):
|
||||
case let .storyItem(_, idValue, _, _, _, _, media, _, _):
|
||||
id = idValue
|
||||
let (parsedMedia, _, _, _) = textMediaAndExpirationTimerFromApiMedia(media, account.peerId)
|
||||
if let parsedMedia = parsedMedia {
|
||||
applyMediaResourceChanges(from: originalMedia, to: parsedMedia, postbox: account.postbox, force: false)
|
||||
@@ -692,13 +705,105 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
|
||||
account.stateManager.addUpdates(updates)
|
||||
}
|
||||
|
||||
return .single(.completed)
|
||||
return .single(.completed(id))
|
||||
}
|
||||
default:
|
||||
return .complete()
|
||||
}
|
||||
default:
|
||||
return .complete()
|
||||
}
|
||||
|> switchToLatest
|
||||
default:
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func _internal_editStory(account: Account, media: EngineStoryInputMedia?, id: Int32, text: String, entities: [MessageTextEntity], privacy: EngineStoryPrivacy?) -> Signal<StoryUploadResult, NoError> {
|
||||
let contentSignal: Signal<PendingMessageUploadedContentResult?, NoError>
|
||||
let originalMedia: Media?
|
||||
if let media = media {
|
||||
(contentSignal, originalMedia) = uploadedStoryContent(account: account, media: media)
|
||||
} else {
|
||||
contentSignal = .single(nil)
|
||||
originalMedia = nil
|
||||
}
|
||||
|
||||
return contentSignal
|
||||
|> mapToSignal { result -> Signal<StoryUploadResult, NoError> in
|
||||
if let result = result, case let .progress(progress) = result {
|
||||
return .single(.progress(progress))
|
||||
}
|
||||
|
||||
let inputMedia: Api.InputMedia?
|
||||
if let result = result, case let .content(uploadedContent) = result, case let .media(media, _) = uploadedContent.content {
|
||||
inputMedia = media
|
||||
} else {
|
||||
inputMedia = nil
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> Signal<StoryUploadResult, NoError> in
|
||||
var flags: Int32 = 0
|
||||
var apiCaption: String?
|
||||
var apiEntities: [Api.MessageEntity]?
|
||||
var privacyRules: [Api.InputPrivacyRule]?
|
||||
|
||||
if let _ = inputMedia {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
if !text.isEmpty {
|
||||
flags |= 1 << 1
|
||||
apiCaption = text
|
||||
|
||||
if !entities.isEmpty {
|
||||
flags |= 1 << 1
|
||||
|
||||
var associatedPeers: [PeerId: Peer] = [:]
|
||||
for entity in entities {
|
||||
for entityPeerId in entity.associatedPeerIds {
|
||||
if let peer = transaction.getPeer(entityPeerId) {
|
||||
associatedPeers[peer.id] = peer
|
||||
}
|
||||
}
|
||||
}
|
||||
apiEntities = apiEntitiesFromMessageTextEntities(entities, associatedPeers: SimpleDictionary(associatedPeers))
|
||||
}
|
||||
}
|
||||
if let privacy = privacy {
|
||||
privacyRules = apiInputPrivacyRules(privacy: privacy, transaction: transaction)
|
||||
flags |= 1 << 2
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.stories.editStory(
|
||||
flags: flags,
|
||||
id: id,
|
||||
media: inputMedia,
|
||||
caption: apiCaption,
|
||||
entities: apiEntities,
|
||||
privacyRules: privacyRules
|
||||
))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { updates -> Signal<StoryUploadResult, NoError> in
|
||||
if let updates = updates {
|
||||
for update in updates.allUpdates {
|
||||
if case let .updateStory(_, story) = update {
|
||||
switch story {
|
||||
case let .storyItem(_, _, _, _, _, _, media, _, _):
|
||||
let (parsedMedia, _, _, _) = textMediaAndExpirationTimerFromApiMedia(media, account.peerId)
|
||||
if let parsedMedia = parsedMedia, let originalMedia = originalMedia {
|
||||
applyMediaResourceChanges(from: originalMedia, to: parsedMedia, postbox: account.postbox, force: false)
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
account.stateManager.addUpdates(updates)
|
||||
}
|
||||
|
||||
return .single(.completed(id))
|
||||
}
|
||||
}
|
||||
|> switchToLatest
|
||||
|
||||
@@ -918,8 +918,12 @@ public extension TelegramEngine {
|
||||
}
|
||||
}
|
||||
|
||||
public func uploadStory(media: EngineStoryInputMedia, text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, period: Int) -> Signal<StoryUploadResult, NoError> {
|
||||
return _internal_uploadStory(account: self.account, media: media, text: text, entities: entities, pin: pin, privacy: privacy, period: period)
|
||||
public func uploadStory(media: EngineStoryInputMedia, text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy, period: Int, randomId: Int64) -> Signal<StoryUploadResult, NoError> {
|
||||
return _internal_uploadStory(account: self.account, media: media, text: text, entities: entities, pin: pin, privacy: privacy, period: period, randomId: randomId)
|
||||
}
|
||||
|
||||
public func editStory(media: EngineStoryInputMedia?, id: Int32, text: String, entities: [MessageTextEntity], privacy: EngineStoryPrivacy?) -> Signal<StoryUploadResult, NoError> {
|
||||
return _internal_editStory(account: self.account, media: media, id: id, text: text, entities: entities, privacy: privacy)
|
||||
}
|
||||
|
||||
public func deleteStory(id: Int32) -> Signal<Never, NoError> {
|
||||
|
||||
Reference in New Issue
Block a user