Video avatar fixes

This commit is contained in:
Ilya Laktyushin 2020-07-10 13:02:28 +03:00
parent 37cfe95fb6
commit 688d692993
5 changed files with 136 additions and 21 deletions

View File

@ -563,8 +563,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
if strongSelf.updatingAvatarOverlay.supernode == nil {
strongSelf.insertSubnode(strongSelf.updatingAvatarOverlay, aboveSubnode: strongSelf.avatarNode)
}
if let updatingImage = item.updatingImage, case .image(_, true) = updatingImage {
strongSelf.activityIndicator.isHidden = false
if let updatingImage = item.updatingImage, case let .image(_, loading) = updatingImage {
strongSelf.activityIndicator.isHidden = !loading
}
} else if strongSelf.updatingAvatarOverlay.supernode != nil {
if animated {

View File

@ -83,7 +83,7 @@ final class AuthorizationSequenceSignUpController: ViewController {
let currentAvatarMixin = Atomic<NSObject?>(value: nil)
self.displayNode = AuthorizationSequenceSignUpControllerNode(theme: self.presentationData.theme, strings: self.presentationData.strings, addPhoto: { [weak self] in
presentLegacyAvatarPicker(holder: currentAvatarMixin, signup: true, theme: defaultPresentationTheme, present: { c, a in
presentLegacyAvatarPicker(holder: currentAvatarMixin, signup: false, theme: defaultPresentationTheme, present: { c, a in
self?.view.endEditing(true)
self?.present(c, in: .window(.root), with: a)
}, openCurrent: nil, completion: { image in

View File

@ -17,6 +17,7 @@ import ItemListAvatarAndNameInfoItem
import WebSearchUI
import PeerInfoUI
import MapResourceToAvatarSizes
import LegacyMediaPickerUI
private struct CreateChannelArguments {
let context: AccountContext
@ -214,6 +215,7 @@ public func createChannelController(context: AccountContext) -> ViewController {
let currentAvatarMixin = Atomic<TGMediaAvatarMenuMixin?>(value: nil)
let uploadedAvatar = Promise<UploadedPeerPhotoData>()
var uploadedVideoAvatar: (Promise<UploadedPeerPhotoData?>, Double?)? = nil
let arguments = CreateChannelArguments(context: context, updateEditingName: { editingName in
updateState { current in
@ -260,7 +262,7 @@ public func createChannelController(context: AccountContext) -> ViewController {
return $0.avatar
}
if let _ = updatingAvatar {
let _ = updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), mapResourceToAvatarSizes: { resource, representations in
let _ = updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations)
}).start()
}
@ -311,12 +313,13 @@ public func createChannelController(context: AccountContext) -> ViewController {
endEditingImpl?()
presentControllerImpl?(legacyController, nil)
let completedImpl: (UIImage) -> Void = { image in
let completedChannelPhotoImpl: (UIImage) -> Void = { image in
if let data = image.jpegData(compressionQuality: 0.6) {
let resource = LocalFileMediaResource(fileId: arc4random64())
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data)
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: resource)
uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: resource))
uploadedVideoAvatar = nil
updateState { current in
var current = current
current.avatar = .image(representation, false)
@ -325,18 +328,113 @@ public func createChannelController(context: AccountContext) -> ViewController {
}
}
let completedChannelVideoImpl: (UIImage, URL, TGVideoEditAdjustments?) -> Void = { image, url, adjustments in
if let data = image.jpegData(compressionQuality: 0.6) {
let photoResource = LocalFileMediaResource(fileId: arc4random64())
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
let representation = TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 640, height: 640), resource: photoResource)
updateState { state in
var state = state
state.avatar = .image(representation, true)
return state
}
var videoStartTimestamp: Double? = nil
if let adjustments = adjustments, adjustments.videoStartValue > 0.0 {
videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue
}
let signal = Signal<TelegramMediaResource?, UploadPeerPhotoError> { subscriber in
var filteredPath = url.path
if filteredPath.hasPrefix("file://") {
filteredPath = String(filteredPath[filteredPath.index(filteredPath.startIndex, offsetBy: "file://".count)])
}
let avAsset = AVURLAsset(url: URL(fileURLWithPath: filteredPath))
let entityRenderer: LegacyPaintEntityRenderer? = adjustments.flatMap { adjustments in
if let paintingData = adjustments.paintingData, paintingData.hasAnimation {
return LegacyPaintEntityRenderer(account: context.account, adjustments: adjustments)
} else {
return nil
}
}
let uploadInterface = LegacyLiveUploadInterface(account: context.account)
let signal = TGMediaVideoConverter.convert(avAsset, adjustments: adjustments, watcher: uploadInterface, entityRenderer: entityRenderer)!
let signalDisposable = signal.start(next: { next in
if let result = next as? TGMediaVideoConversionResult {
if let image = result.coverImage, let data = image.jpegData(compressionQuality: 0.7) {
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
}
updateState { state in
var state = state
state.avatar = .image(representation, false)
return state
}
var value = stat()
if stat(result.fileURL.path, &value) == 0 {
if let data = try? Data(contentsOf: result.fileURL) {
let resource: TelegramMediaResource
if let liveUploadData = result.liveUploadData as? LegacyLiveUploadInterfaceResult {
resource = LocalFileMediaResource(fileId: liveUploadData.id)
} else {
resource = LocalFileMediaResource(fileId: arc4random64())
}
context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
subscriber.putNext(resource)
}
}
subscriber.putCompletion()
}
}, error: { _ in
}, completed: nil)
let disposable = ActionDisposable {
signalDisposable?.dispose()
}
return ActionDisposable {
disposable.dispose()
}
}
uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: photoResource))
let promise = Promise<UploadedPeerPhotoData?>()
promise.set(signal
|> `catch` { _ -> Signal<TelegramMediaResource?, NoError> in
return .single(nil)
}
|> mapToSignal { resource -> Signal<UploadedPeerPhotoData?, NoError> in
if let resource = resource {
return uploadedPeerVideo(postbox: context.account.postbox, network: context.account.network, messageMediaPreuploadManager: context.account.messageMediaPreuploadManager, resource: resource) |> map(Optional.init)
} else {
return .single(nil)
}
})
uploadedVideoAvatar = (promise, videoStartTimestamp)
}
}
let mixin = TGMediaAvatarMenuMixin(context: legacyController.context, parentController: emptyController, hasSearchButton: true, hasDeleteButton: stateValue.with({ $0.avatar }) != nil, hasViewButton: false, personalPhoto: false, isVideo: false, saveEditedPhotos: false, saveCapturedMedia: false, signup: false)!
let _ = currentAvatarMixin.swap(mixin)
mixin.requestSearchController = { assetsController in
let controller = WebSearchController(context: context, peer: peer, configuration: searchBotsConfiguration, mode: .avatar(initialQuery: title, completion: { result in
assetsController?.dismiss()
completedImpl(result)
completedChannelPhotoImpl(result)
}))
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
mixin.didFinishWithImage = { image in
if let image = image {
completedImpl(image)
completedChannelPhotoImpl(image)
}
}
mixin.didFinishWithVideo = { image, url, adjustments in
if let image = image, let url = url {
completedChannelVideoImpl(image, url, adjustments)
}
}
if stateValue.with({ $0.avatar }) != nil {

View File

@ -384,7 +384,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
let currentAvatarMixin = Atomic<TGMediaAvatarMenuMixin?>(value: nil)
let uploadedAvatar = Promise<UploadedPeerPhotoData>()
var uploadedVideoAvatar: Promise<UploadedPeerPhotoData?>? = nil
var uploadedVideoAvatar: (Promise<UploadedPeerPhotoData?>, Double?)? = nil
let addressPromise = Promise<String?>(nil)
let venuesPromise = Promise<[TelegramMediaMap]?>(nil)
@ -482,7 +482,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
return $0.avatar
}
if let _ = updatingAvatar {
return updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.get(), mapResourceToAvatarSizes: { resource, representations in
return updatePeerPhoto(postbox: context.account.postbox, network: context.account.network, stateManager: context.account.stateManager, accountPeerId: context.account.peerId, peerId: peerId, photo: uploadedAvatar.get(), video: uploadedVideoAvatar?.0.get(), videoStartTimestamp: uploadedVideoAvatar?.1, mapResourceToAvatarSizes: { resource, representations in
return mapResourceToAvatarSizes(postbox: context.account.postbox, resource: resource, representations: representations)
})
|> ignoreValues
@ -602,7 +602,7 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
videoStartTimestamp = adjustments.videoStartValue - adjustments.trimStartValue
}
let signal = Signal<TelegramMediaResource, UploadPeerPhotoError> { subscriber in
let signal = Signal<TelegramMediaResource?, UploadPeerPhotoError> { subscriber in
var filteredPath = url.path
if filteredPath.hasPrefix("file://") {
filteredPath = String(filteredPath[filteredPath.index(filteredPath.startIndex, offsetBy: "file://".count)])
@ -625,6 +625,12 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
context.account.postbox.mediaBox.storeResourceData(photoResource.id, data: data)
}
updateState { state in
var state = state
state.avatar = .image(representation, false)
return state
}
var value = stat()
if stat(result.fileURL.path, &value) == 0 {
if let data = try? Data(contentsOf: result.fileURL) {
@ -652,14 +658,21 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
}
}
// let promise = Promise<UploadedPeerPhotoData?>()
// promise.set(signal |> mapToSignal { resource in
// return uploadedPeerVideo(postbox: context.account.postbox, network: context.account.network, messageMediaPreuploadManager: context.account.messageMediaPreuploadManager, resource: resource) |> map(Optional.init)
// |> `catch` { _ -> Signal<UploadedPeerPhotoData?, NoError> in
// return .single(nil)
// }
// })
// uploadedVideoAvatar = promise
uploadedAvatar.set(uploadedPeerPhoto(postbox: context.account.postbox, network: context.account.network, resource: photoResource))
let promise = Promise<UploadedPeerPhotoData?>()
promise.set(signal
|> `catch` { _ -> Signal<TelegramMediaResource?, NoError> in
return .single(nil)
}
|> mapToSignal { resource -> Signal<UploadedPeerPhotoData?, NoError> in
if let resource = resource {
return uploadedPeerVideo(postbox: context.account.postbox, network: context.account.network, messageMediaPreuploadManager: context.account.messageMediaPreuploadManager, resource: resource) |> map(Optional.init)
} else {
return .single(nil)
}
})
uploadedVideoAvatar = (promise, videoStartTimestamp)
}
}
@ -677,8 +690,10 @@ public func createGroupControllerImpl(context: AccountContext, peerIds: [PeerId]
completedGroupPhotoImpl(image)
}
}
mixin.didFinishWithVideo = { _, _, _ in
mixin.didFinishWithVideo = { image, url, adjustments in
if let image = image, let url = url {
completedGroupVideoImpl(image, url, adjustments)
}
}
if stateValue.with({ $0.avatar }) != nil {
mixin.didFinishWithDelete = {

View File

@ -175,9 +175,11 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
let itemHeight: ItemListPeerItemHeight
let itemText: ItemListPeerItemText
var synchronousLoads = false
if case .account = item.member {
itemHeight = .generic
itemText = .none
synchronousLoads = true
} else {
itemHeight = .peerList
itemText = .presence
@ -207,7 +209,7 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
})
} else {
var itemNodeValue: ListViewItemNode?
peerItem.nodeConfiguredForParams(async: { $0() }, params: params, synchronousLoads: false, previousItem: nil, nextItem: nil, completion: { node, apply in
peerItem.nodeConfiguredForParams(async: { $0() }, params: params, synchronousLoads: synchronousLoads, previousItem: nil, nextItem: nil, completion: { node, apply in
itemNodeValue = node
apply().1(ListViewItemApply(isOnScreen: true))
})