Camera and editor improvements

This commit is contained in:
Ilya Laktyushin
2023-06-06 15:06:22 +04:00
parent b280850bbc
commit 3c274dbf0c
11 changed files with 372 additions and 112 deletions

View File

@@ -492,7 +492,7 @@ public enum StoryUploadResult {
case completed
}
func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text: String, entities: [MessageTextEntity], pin: Bool, privacy: EngineStoryPrivacy) -> Signal<StoryUploadResult, NoError> {
private func uploadedStoryContent(account: Account, media: EngineStoryInputMedia) -> (signal: Signal<PendingMessageUploadedContentResult?, NoError>, media: Media) {
let originalMedia: Media
let contentToUpload: MessageContentToUpload
@@ -571,48 +571,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) -> 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
@@ -622,7 +634,6 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
if pin {
flags |= 1 << 2
}
if !text.isEmpty {
flags |= 1 << 0
apiCaption = text
@@ -678,8 +689,100 @@ func _internal_uploadStory(account: Account, media: EngineStoryInputMedia, text:
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)
}
}
|> switchToLatest

View File

@@ -880,6 +880,10 @@ public extension TelegramEngine {
return _internal_uploadStory(account: self.account, media: media, text: text, entities: entities, pin: pin, privacy: privacy)
}
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> {
return _internal_deleteStory(account: self.account, id: id)
}