mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Camera and editor improvements
This commit is contained in:
@@ -26,6 +26,7 @@ import AvatarNode
|
||||
import LocalMediaResources
|
||||
import ShareWithPeersScreen
|
||||
import ImageCompression
|
||||
import TextFormat
|
||||
|
||||
private class DetailsChatPlaceholderNode: ASDisplayNode, NavigationDetailsPlaceholderNode {
|
||||
private var presentationData: PresentationData
|
||||
@@ -196,16 +197,8 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var transitionIn: StoryCameraTransitionIn?
|
||||
if let cameraItemView = self.rootTabController?.viewForCameraItem() {
|
||||
transitionIn = StoryCameraTransitionIn(
|
||||
sourceView: cameraItemView,
|
||||
sourceRect: cameraItemView.bounds,
|
||||
sourceCornerRadius: cameraItemView.bounds.height / 2.0
|
||||
)
|
||||
}
|
||||
self.openStoryCamera(
|
||||
transitionIn: transitionIn,
|
||||
let coordinator = self.openStoryCamera(
|
||||
transitionIn: nil,
|
||||
transitionOut: { [weak self] finished in
|
||||
guard let self else {
|
||||
return nil
|
||||
@@ -218,18 +211,11 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
destinationCornerRadius: transitionView.bounds.height / 2.0
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if let cameraItemView = self.rootTabController?.viewForCameraItem() {
|
||||
return StoryCameraTransitionOut(
|
||||
destinationView: cameraItemView,
|
||||
destinationRect: cameraItemView.bounds,
|
||||
destinationCornerRadius: cameraItemView.bounds.height / 2.0
|
||||
)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
)
|
||||
coordinator?.animateIn()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -288,9 +274,10 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
presentedLegacyShortcutCamera(context: self.context, saveCapturedMedia: false, saveEditedPhotos: false, mediaGrouping: true, parentController: controller)
|
||||
}
|
||||
|
||||
public func openStoryCamera(transitionIn: StoryCameraTransitionIn?, transitionOut: @escaping (Bool) -> StoryCameraTransitionOut?) {
|
||||
@discardableResult
|
||||
public func openStoryCamera(transitionIn: StoryCameraTransitionIn?, transitionOut: @escaping (Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? {
|
||||
guard let controller = self.viewControllers.last as? ViewController else {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
controller.view.endEditing(true)
|
||||
|
||||
@@ -299,7 +286,6 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
var presentImpl: ((ViewController) -> Void)?
|
||||
var returnToCameraImpl: (() -> Void)?
|
||||
var dismissCameraImpl: (() -> Void)?
|
||||
var hideCameraImpl: (() -> Void)?
|
||||
var showDraftTooltipImpl: (() -> Void)?
|
||||
let cameraController = CameraScreen(
|
||||
context: context,
|
||||
@@ -326,7 +312,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
return nil
|
||||
}
|
||||
},
|
||||
completion: { result in
|
||||
completion: { result, resultTransition in
|
||||
let subject: Signal<MediaEditorScreen.Subject?, NoError> = result
|
||||
|> map { value -> MediaEditorScreen.Subject? in
|
||||
switch value {
|
||||
@@ -342,17 +328,37 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
return .draft(draft)
|
||||
}
|
||||
}
|
||||
|
||||
var transitionIn: MediaEditorScreen.TransitionIn?
|
||||
if let resultTransition, let sourceView = resultTransition.sourceView {
|
||||
transitionIn = .gallery(
|
||||
MediaEditorScreen.TransitionIn.GalleryTransitionIn(
|
||||
sourceView: sourceView,
|
||||
sourceRect: resultTransition.sourceRect,
|
||||
sourceImage: resultTransition.sourceImage
|
||||
)
|
||||
)
|
||||
} else {
|
||||
transitionIn = .camera
|
||||
}
|
||||
|
||||
let controller = MediaEditorScreen(
|
||||
context: context,
|
||||
subject: subject,
|
||||
transitionIn: nil,
|
||||
transitionIn: transitionIn,
|
||||
transitionOut: { finished in
|
||||
if finished, let transitionOut = transitionOut(true), let destinationView = transitionOut.destinationView {
|
||||
if finished, let transitionOut = transitionOut(finished), let destinationView = transitionOut.destinationView {
|
||||
return MediaEditorScreen.TransitionOut(
|
||||
destinationView: destinationView,
|
||||
destinationRect: transitionOut.destinationRect,
|
||||
destinationCornerRadius: transitionOut.destinationCornerRadius
|
||||
)
|
||||
} else if !finished, let resultTransition, let (destinationView, destinationRect) = resultTransition.transitionOut() {
|
||||
return MediaEditorScreen.TransitionOut(
|
||||
destinationView: destinationView,
|
||||
destinationRect: destinationRect,
|
||||
destinationCornerRadius: 0.0
|
||||
)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@@ -367,10 +373,71 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
switch mediaResult {
|
||||
case let .image(image, dimensions, caption):
|
||||
if let imageData = compressImageToJPEG(image, quality: 0.6) {
|
||||
storyListContext.upload(media: .image(dimensions: dimensions, data: imageData), text: caption?.string ?? "", entities: [], privacy: privacy)
|
||||
Queue.mainQueue().after(0.2, { [weak chatListController] in
|
||||
chatListController?.animateStoryUploadRipple()
|
||||
})
|
||||
switch privacy {
|
||||
case let .story(storyPrivacy, _):
|
||||
storyListContext.upload(media: .image(dimensions: dimensions, data: imageData), text: caption?.string ?? "", entities: [], privacy: storyPrivacy)
|
||||
Queue.mainQueue().after(0.2, { [weak chatListController] in
|
||||
chatListController?.animateStoryUploadRipple()
|
||||
})
|
||||
case let .message(peerIds, timeout):
|
||||
var randomId: Int64 = 0
|
||||
arc4random_buf(&randomId, 8)
|
||||
let tempFilePath = NSTemporaryDirectory() + "\(randomId).jpg"
|
||||
let _ = try? imageData.write(to: URL(fileURLWithPath: tempFilePath))
|
||||
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
let resource = LocalFileReferenceMediaResource(localFilePath: tempFilePath, randomId: randomId)
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(image.size), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
|
||||
|
||||
var attributes: [MessageAttribute] = []
|
||||
let imageFlags: TelegramMediaImageFlags = []
|
||||
// var stickerFiles: [TelegramMediaFile] = []
|
||||
// if !stickers.isEmpty {
|
||||
// for fileReference in stickers {
|
||||
// stickerFiles.append(fileReference.media)
|
||||
// }
|
||||
// }
|
||||
// if !stickerFiles.isEmpty {
|
||||
// attributes.append(EmbeddedMediaStickersMessageAttribute(files: stickerFiles))
|
||||
// imageFlags.insert(.hasStickers)
|
||||
// }
|
||||
|
||||
let media = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: randomId), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: imageFlags)
|
||||
if let timeout, timeout > 0 && timeout <= 60 {
|
||||
attributes.append(AutoremoveTimeoutMessageAttribute(timeout: timeout, countdownBeginTime: nil))
|
||||
}
|
||||
|
||||
let text = trimChatInputText(convertMarkdownToAttributes(caption ?? NSAttributedString()))
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
var bubbleUpEmojiOrStickersetsById: [Int64: ItemCollectionId] = [:]
|
||||
text.enumerateAttribute(ChatTextInputAttributes.customEmoji, in: NSRange(location: 0, length: text.length), using: { value, _, _ in
|
||||
if let value = value as? ChatTextInputTextCustomEmojiAttribute {
|
||||
if let file = value.file {
|
||||
if let packId = value.interactivelySelectedFromPackId {
|
||||
bubbleUpEmojiOrStickersetsById[file.fileId.id] = packId
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
var bubbleUpEmojiOrStickersets: [ItemCollectionId] = []
|
||||
for entity in entities {
|
||||
if case let .CustomEmoji(_, fileId) = entity.type {
|
||||
if let packId = bubbleUpEmojiOrStickersetsById[fileId] {
|
||||
if !bubbleUpEmojiOrStickersets.contains(packId) {
|
||||
bubbleUpEmojiOrStickersets.append(packId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _ = enqueueMessagesToMultiplePeers(
|
||||
account: self.context.account,
|
||||
peerIds: peerIds, threadIds: [:],
|
||||
messages: [.message(text: text.string, attributes: attributes, inlineStickers: [:], mediaReference: .standalone(media: media), replyToMessageId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets)]).start()
|
||||
}
|
||||
}
|
||||
case let .video(content, _, values, duration, dimensions, caption):
|
||||
let adjustments: VideoMediaResourceAdjustments
|
||||
@@ -388,10 +455,14 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
case let .asset(localIdentifier):
|
||||
resource = VideoLibraryMediaResource(localIdentifier: localIdentifier, conversion: .compress(adjustments))
|
||||
}
|
||||
storyListContext.upload(media: .video(dimensions: dimensions, duration: Int(duration), resource: resource), text: caption?.string ?? "", entities: [], privacy: privacy)
|
||||
Queue.mainQueue().after(0.2, { [weak chatListController] in
|
||||
chatListController?.animateStoryUploadRipple()
|
||||
})
|
||||
if case let .story(storyPrivacy, _) = privacy {
|
||||
storyListContext.upload(media: .video(dimensions: dimensions, duration: Int(duration), resource: resource), text: caption?.string ?? "", entities: [], privacy: storyPrivacy)
|
||||
Queue.mainQueue().after(0.2, { [weak chatListController] in
|
||||
chatListController?.animateStoryUploadRipple()
|
||||
})
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,16 +471,12 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
commit()
|
||||
}
|
||||
)
|
||||
controller.sourceHint = .camera
|
||||
controller.cancelled = { showDraftTooltip in
|
||||
if showDraftTooltip {
|
||||
showDraftTooltipImpl?()
|
||||
}
|
||||
returnToCameraImpl?()
|
||||
}
|
||||
controller.onReady = {
|
||||
hideCameraImpl?()
|
||||
}
|
||||
presentImpl?(controller)
|
||||
}
|
||||
)
|
||||
@@ -429,16 +496,28 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
||||
cameraController.returnFromEditor()
|
||||
}
|
||||
}
|
||||
hideCameraImpl = { [weak cameraController] in
|
||||
if let cameraController {
|
||||
cameraController.commitTransitionToEditor()
|
||||
}
|
||||
}
|
||||
showDraftTooltipImpl = { [weak cameraController] in
|
||||
if let cameraController {
|
||||
cameraController.presentDraftTooltip()
|
||||
}
|
||||
}
|
||||
return StoryCameraTransitionInCoordinator(
|
||||
animateIn: { [weak cameraController] in
|
||||
if let cameraController {
|
||||
cameraController.updateTransitionProgress(0.0, transition: .immediate)
|
||||
cameraController.completeWithTransitionProgress(1.0, velocity: 0.0, dismissing: false)
|
||||
}
|
||||
},
|
||||
updateTransitionProgress: { [weak cameraController] transitionFraction in
|
||||
if let cameraController {
|
||||
cameraController.updateTransitionProgress(transitionFraction, transition: .immediate)
|
||||
}
|
||||
},
|
||||
completeWithTransitionProgressAndVelocity: { [weak cameraController] transitionFraction, velocity in
|
||||
if let cameraController {
|
||||
cameraController.completeWithTransitionProgress(transitionFraction, velocity: velocity, dismissing: false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func openSettings() {
|
||||
|
||||
Reference in New Issue
Block a user