Various improvements

This commit is contained in:
Ilya Laktyushin
2023-11-22 03:24:33 +04:00
parent 31eb1081df
commit 90f09a13e4
134 changed files with 8488 additions and 3171 deletions

View File

@@ -53,7 +53,7 @@ private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceh
self.presentationData = presentationData
self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: self.presentationData.chatWallpaper, theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.presentationInterfaceState.limitsConfiguration, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.presentationInterfaceState.accountPeerId, mode: .standard(previewing: false), chatLocation: self.presentationInterfaceState.chatLocation, subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil, replyMessage: nil, accountPeerColor: nil)
self.wallpaperBackgroundNode.update(wallpaper: presentationData.chatWallpaper)
self.wallpaperBackgroundNode.update(wallpaper: presentationData.chatWallpaper, animated: false)
}
func updateLayout(size: CGSize, needsTiling: Bool, transition: ContainedViewLayoutTransition) {
@@ -158,7 +158,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
detailsPlaceholderNode = current
} else {
detailsPlaceholderNode = DetailsChatPlaceholderNode(context: self.context)
detailsPlaceholderNode.wallpaperBackgroundNode.update(wallpaper: self.presentationData.chatWallpaper)
detailsPlaceholderNode.wallpaperBackgroundNode.update(wallpaper: self.presentationData.chatWallpaper, animated: false)
self.detailsPlaceholderNode = detailsPlaceholderNode
}
self.updateDetailsPlaceholderNode(detailsPlaceholderNode)
@@ -275,9 +275,11 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
let context = self.context
var storyTarget: Stories.PendingTarget?
var isPeerArchived = false
var updatedTransitionOut: ((Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?)?
let externalState = MediaEditorTransitionOutExternalState(
storyTarget: nil,
isPeerArchived: false,
transitionOut: nil
)
var presentImpl: ((ViewController) -> Void)?
var returnToCameraImpl: (() -> Void)?
@@ -297,7 +299,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
}
},
transitionOut: { finished in
if let transitionOut = (updatedTransitionOut ?? transitionOut)(finished ? storyTarget : nil, isPeerArchived), let destinationView = transitionOut.destinationView {
if let transitionOut = (externalState.transitionOut ?? transitionOut)(finished ? externalState.storyTarget : nil, externalState.isPeerArchived), let destinationView = transitionOut.destinationView {
return CameraScreen.TransitionOut(
destinationView: destinationView,
destinationRect: transitionOut.destinationRect,
@@ -353,10 +355,9 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
context: context,
subject: subject,
customTarget: customTarget,
isEditing: false,
transitionIn: transitionIn,
transitionOut: { finished, isNew in
if finished, let transitionOut = (updatedTransitionOut ?? transitionOut)(storyTarget, false), let destinationView = transitionOut.destinationView {
if finished, let transitionOut = (externalState.transitionOut ?? transitionOut)(externalState.storyTarget, false), let destinationView = transitionOut.destinationView {
return MediaEditorScreen.TransitionOut(
destinationView: destinationView,
destinationRect: transitionOut.destinationRect,
@@ -371,20 +372,20 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
} else {
return nil
}
}, completion: { [weak self] randomId, mediaResult, mediaAreas, caption, options, stickers, commit in
guard let self, let mediaResult else {
}, completion: { [weak self] result, commit in
guard let self else {
dismissCameraImpl?()
commit({})
return
}
let target: Stories.PendingTarget
let targetPeerId: EnginePeer.Id
if let customTarget {
target = .peer(customTarget)
targetPeerId = customTarget
} else {
if let sendAsPeerId = options.sendAsPeerId {
if let sendAsPeerId = result.options.sendAsPeerId {
target = .peer(sendAsPeerId)
targetPeerId = sendAsPeerId
} else {
@@ -392,8 +393,8 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
targetPeerId = context.account.peerId
}
}
storyTarget = target
externalState.storyTarget = target
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: targetPeerId))
|> deliverOnMainQueue).startStandalone(next: { [weak self] peer in
guard let self, let peer else {
@@ -401,120 +402,16 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
}
if case let .user(user) = peer {
isPeerArchived = user.storiesHidden ?? false
externalState.isPeerArchived = user.storiesHidden ?? false
} else if case let .channel(channel) = peer {
isPeerArchived = channel.storiesHidden ?? false
externalState.isPeerArchived = channel.storiesHidden ?? false
}
let context = self.context
if let rootTabController = self.rootTabController {
if let index = rootTabController.controllers.firstIndex(where: { $0 is ChatListController}) {
rootTabController.selectedIndex = index
}
}
let completionImpl: () -> Void = { [weak self] in
guard let self else {
return
}
var chatListController: ChatListControllerImpl?
if isPeerArchived {
var viewControllers = self.viewControllers
let archiveController = ChatListControllerImpl(context: context, location: .chatList(groupId: .archive), controlsHistoryPreload: false, hideNetworkActivityStatus: false, previewing: false, enableDebugActions: false)
updatedTransitionOut = archiveController.storyCameraTransitionOut()
chatListController = archiveController
viewControllers.insert(archiveController, at: 1)
self.setViewControllers(viewControllers, animated: false)
} else {
chatListController = self.chatListController as? ChatListControllerImpl
}
if let chatListController {
let _ = (chatListController.hasPendingStories
|> filter { $0 }
|> take(1)
|> timeout(isPeerArchived ? 0.5 : 0.25, queue: .mainQueue(), alternate: .single(true))
|> deliverOnMainQueue).startStandalone(completed: { [weak chatListController] in
guard let chatListController else {
return
}
chatListController.scrollToStories(peerId: targetPeerId)
Queue.mainQueue().justDispatch {
commit({})
}
})
} else {
Queue.mainQueue().justDispatch {
commit({})
}
}
}
if let _ = self.chatListController as? ChatListControllerImpl {
switch mediaResult {
case let .image(image, dimensions):
let tempFile = TempBox.shared.tempFile(fileName: "file")
defer {
TempBox.shared.dispose(tempFile)
}
if let imageData = compressImageToJPEG(image, quality: 0.7, tempFilePath: tempFile.path) {
let entities = generateChatInputTextEntities(caption)
Logger.shared.log("MediaEditor", "Calling uploadStory for image, randomId \(randomId)")
let _ = (context.engine.messages.uploadStory(target: target, media: .image(dimensions: dimensions, data: imageData, stickers: stickers), mediaAreas: mediaAreas, text: caption.string, entities: entities, pin: options.pin, privacy: options.privacy, isForwardingDisabled: options.isForwardingDisabled, period: options.timeout, randomId: randomId)
|> deliverOnMainQueue).startStandalone(next: { stableId in
moveStorySource(engine: context.engine, peerId: context.account.peerId, from: randomId, to: Int64(stableId))
})
completionImpl()
}
case let .video(content, firstFrameImage, values, duration, dimensions):
let adjustments: VideoMediaResourceAdjustments
if let valuesData = try? JSONEncoder().encode(values) {
let data = MemoryBuffer(data: valuesData)
let digest = MemoryBuffer(data: data.md5Digest())
adjustments = VideoMediaResourceAdjustments(data: data, digest: digest, isStory: true)
let resource: TelegramMediaResource
switch content {
case let .imageFile(path):
resource = LocalFileVideoMediaResource(randomId: Int64.random(in: .min ... .max), path: path, adjustments: adjustments)
case let .videoFile(path):
resource = LocalFileVideoMediaResource(randomId: Int64.random(in: .min ... .max), path: path, adjustments: adjustments)
case let .asset(localIdentifier):
resource = VideoLibraryMediaResource(localIdentifier: localIdentifier, conversion: .compress(adjustments))
}
let tempFile = TempBox.shared.tempFile(fileName: "file")
defer {
TempBox.shared.dispose(tempFile)
}
let imageData = firstFrameImage.flatMap { compressImageToJPEG($0, quality: 0.6, tempFilePath: tempFile.path) }
let firstFrameFile = imageData.flatMap { data -> TempBoxFile? in
let file = TempBox.shared.tempFile(fileName: "image.jpg")
if let _ = try? data.write(to: URL(fileURLWithPath: file.path)) {
return file
} else {
return nil
}
}
Logger.shared.log("MediaEditor", "Calling uploadStory for video, randomId \(randomId)")
let entities = generateChatInputTextEntities(caption)
let _ = (context.engine.messages.uploadStory(target: target, media: .video(dimensions: dimensions, duration: duration, resource: resource, firstFrameFile: firstFrameFile, stickers: stickers), mediaAreas: mediaAreas, text: caption.string, entities: entities, pin: options.pin, privacy: options.privacy, isForwardingDisabled: options.isForwardingDisabled, period: options.timeout, randomId: randomId)
|> deliverOnMainQueue).startStandalone(next: { stableId in
moveStorySource(engine: context.engine, peerId: context.account.peerId, from: randomId, to: Int64(stableId))
})
completionImpl()
}
}
}
self.proceedWithStoryUpload(target: target, result: result, existingMedia: nil, forwardInfo: nil, externalState: externalState, commit: commit)
dismissCameraImpl?()
})
} as (Int64, MediaEditorScreen.Result?, [MediaArea], NSAttributedString, MediaEditorResultPrivacy, [TelegramMediaFile], @escaping (@escaping () -> Void) -> Void) -> Void
} as (MediaEditorScreen.Result, @escaping (@escaping () -> Void) -> Void) -> Void
)
controller.cancelled = { showDraftTooltip in
if showDraftTooltip {
@@ -569,6 +466,138 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
})
}
public func proceedWithStoryUpload(target: Stories.PendingTarget, result: MediaEditorScreenResult, existingMedia: EngineMedia?, forwardInfo: Stories.PendingForwardInfo?, externalState: MediaEditorTransitionOutExternalState, commit: @escaping (@escaping () -> Void) -> Void) {
guard let result = result as? MediaEditorScreen.Result else {
return
}
let context = self.context
let targetPeerId: EnginePeer.Id
switch target {
case let .peer(peerId):
targetPeerId = peerId
case .myStories:
targetPeerId = context.account.peerId
}
if let rootTabController = self.rootTabController {
if let index = rootTabController.controllers.firstIndex(where: { $0 is ChatListController}) {
rootTabController.selectedIndex = index
}
}
let completionImpl: () -> Void = { [weak self] in
guard let self else {
return
}
var chatListController: ChatListControllerImpl?
if externalState.isPeerArchived {
var viewControllers = self.viewControllers
let archiveController = ChatListControllerImpl(context: context, location: .chatList(groupId: .archive), controlsHistoryPreload: false, hideNetworkActivityStatus: false, previewing: false, enableDebugActions: false)
externalState.transitionOut = archiveController.storyCameraTransitionOut()
chatListController = archiveController
viewControllers.insert(archiveController, at: 1)
self.setViewControllers(viewControllers, animated: false)
} else {
chatListController = self.chatListController as? ChatListControllerImpl
externalState.transitionOut = chatListController?.storyCameraTransitionOut()
}
if let chatListController {
let _ = (chatListController.hasPendingStories
|> filter { $0 }
|> take(1)
|> timeout(externalState.isPeerArchived ? 0.5 : 0.25, queue: .mainQueue(), alternate: .single(true))
|> deliverOnMainQueue).startStandalone(completed: { [weak chatListController] in
guard let chatListController else {
return
}
chatListController.scrollToStories(peerId: targetPeerId)
Queue.mainQueue().justDispatch {
commit({})
}
})
} else {
Queue.mainQueue().justDispatch {
commit({})
}
}
}
if let _ = self.chatListController as? ChatListControllerImpl {
var media: EngineStoryInputMedia?
if let mediaResult = result.media {
switch mediaResult {
case let .image(image, dimensions):
let tempFile = TempBox.shared.tempFile(fileName: "file")
defer {
TempBox.shared.dispose(tempFile)
}
if let imageData = compressImageToJPEG(image, quality: 0.7, tempFilePath: tempFile.path) {
media = .image(dimensions: dimensions, data: imageData, stickers: result.stickers)
}
case let .video(content, firstFrameImage, values, duration, dimensions):
let adjustments: VideoMediaResourceAdjustments
if let valuesData = try? JSONEncoder().encode(values) {
let data = MemoryBuffer(data: valuesData)
let digest = MemoryBuffer(data: data.md5Digest())
adjustments = VideoMediaResourceAdjustments(data: data, digest: digest, isStory: true)
let resource: TelegramMediaResource
switch content {
case let .imageFile(path):
resource = LocalFileVideoMediaResource(randomId: Int64.random(in: .min ... .max), path: path, adjustments: adjustments)
case let .videoFile(path):
resource = LocalFileVideoMediaResource(randomId: Int64.random(in: .min ... .max), path: path, adjustments: adjustments)
case let .asset(localIdentifier):
resource = VideoLibraryMediaResource(localIdentifier: localIdentifier, conversion: .compress(adjustments))
}
let tempFile = TempBox.shared.tempFile(fileName: "file")
defer {
TempBox.shared.dispose(tempFile)
}
let imageData = firstFrameImage.flatMap { compressImageToJPEG($0, quality: 0.6, tempFilePath: tempFile.path) }
let firstFrameFile = imageData.flatMap { data -> TempBoxFile? in
let file = TempBox.shared.tempFile(fileName: "image.jpg")
if let _ = try? data.write(to: URL(fileURLWithPath: file.path)) {
return file
} else {
return nil
}
}
media = .video(dimensions: dimensions, duration: duration, resource: resource, firstFrameFile: firstFrameFile, stickers: result.stickers)
}
}
} else if let existingMedia {
media = .existing(media: existingMedia._asMedia())
}
if let media {
let _ = (context.engine.messages.uploadStory(
target: target,
media: media,
mediaAreas: result.mediaAreas,
text: result.caption.string,
entities: generateChatInputTextEntities(result.caption),
pin: result.options.pin,
privacy: result.options.privacy,
isForwardingDisabled: result.options.isForwardingDisabled,
period: result.options.timeout,
randomId: result.randomId,
forwardInfo: forwardInfo
)
|> deliverOnMainQueue).startStandalone(next: { stableId in
moveStorySource(engine: context.engine, peerId: context.account.peerId, from: result.randomId, to: Int64(stableId))
})
}
completionImpl()
}
}
public func openSettings() {
guard let rootTabController = self.rootTabController else {
return
@@ -581,3 +610,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
}
}
}
extension MediaEditorScreen.Result: MediaEditorScreenResult {
}