mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Avatar upload improvements
This commit is contained in:
parent
8e7936bb57
commit
1b723cd2a7
@ -142,6 +142,15 @@ public enum AvatarGalleryEntry: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var emojiMarkup: TelegramMediaImage.EmojiMarkup? {
|
||||||
|
switch self {
|
||||||
|
case .topImage:
|
||||||
|
return nil
|
||||||
|
case let .image(_, _, _, _, _, _, _, _, _, _, _, markup):
|
||||||
|
return markup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var indexData: GalleryItemIndexData? {
|
public var indexData: GalleryItemIndexData? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .topImage(_, _, _, indexData, _, _):
|
case let .topImage(_, _, _, indexData, _, _):
|
||||||
@ -343,11 +352,16 @@ public func fetchedAvatarGalleryEntries(engine: TelegramEngine, account: Account
|
|||||||
let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count))
|
let indexData = GalleryItemIndexData(position: index, totalCount: Int32(photos.count))
|
||||||
if result.isEmpty, let first = initialEntries.first {
|
if result.isEmpty, let first = initialEntries.first {
|
||||||
var videoRepresentations: [VideoRepresentationWithReference] = first.videoRepresentations
|
var videoRepresentations: [VideoRepresentationWithReference] = first.videoRepresentations
|
||||||
|
var emojiMarkup: TelegramMediaImage.EmojiMarkup? = first.emojiMarkup
|
||||||
let isPersonal = first.representations.first?.representation.isPersonal == true
|
let isPersonal = first.representations.first?.representation.isPersonal == true
|
||||||
if videoRepresentations.isEmpty, !isPersonal {
|
if videoRepresentations.isEmpty, !isPersonal {
|
||||||
videoRepresentations = photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) })
|
videoRepresentations = photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) })
|
||||||
}
|
}
|
||||||
result.append(.image(photo.image.imageId, photo.image.reference, first.representations, videoRepresentations, peer, secondEntry != nil ? 0 : photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, false, photo.image.emojiMarkup))
|
if emojiMarkup == nil, !isPersonal {
|
||||||
|
emojiMarkup = photo.image.emojiMarkup
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(.image(photo.image.imageId, photo.image.reference, first.representations, videoRepresentations, peer, secondEntry != nil ? 0 : photo.date, indexData, photo.messageId, first.immediateThumbnailData ?? photo.image.immediateThumbnailData, nil, false, emojiMarkup))
|
||||||
} else {
|
} else {
|
||||||
result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, photo.image.id == lastEntry?.id, photo.image.emojiMarkup))
|
result.append(.image(photo.image.imageId, photo.image.reference, photo.image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), photo.image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: MediaResourceReference.avatarList(peer: peerReference, resource: $0.resource)) }), peer, photo.date, indexData, photo.messageId, photo.image.immediateThumbnailData, nil, photo.image.id == lastEntry?.id, photo.image.emojiMarkup))
|
||||||
}
|
}
|
||||||
|
@ -4676,6 +4676,21 @@ public extension Api.functions.messages {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.messages {
|
||||||
|
static func getEmojiProfilePhotoGroups(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.EmojiGroups>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(564480243)
|
||||||
|
serializeInt32(hash, buffer: buffer, boxed: false)
|
||||||
|
return (FunctionDescription(name: "messages.getEmojiProfilePhotoGroups", parameters: [("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.EmojiGroups? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.messages.EmojiGroups?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.messages.EmojiGroups
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.messages {
|
public extension Api.functions.messages {
|
||||||
static func getEmojiStatusGroups(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.EmojiGroups>) {
|
static func getEmojiStatusGroups(hash: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.EmojiGroups>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
@ -7764,15 +7779,16 @@ public extension Api.functions.photos {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public extension Api.functions.photos {
|
public extension Api.functions.photos {
|
||||||
static func uploadContactProfilePhoto(flags: Int32, userId: Api.InputUser, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.photos.Photo>) {
|
static func uploadContactProfilePhoto(flags: Int32, userId: Api.InputUser, file: Api.InputFile?, video: Api.InputFile?, videoStartTs: Double?, videoEmojiMarkup: Api.VideoSize?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.photos.Photo>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
buffer.appendInt32(-1189444673)
|
buffer.appendInt32(-515093903)
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
userId.serialize(buffer, true)
|
userId.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {file!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 0) != 0 {file!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 1) != 0 {video!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 1) != 0 {video!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 2) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 2) != 0 {serializeDouble(videoStartTs!, buffer: buffer, boxed: false)}
|
||||||
return (FunctionDescription(name: "photos.uploadContactProfilePhoto", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in
|
if Int(flags) & Int(1 << 5) != 0 {videoEmojiMarkup!.serialize(buffer, true)}
|
||||||
|
return (FunctionDescription(name: "photos.uploadContactProfilePhoto", parameters: [("flags", String(describing: flags)), ("userId", String(describing: userId)), ("file", String(describing: file)), ("video", String(describing: video)), ("videoStartTs", String(describing: videoStartTs)), ("videoEmojiMarkup", String(describing: videoEmojiMarkup))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.photos.Photo? in
|
||||||
let reader = BufferReader(buffer)
|
let reader = BufferReader(buffer)
|
||||||
var result: Api.photos.Photo?
|
var result: Api.photos.Photo?
|
||||||
if let signature = reader.readInt32() {
|
if let signature = reader.readInt32() {
|
||||||
|
@ -26,8 +26,8 @@ public extension TelegramEngine {
|
|||||||
return _internal_updateContactName(account: self.account, peerId: peerId, firstName: firstName, lastName: lastName)
|
return _internal_updateContactName(account: self.account, peerId: peerId, firstName: firstName, lastName: lastName)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func updateContactPhoto(peerId: PeerId, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mode: SetCustomPeerPhotoMode, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
public func updateContactPhoto(peerId: PeerId, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, markup: UploadPeerPhotoMarkup?, mode: SetCustomPeerPhotoMode, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
||||||
return _internal_updateContactPhoto(account: self.account, peerId: peerId, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mode: mode, mapResourceToAvatarSizes: mapResourceToAvatarSizes)
|
return _internal_updateContactPhoto(account: self.account, peerId: peerId, resource: resource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: mode, mapResourceToAvatarSizes: mapResourceToAvatarSizes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func deviceContactsImportedByCount(contacts: [(String, [DeviceContactNormalizedPhoneNumber])]) -> Signal<[String: Int32], NoError> {
|
public func deviceContactsImportedByCount(contacts: [(String, [DeviceContactNormalizedPhoneNumber])]) -> Signal<[String: Int32], NoError> {
|
||||||
|
@ -19,7 +19,13 @@ public enum UploadPeerPhotoMarkup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func _internal_updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, markup: UploadPeerPhotoMarkup?, fallback: Bool, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
func _internal_updateAccountPhoto(account: Account, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, markup: UploadPeerPhotoMarkup?, fallback: Bool, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
||||||
return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, markup: markup, fallback: fallback, mapResourceToAvatarSizes: mapResourceToAvatarSizes)
|
let photo: Signal<UploadedPeerPhotoData, NoError>?
|
||||||
|
if videoResource == nil && markup != nil, let resource = resource {
|
||||||
|
photo = .single(UploadedPeerPhotoData.withResource(resource))
|
||||||
|
} else {
|
||||||
|
photo = resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) })
|
||||||
|
}
|
||||||
|
return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: account.peerId, photo: photo, video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, markup: markup, fallback: fallback, mapResourceToAvatarSizes: mapResourceToAvatarSizes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum SetCustomPeerPhotoMode {
|
public enum SetCustomPeerPhotoMode {
|
||||||
@ -28,13 +34,14 @@ public enum SetCustomPeerPhotoMode {
|
|||||||
case customAndSuggest
|
case customAndSuggest
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_updateContactPhoto(account: Account, peerId: PeerId, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, mode: SetCustomPeerPhotoMode, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
func _internal_updateContactPhoto(account: Account, peerId: PeerId, resource: MediaResource?, videoResource: MediaResource?, videoStartTimestamp: Double?, markup: UploadPeerPhotoMarkup?, mode: SetCustomPeerPhotoMode, mapResourceToAvatarSizes: @escaping (MediaResource, [TelegramMediaImageRepresentation]) -> Signal<[Int: Data], NoError>) -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> {
|
||||||
return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, customPeerPhotoMode: mode, mapResourceToAvatarSizes: mapResourceToAvatarSizes)
|
return _internal_updatePeerPhoto(postbox: account.postbox, network: account.network, stateManager: account.stateManager, accountPeerId: account.peerId, peerId: peerId, photo: resource.flatMap({ _internal_uploadedPeerPhoto(postbox: account.postbox, network: account.network, resource: $0) }), video: videoResource.flatMap({ _internal_uploadedPeerVideo(postbox: account.postbox, network: account.network, messageMediaPreuploadManager: account.messageMediaPreuploadManager, resource: $0) |> map(Optional.init) }), videoStartTimestamp: videoStartTimestamp, markup: markup, customPeerPhotoMode: mode, mapResourceToAvatarSizes: mapResourceToAvatarSizes)
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UploadedPeerPhotoData {
|
public struct UploadedPeerPhotoData {
|
||||||
fileprivate let resource: MediaResource
|
fileprivate let resource: MediaResource
|
||||||
fileprivate let content: UploadedPeerPhotoDataContent
|
fileprivate let content: UploadedPeerPhotoDataContent
|
||||||
|
fileprivate let local: Bool
|
||||||
|
|
||||||
public var isCompleted: Bool {
|
public var isCompleted: Bool {
|
||||||
if case let .result(result) = content, case .inputFile = result {
|
if case let .result(result) = content, case .inputFile = result {
|
||||||
@ -43,6 +50,10 @@ public struct UploadedPeerPhotoData {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func withResource(_ resource: MediaResource) -> UploadedPeerPhotoData {
|
||||||
|
return UploadedPeerPhotoData(resource: resource, content: .result(.inputFile(.inputFile(id: 0, parts: 0, name: "", md5Checksum: ""))), local: true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UploadedPeerPhotoDataContent {
|
enum UploadedPeerPhotoDataContent {
|
||||||
@ -53,10 +64,10 @@ enum UploadedPeerPhotoDataContent {
|
|||||||
func _internal_uploadedPeerPhoto(postbox: Postbox, network: Network, resource: MediaResource) -> Signal<UploadedPeerPhotoData, NoError> {
|
func _internal_uploadedPeerPhoto(postbox: Postbox, network: Network, resource: MediaResource) -> Signal<UploadedPeerPhotoData, NoError> {
|
||||||
return multipartUpload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image, userContentType: .image), hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: false)
|
return multipartUpload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .image, userContentType: .image), hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: false)
|
||||||
|> map { result -> UploadedPeerPhotoData in
|
|> map { result -> UploadedPeerPhotoData in
|
||||||
return UploadedPeerPhotoData(resource: resource, content: .result(result))
|
return UploadedPeerPhotoData(resource: resource, content: .result(result), local: false)
|
||||||
}
|
}
|
||||||
|> `catch` { _ -> Signal<UploadedPeerPhotoData, NoError> in
|
|> `catch` { _ -> Signal<UploadedPeerPhotoData, NoError> in
|
||||||
return .single(UploadedPeerPhotoData(resource: resource, content: .error))
|
return .single(UploadedPeerPhotoData(resource: resource, content: .error, local: false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,18 +75,18 @@ func _internal_uploadedPeerVideo(postbox: Postbox, network: Network, messageMedi
|
|||||||
if let messageMediaPreuploadManager = messageMediaPreuploadManager {
|
if let messageMediaPreuploadManager = messageMediaPreuploadManager {
|
||||||
return messageMediaPreuploadManager.upload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .video, userContentType: .video), hintFileSize: nil, hintFileIsLarge: false)
|
return messageMediaPreuploadManager.upload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .video, userContentType: .video), hintFileSize: nil, hintFileIsLarge: false)
|
||||||
|> map { result -> UploadedPeerPhotoData in
|
|> map { result -> UploadedPeerPhotoData in
|
||||||
return UploadedPeerPhotoData(resource: resource, content: .result(result))
|
return UploadedPeerPhotoData(resource: resource, content: .result(result), local: false)
|
||||||
}
|
}
|
||||||
|> `catch` { _ -> Signal<UploadedPeerPhotoData, NoError> in
|
|> `catch` { _ -> Signal<UploadedPeerPhotoData, NoError> in
|
||||||
return .single(UploadedPeerPhotoData(resource: resource, content: .error))
|
return .single(UploadedPeerPhotoData(resource: resource, content: .error, local: false))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return multipartUpload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .video, userContentType: .video), hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: false)
|
return multipartUpload(network: network, postbox: postbox, source: .resource(.standalone(resource: resource)), encrypt: false, tag: TelegramMediaResourceFetchTag(statsCategory: .video, userContentType: .video), hintFileSize: nil, hintFileIsLarge: false, forceNoBigParts: false)
|
||||||
|> map { result -> UploadedPeerPhotoData in
|
|> map { result -> UploadedPeerPhotoData in
|
||||||
return UploadedPeerPhotoData(resource: resource, content: .result(result))
|
return UploadedPeerPhotoData(resource: resource, content: .result(result), local: false)
|
||||||
}
|
}
|
||||||
|> `catch` { _ -> Signal<UploadedPeerPhotoData, NoError> in
|
|> `catch` { _ -> Signal<UploadedPeerPhotoData, NoError> in
|
||||||
return .single(UploadedPeerPhotoData(resource: resource, content: .error))
|
return .single(UploadedPeerPhotoData(resource: resource, content: .error, local: false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -88,6 +99,16 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
return peer
|
return peer
|
||||||
|> mapError { _ -> UploadPeerPhotoError in }
|
|> mapError { _ -> UploadPeerPhotoError in }
|
||||||
|> mapToSignal { peer -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
|> mapToSignal { peer -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
||||||
|
var videoEmojiMarkup: Api.VideoSize?
|
||||||
|
if let markup = markup {
|
||||||
|
switch markup {
|
||||||
|
case let .emoji(fileId, backgroundColors):
|
||||||
|
videoEmojiMarkup = .videoSizeEmojiMarkup(emojiId: fileId, backgroundColors: backgroundColors)
|
||||||
|
case let .sticker(packReference, fileId, backgroundColors):
|
||||||
|
videoEmojiMarkup = .videoSizeStickerMarkup(stickerset: packReference.apiInputStickerSet, stickerId: fileId, backgroundColors: backgroundColors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let photo = photo {
|
if let photo = photo {
|
||||||
let mappedPhoto = photo
|
let mappedPhoto = photo
|
||||||
|> take(until: { value in
|
|> take(until: { value in
|
||||||
@ -146,8 +167,16 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var photoFile: Api.InputFile?
|
||||||
|
if !photoResult.local {
|
||||||
|
photoFile = file
|
||||||
|
}
|
||||||
|
|
||||||
if peer is TelegramUser {
|
if peer is TelegramUser {
|
||||||
var flags: Int32 = (1 << 0)
|
var flags: Int32 = 0
|
||||||
|
if let _ = photoFile {
|
||||||
|
flags = (1 << 0)
|
||||||
|
}
|
||||||
if let _ = videoFile {
|
if let _ = videoFile {
|
||||||
flags |= (1 << 1)
|
flags |= (1 << 1)
|
||||||
if let _ = videoStartTimestamp {
|
if let _ = videoStartTimestamp {
|
||||||
@ -155,23 +184,15 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoEmojiMarkup: Api.VideoSize?
|
|
||||||
if let markup = markup{
|
|
||||||
switch markup {
|
|
||||||
case let .emoji(fileId, backgroundColors):
|
|
||||||
videoEmojiMarkup = .videoSizeEmojiMarkup(emojiId: fileId, backgroundColors: backgroundColors)
|
|
||||||
case let .sticker(packReference, fileId, backgroundColors):
|
|
||||||
videoEmojiMarkup = .videoSizeStickerMarkup(stickerset: packReference.apiInputStickerSet, stickerId: fileId, backgroundColors: backgroundColors)
|
|
||||||
}
|
|
||||||
flags |= (1 << 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
let request: Signal<Api.photos.Photo, MTRpcError>
|
let request: Signal<Api.photos.Photo, MTRpcError>
|
||||||
if peer.id == accountPeerId {
|
if peer.id == accountPeerId {
|
||||||
if fallback {
|
if fallback {
|
||||||
flags |= (1 << 3)
|
flags |= (1 << 3)
|
||||||
}
|
}
|
||||||
request = network.request(Api.functions.photos.uploadProfilePhoto(flags: flags, file: file, video: videoFile, videoStartTs: videoStartTimestamp, videoEmojiMarkup: videoEmojiMarkup))
|
if let _ = videoEmojiMarkup {
|
||||||
|
flags |= (1 << 4)
|
||||||
|
}
|
||||||
|
request = network.request(Api.functions.photos.uploadProfilePhoto(flags: flags, file: photoFile, video: videoFile, videoStartTs: videoStartTimestamp, videoEmojiMarkup: videoEmojiMarkup))
|
||||||
} else if let inputUser = apiInputUser(peer) {
|
} else if let inputUser = apiInputUser(peer) {
|
||||||
if let customPeerPhotoMode = customPeerPhotoMode {
|
if let customPeerPhotoMode = customPeerPhotoMode {
|
||||||
switch customPeerPhotoMode {
|
switch customPeerPhotoMode {
|
||||||
@ -184,8 +205,10 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
flags |= (1 << 4)
|
flags |= (1 << 4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let _ = videoEmojiMarkup {
|
||||||
request = network.request(Api.functions.photos.uploadContactProfilePhoto(flags: flags, userId: inputUser, file: file, video: videoFile, videoStartTs: videoStartTimestamp))
|
flags |= (1 << 5)
|
||||||
|
}
|
||||||
|
request = network.request(Api.functions.photos.uploadContactProfilePhoto(flags: flags, userId: inputUser, file: file, video: videoFile, videoStartTs: videoStartTimestamp, videoEmojiMarkup: videoEmojiMarkup))
|
||||||
} else {
|
} else {
|
||||||
request = .complete()
|
request = .complete()
|
||||||
}
|
}
|
||||||
@ -273,6 +296,14 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if peer.id == accountPeerId && customPeerPhotoMode == nil {
|
||||||
|
transaction.updatePeerCachedData(peerIds: Set([peer.id])) { peerId, cachedPeerData in
|
||||||
|
if let cachedPeerData = cachedPeerData as? CachedUserData {
|
||||||
|
return cachedPeerData.withUpdatedPhoto(.known(image))
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (.complete(representations), photoResult.resource, videoResult?.resource)
|
return (.complete(representations), photoResult.resource, videoResult?.resource)
|
||||||
@ -287,14 +318,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoEmojiMarkup: Api.VideoSize?
|
if let _ = videoEmojiMarkup {
|
||||||
if let markup = markup {
|
|
||||||
switch markup {
|
|
||||||
case let .emoji(fileId, backgroundColors):
|
|
||||||
videoEmojiMarkup = .videoSizeEmojiMarkup(emojiId: fileId, backgroundColors: backgroundColors)
|
|
||||||
case let .sticker(packReference, fileId, backgroundColors):
|
|
||||||
videoEmojiMarkup = .videoSizeStickerMarkup(stickerset: packReference.apiInputStickerSet, stickerId: fileId, backgroundColors: backgroundColors)
|
|
||||||
}
|
|
||||||
flags |= (1 << 3)
|
flags |= (1 << 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +412,7 @@ func _internal_updatePeerPhotoInternal(postbox: Postbox, network: Network, state
|
|||||||
request = network.request(Api.functions.photos.updateProfilePhoto(flags: flags, id: Api.InputPhoto.inputPhotoEmpty))
|
request = network.request(Api.functions.photos.updateProfilePhoto(flags: flags, id: Api.InputPhoto.inputPhotoEmpty))
|
||||||
} else if let inputUser = apiInputUser(peer) {
|
} else if let inputUser = apiInputUser(peer) {
|
||||||
let flags: Int32 = (1 << 4)
|
let flags: Int32 = (1 << 4)
|
||||||
request = network.request(Api.functions.photos.uploadContactProfilePhoto(flags: flags, userId: inputUser, file: nil, video: nil, videoStartTs: nil))
|
request = network.request(Api.functions.photos.uploadContactProfilePhoto(flags: flags, userId: inputUser, file: nil, video: nil, videoStartTs: nil, videoEmojiMarkup: nil))
|
||||||
} else {
|
} else {
|
||||||
request = .complete()
|
request = .complete()
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import GalleryUI
|
|||||||
import HierarchyTrackingLayer
|
import HierarchyTrackingLayer
|
||||||
import WallpaperBackgroundNode
|
import WallpaperBackgroundNode
|
||||||
import ChatControllerInteraction
|
import ChatControllerInteraction
|
||||||
|
import AvatarVideoNode
|
||||||
|
|
||||||
private let timezoneOffset: Int32 = {
|
private let timezoneOffset: Int32 = {
|
||||||
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
let nowTimestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||||
@ -446,20 +447,17 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
|
|
||||||
private let containerNode: ContextControllerSourceNode
|
private let containerNode: ContextControllerSourceNode
|
||||||
private let avatarNode: AvatarNode
|
private let avatarNode: AvatarNode
|
||||||
private var videoNode: UniversalVideoNode?
|
private var avatarVideoNode: AvatarVideoNode?
|
||||||
|
|
||||||
private var videoContent: NativeVideoContent?
|
|
||||||
private let playbackStartDisposable = MetaDisposable()
|
|
||||||
private var cachedDataDisposable = MetaDisposable()
|
private var cachedDataDisposable = MetaDisposable()
|
||||||
private var hierarchyTrackingLayer: HierarchyTrackingLayer?
|
private var hierarchyTrackingLayer: HierarchyTrackingLayer?
|
||||||
private var videoLoopCount = 0
|
|
||||||
|
|
||||||
private var trackingIsInHierarchy: Bool = false {
|
private var trackingIsInHierarchy: Bool = false {
|
||||||
didSet {
|
didSet {
|
||||||
if self.trackingIsInHierarchy != oldValue {
|
if self.trackingIsInHierarchy != oldValue {
|
||||||
Queue.mainQueue().justDispatch {
|
Queue.mainQueue().justDispatch {
|
||||||
if self.trackingIsInHierarchy {
|
if self.trackingIsInHierarchy {
|
||||||
self.videoLoopCount = 0
|
self.avatarVideoNode?.resetPlayback()
|
||||||
}
|
}
|
||||||
self.updateVideoVisibility()
|
self.updateVideoVisibility()
|
||||||
}
|
}
|
||||||
@ -507,7 +505,6 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.cachedDataDisposable.dispose()
|
self.cachedDataDisposable.dispose()
|
||||||
self.playbackStartDisposable.dispose()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor) {
|
func setCustomLetters(context: AccountContext, theme: PresentationTheme, synchronousLoad: Bool, letters: [String], emptyColor: UIColor) {
|
||||||
@ -531,16 +528,35 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let cachedPeerData = peerView.cachedData
|
|
||||||
if let cachedPeerData = cachedPeerData as? CachedUserData, case let .known(maybePhoto) = cachedPeerData.photo {
|
let cachedPeerData = peerView.cachedData as? CachedUserData
|
||||||
if let photo = maybePhoto, let video = photo.videoRepresentations.last, let peerReference = PeerReference(peer) {
|
var personalPhoto: TelegramMediaImage?
|
||||||
let videoId = photo.id?.id ?? peer.id.id._internalGetInt64Value()
|
var profilePhoto: TelegramMediaImage?
|
||||||
let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
var isKnown = false
|
||||||
let videoContent = NativeVideoContent(id: .profileVideo(videoId, "\(Int32.random(in: 0 ..< Int32.max))"), userLocation: .other, fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: false, storeAfterDownload: nil)
|
|
||||||
if videoContent.id != strongSelf.videoContent?.id {
|
if let cachedPeerData = cachedPeerData {
|
||||||
strongSelf.videoNode?.removeFromSupernode()
|
if case let .known(maybePersonalPhoto) = cachedPeerData.personalPhoto {
|
||||||
strongSelf.videoContent = videoContent
|
personalPhoto = maybePersonalPhoto
|
||||||
|
isKnown = true
|
||||||
}
|
}
|
||||||
|
if case let .known(maybePhoto) = cachedPeerData.photo {
|
||||||
|
profilePhoto = maybePhoto
|
||||||
|
isKnown = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if isKnown {
|
||||||
|
let photo = personalPhoto ?? profilePhoto
|
||||||
|
if let photo = photo, !photo.videoRepresentations.isEmpty || photo.emojiMarkup != nil {
|
||||||
|
let videoNode: AvatarVideoNode
|
||||||
|
if let current = strongSelf.avatarVideoNode {
|
||||||
|
videoNode = current
|
||||||
|
} else {
|
||||||
|
videoNode = AvatarVideoNode(context: context)
|
||||||
|
strongSelf.avatarNode.addSubnode(videoNode)
|
||||||
|
strongSelf.avatarVideoNode = videoNode
|
||||||
|
}
|
||||||
|
videoNode.update(peer: EnginePeer(peer), photo: photo, size: CGSize(width: 38.0, height: 38.0))
|
||||||
|
|
||||||
if strongSelf.hierarchyTrackingLayer == nil {
|
if strongSelf.hierarchyTrackingLayer == nil {
|
||||||
let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
||||||
@ -561,23 +577,65 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
strongSelf.layer.addSublayer(hierarchyTrackingLayer)
|
strongSelf.layer.addSublayer(hierarchyTrackingLayer)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strongSelf.videoContent = nil
|
if let avatarVideoNode = strongSelf.avatarVideoNode {
|
||||||
|
avatarVideoNode.removeFromSupernode()
|
||||||
|
strongSelf.avatarVideoNode = nil
|
||||||
|
}
|
||||||
strongSelf.hierarchyTrackingLayer?.removeFromSuperlayer()
|
strongSelf.hierarchyTrackingLayer?.removeFromSuperlayer()
|
||||||
strongSelf.hierarchyTrackingLayer = nil
|
strongSelf.hierarchyTrackingLayer = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.updateVideoVisibility()
|
strongSelf.updateVideoVisibility()
|
||||||
} else {
|
} else {
|
||||||
let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peer.id).start()
|
let _ = context.engine.peers.fetchAndUpdateCachedPeerData(peerId: peer.id).start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// let cachedPeerData = peerView.cachedData
|
||||||
|
// if let cachedPeerData = cachedPeerData as? CachedUserData, case let .known(maybePhoto) = cachedPeerData.photo {
|
||||||
|
// if let photo = maybePhoto, let video = photo.videoRepresentations.last, let peerReference = PeerReference(peer) {
|
||||||
|
// let videoId = photo.id?.id ?? peer.id.id._internalGetInt64Value()
|
||||||
|
// let videoFileReference = FileMediaReference.avatarList(peer: peerReference, media: TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: 0), partialReference: nil, resource: video.resource, previewRepresentations: photo.representations, videoThumbnails: [], immediateThumbnailData: photo.immediateThumbnailData, mimeType: "video/mp4", size: nil, attributes: [.Animated, .Video(duration: 0, size: video.dimensions, flags: [])]))
|
||||||
|
// let videoContent = NativeVideoContent(id: .profileVideo(videoId, "\(Int32.random(in: 0 ..< Int32.max))"), userLocation: .other, fileReference: videoFileReference, streamVideo: isMediaStreamable(resource: video.resource) ? .conservative : .none, loopVideo: true, enableSound: false, fetchAutomatically: true, onlyFullSizeThumbnail: false, useLargeThumbnail: true, autoFetchFullSizeThumbnail: true, startTimestamp: video.startTimestamp, continuePlayingWithoutSoundOnLostAudioSession: false, placeholderColor: .clear, captureProtected: false, storeAfterDownload: nil)
|
||||||
|
// if videoContent.id != strongSelf.videoContent?.id {
|
||||||
|
// strongSelf.videoNode?.removeFromSupernode()
|
||||||
|
// strongSelf.videoContent = videoContent
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if strongSelf.hierarchyTrackingLayer == nil {
|
||||||
|
// let hierarchyTrackingLayer = HierarchyTrackingLayer()
|
||||||
|
// hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in
|
||||||
|
// guard let strongSelf = self else {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// strongSelf.trackingIsInHierarchy = true
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// hierarchyTrackingLayer.didExitHierarchy = { [weak self] in
|
||||||
|
// guard let strongSelf = self else {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// strongSelf.trackingIsInHierarchy = false
|
||||||
|
// }
|
||||||
|
// strongSelf.hierarchyTrackingLayer = hierarchyTrackingLayer
|
||||||
|
// strongSelf.layer.addSublayer(hierarchyTrackingLayer)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// strongSelf.videoContent = nil
|
||||||
|
//
|
||||||
|
// strongSelf.hierarchyTrackingLayer?.removeFromSuperlayer()
|
||||||
|
// strongSelf.hierarchyTrackingLayer = nil
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// strongSelf.updateVideoVisibility()
|
||||||
|
// } else {
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
self.cachedDataDisposable.set(nil)
|
self.cachedDataDisposable.set(nil)
|
||||||
self.videoContent = nil
|
|
||||||
|
|
||||||
self.videoNode?.removeFromSupernode()
|
self.avatarVideoNode?.removeFromSupernode()
|
||||||
self.videoNode = nil
|
self.avatarVideoNode = nil
|
||||||
|
|
||||||
self.hierarchyTrackingLayer?.removeFromSuperlayer()
|
self.hierarchyTrackingLayer?.removeFromSuperlayer()
|
||||||
self.hierarchyTrackingLayer = nil
|
self.hierarchyTrackingLayer = nil
|
||||||
@ -659,74 +717,12 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateVideoVisibility() {
|
private func updateVideoVisibility() {
|
||||||
let context = self.context
|
|
||||||
let isVisible = self.trackingIsInHierarchy
|
let isVisible = self.trackingIsInHierarchy
|
||||||
if isVisible, let videoContent = self.videoContent, self.videoLoopCount != maxVideoLoopCount {
|
self.avatarVideoNode?.updateVisibility(isVisible)
|
||||||
if self.videoNode == nil {
|
|
||||||
let mediaManager = context.sharedContext.mediaManager
|
|
||||||
let videoNode = UniversalVideoNode(postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: GalleryVideoDecoration(), content: videoContent, priority: .embedded)
|
|
||||||
videoNode.clipsToBounds = true
|
|
||||||
videoNode.isUserInteractionEnabled = false
|
|
||||||
videoNode.isHidden = true
|
|
||||||
videoNode.playbackCompleted = { [weak self] in
|
|
||||||
Queue.mainQueue().async {
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.videoLoopCount += 1
|
|
||||||
if strongSelf.videoLoopCount == maxVideoLoopCount {
|
|
||||||
if let videoNode = strongSelf.videoNode {
|
|
||||||
strongSelf.videoNode = nil
|
|
||||||
videoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak videoNode] _ in
|
|
||||||
videoNode?.removeFromSupernode()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let _ = videoContent.startTimestamp {
|
if let videoNode = self.avatarVideoNode {
|
||||||
self.playbackStartDisposable.set((videoNode.status
|
videoNode.updateLayout(size: self.avatarNode.frame.size, cornerRadius: self.avatarNode.frame.size.width / 2.0, transition: .immediate)
|
||||||
|> map { status -> Bool in
|
videoNode.frame = self.avatarNode.bounds
|
||||||
if let status = status, case .playing = status.status {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|> filter { playing in
|
|
||||||
return playing
|
|
||||||
}
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).start(completed: { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
Queue.mainQueue().after(0.15) {
|
|
||||||
strongSelf.videoNode?.isHidden = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
self.playbackStartDisposable.set(nil)
|
|
||||||
videoNode.isHidden = false
|
|
||||||
}
|
|
||||||
videoNode.layer.cornerRadius = self.avatarNode.frame.size.width / 2.0
|
|
||||||
if #available(iOS 13.0, *) {
|
|
||||||
videoNode.layer.cornerCurve = .circular
|
|
||||||
}
|
|
||||||
|
|
||||||
videoNode.canAttachContent = true
|
|
||||||
videoNode.play()
|
|
||||||
|
|
||||||
self.containerNode.insertSubnode(videoNode, aboveSubnode: self.avatarNode)
|
|
||||||
self.videoNode = videoNode
|
|
||||||
}
|
|
||||||
} else if let videoNode = self.videoNode {
|
|
||||||
self.videoNode = nil
|
|
||||||
videoNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
|
|
||||||
if let videoNode = self.videoNode {
|
|
||||||
videoNode.updateLayout(size: self.avatarNode.frame.size, transition: .immediate)
|
|
||||||
videoNode.frame = self.avatarNode.frame
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6919,11 +6919,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if case .custom = mode {
|
} else if case .custom = mode {
|
||||||
signal = self.context.engine.contacts.updateContactPhoto(peerId: self.peerId, resource: resource, videoResource: nil, videoStartTimestamp: nil, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
signal = self.context.engine.contacts.updateContactPhoto(peerId: self.peerId, resource: resource, videoResource: nil, videoStartTimestamp: nil, markup: nil, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} else if case .suggest = mode {
|
} else if case .suggest = mode {
|
||||||
signal = self.context.engine.contacts.updateContactPhoto(peerId: self.peerId, resource: resource, videoResource: nil, videoStartTimestamp: nil, mode: .suggest, mapResourceToAvatarSizes: { resource, representations in
|
signal = self.context.engine.contacts.updateContactPhoto(peerId: self.peerId, resource: resource, videoResource: nil, videoStartTimestamp: nil, markup: nil, mode: .suggest, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -7030,9 +7030,30 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue
|
videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var markup: UploadPeerPhotoMarkup? = nil
|
||||||
|
if let fileId = adjustments?.documentId, let backgroundColors = adjustments?.colors as? [Int32], fileId != 0 {
|
||||||
|
if let packId = adjustments?.stickerPackId, let accessHash = adjustments?.stickerPackAccessHash, packId != 0 {
|
||||||
|
markup = .sticker(packReference: .id(id: packId, accessHash: accessHash), fileId: fileId, backgroundColors: backgroundColors)
|
||||||
|
} else {
|
||||||
|
markup = .emoji(fileId: fileId, backgroundColors: backgroundColors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var uploadVideo = true
|
||||||
|
if let _ = markup {
|
||||||
|
if let data = self.context.currentAppConfiguration.with({ $0 }).data, let uploadVideoValue = data["upload_markup_video"] as? Bool, uploadVideoValue {
|
||||||
|
uploadVideo = true
|
||||||
|
} else {
|
||||||
|
uploadVideo = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let account = self.context.account
|
let account = self.context.account
|
||||||
let context = self.context
|
let context = self.context
|
||||||
let signal = Signal<TelegramMediaResource, UploadPeerPhotoError> { [weak self] subscriber in
|
|
||||||
|
let videoResource: Signal<TelegramMediaResource?, UploadPeerPhotoError>
|
||||||
|
if uploadVideo {
|
||||||
|
videoResource = Signal<TelegramMediaResource?, UploadPeerPhotoError> { [weak self] subscriber in
|
||||||
let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in
|
let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in
|
||||||
if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
|
if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
|
||||||
return LegacyPaintEntityRenderer(account: account, adjustments: adjustments)
|
return LegacyPaintEntityRenderer(account: account, adjustments: adjustments)
|
||||||
@ -7110,6 +7131,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
disposable.dispose()
|
disposable.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
videoResource = .single(nil)
|
||||||
|
}
|
||||||
|
|
||||||
var dismissStatus: (() -> Void)?
|
var dismissStatus: (() -> Void)?
|
||||||
if [.suggest, .fallback, .accept].contains(mode) {
|
if [.suggest, .fallback, .accept].contains(mode) {
|
||||||
@ -7131,17 +7155,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
let peerId = self.peerId
|
let peerId = self.peerId
|
||||||
let isSettings = self.isSettings
|
let isSettings = self.isSettings
|
||||||
self.updateAvatarDisposable.set((signal
|
self.updateAvatarDisposable.set((videoResource
|
||||||
|> mapToSignal { videoResource -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
|> mapToSignal { videoResource -> Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError> in
|
||||||
var markup: UploadPeerPhotoMarkup? = nil
|
|
||||||
if isSettings {
|
if isSettings {
|
||||||
if let fileId = adjustments?.documentId, let backgroundColors = adjustments?.colors as? [Int32], fileId != 0 {
|
|
||||||
if let packId = adjustments?.stickerPackId, let accessHash = adjustments?.stickerPackAccessHash, packId != 0 {
|
|
||||||
markup = .sticker(packReference: .id(id: packId, accessHash: accessHash), fileId: fileId, backgroundColors: backgroundColors)
|
|
||||||
} else {
|
|
||||||
markup = .emoji(fileId: fileId, backgroundColors: backgroundColors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if case .fallback = mode {
|
if case .fallback = mode {
|
||||||
return context.engine.accountData.updateFallbackPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
return context.engine.accountData.updateFallbackPhoto(resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||||
@ -7152,15 +7168,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else if case .custom = mode {
|
} else if case .custom = mode {
|
||||||
return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} else if case .suggest = mode {
|
} else if case .suggest = mode {
|
||||||
return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, mode: .suggest, mapResourceToAvatarSizes: { resource, representations in
|
return context.engine.contacts.updateContactPhoto(peerId: peerId, resource: photoResource, videoResource: videoResource, videoStartTimestamp: videoStartTimestamp, markup: markup, mode: .suggest, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: photoResource), video: context.engine.peers.uploadedPeerVideo(resource: videoResource) |> map(Optional.init), videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
return context.engine.peers.updatePeerPhoto(peerId: peerId, photo: context.engine.peers.uploadedPeerPhoto(resource: photoResource), video: videoResource.flatMap { context.engine.peers.uploadedPeerVideo(resource: $0) |> map(Optional.init) }, videoStartTimestamp: videoStartTimestamp, markup: markup, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: account.postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -7418,7 +7434,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
let postbox = strongSelf.context.account.postbox
|
let postbox = strongSelf.context.account.postbox
|
||||||
let signal: Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError>
|
let signal: Signal<UpdatePeerPhotoStatus, UploadPeerPhotoError>
|
||||||
if case .custom = mode {
|
if case .custom = mode {
|
||||||
signal = strongSelf.context.engine.contacts.updateContactPhoto(peerId: strongSelf.peerId, resource: nil, videoResource: nil, videoStartTimestamp: nil, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
signal = strongSelf.context.engine.contacts.updateContactPhoto(peerId: strongSelf.peerId, resource: nil, videoResource: nil, videoStartTimestamp: nil, markup: nil, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
||||||
return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations)
|
return mapResourceToAvatarSizes(postbox: postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
} else if case .fallback = mode {
|
} else if case .fallback = mode {
|
||||||
@ -8507,7 +8523,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
strongSelf.updateAvatarDisposable.set((strongSelf.context.engine.contacts.updateContactPhoto(peerId: strongSelf.peerId, resource: nil, videoResource: nil, videoStartTimestamp: nil, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
strongSelf.updateAvatarDisposable.set((strongSelf.context.engine.contacts.updateContactPhoto(peerId: strongSelf.peerId, resource: nil, videoResource: nil, videoStartTimestamp: nil, markup: nil, mode: .custom, mapResourceToAvatarSizes: { resource, representations in
|
||||||
mapResourceToAvatarSizes(postbox: strongSelf.context.account.postbox, resource: resource, representations: representations)
|
mapResourceToAvatarSizes(postbox: strongSelf.context.account.postbox, resource: resource, representations: representations)
|
||||||
})
|
})
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user