Files
Swiftgram/submodules/TelegramUI/Sources/Chat/ChatControllerOpenDocumentScanner.swift
2026-02-19 21:53:26 +04:00

114 lines
5.4 KiB
Swift

import Foundation
import UIKit
import SwiftSignalKit
import Postbox
import TelegramCore
import AsyncDisplayKit
import Display
import AccountContext
import ChatControllerInteraction
import VisionKit
import PDFKit
import Pdf
extension ChatControllerImpl: VNDocumentCameraViewControllerDelegate {
func presentDocumentScanner() {
let documentScanner = VNDocumentCameraViewController()
documentScanner.delegate = self
if let rootViewController = self.context.sharedContext.mainWindow?.viewController?.view.window?.rootViewController {
rootViewController.present(documentScanner, animated: true)
}
}
func enqueueScan(scan: VNDocumentCameraScan, convertToPdf: Bool) {
struct Item {
let resource: TelegramMediaResource
let previewResource: TelegramMediaResource?
let fileName: String
let mimeType: String
let size: Int64
}
var items: [Item] = []
var title = scan.title.trimmingCharacters(in: .whitespacesAndNewlines)
if title.isEmpty {
title = "Scan"
}
if convertToPdf {
let pdfDocument = PDFDocument()
for i in 0 ..< scan.pageCount {
let image = scan.imageOfPage(at: i)
if let pdfPage = PDFPage(image: image) {
pdfDocument.insert(pdfPage, at: i)
}
}
if let data = pdfDocument.dataRepresentation() {
var randomId: Int64 = 0
arc4random_buf(&randomId, 8)
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
var previewResource: LocalFileMediaResource?
if let image = generatePdfPreviewImage(data: data, size: CGSize(width: 256, height: 256.0)), let jpegData = image.jpegData(compressionQuality: 0.5) {
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: jpegData, synchronous: true)
previewResource = resource
}
items.append(Item(resource: resource, previewResource: previewResource, fileName: "\(title).pdf", mimeType: "application/pdf", size: Int64(data.count)))
}
} else {
for i in 0 ..< scan.pageCount {
let image = scan.imageOfPage(at: i)
if let data = image.jpegData(compressionQuality: 0.87) {
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
self.context.account.postbox.mediaBox.storeResourceData(resource.id, data: data, synchronous: true)
var fileTitle = title
if scan.pageCount > 1 {
fileTitle += "\(fileTitle)-\(i)"
}
items.append(Item(resource: resource, previewResource: nil, fileName: "\(fileTitle).jpg", mimeType: "image/jpeg", size: Int64(data.count)))
}
}
}
var messages: [EnqueueMessage] = []
var groupingKey: Int64?
if items.count > 1 {
groupingKey = Int64.random(in: Int64.min ... Int64.max)
}
for item in items {
let fileId = Int64.random(in: Int64.min ... Int64.max)
var previewRepresentations: [TelegramMediaImageRepresentation] = []
if let previewResource = item.previewResource {
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: 320, height: 320), resource: previewResource, progressiveSizes: [], immediateThumbnailData: nil, hasVideo: false, isPersonal: false))
}
var attributes: [TelegramMediaFileAttribute] = []
attributes.append(.FileName(fileName: item.fileName))
let file = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: item.resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: item.mimeType, size: item.size, attributes: attributes, alternativeRepresentations: [])
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), threadId: self.chatLocation.threadId, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
messages.append(message)
if let _ = groupingKey, messages.count % 10 == 0 {
groupingKey = Int64.random(in: Int64.min ... Int64.max)
}
}
let transformedMessages = self.transformEnqueueMessages(messages)
self.sendMessages(transformedMessages)
}
public func documentCameraViewController(_ controller: VNDocumentCameraViewController, didFinishWith scan: VNDocumentCameraScan) {
controller.dismiss(animated: true)
self.enqueueScan(scan: scan, convertToPdf: true)
}
}