Give mixed selections something to do

A Drag of different kinds showed an empty wheel, because the catalog only
answers for a single category. Filee's answer is a mixed profile, so add
Zip (one archive, flat names) and Merge (non-PDFs are converted to PDF
first); a multi-file drag of one kind gets Zip too.
This commit is contained in:
2026-10-20 01:30:42 +08:00
parent 2d031e58a4
commit a01d5def89
8 changed files with 295 additions and 41 deletions
+46 -1
View File
@@ -207,7 +207,37 @@ enum ToolRunner {
for: first.deletingLastPathComponent()
.appendingPathComponent(first.deletingPathExtension().lastPathComponent + " merged.pdf")
)
try PDFConverter.merge(inputs, at: destination, cancellation: cancellation)
// A mixed selection is merged by turning each non-PDF into a PDF
// first, so "3 photos + 2 PDFs" is one drop instead of two jobs.
var staged: [URL] = []
let staging = FileManager.default.temporaryDirectory
.appendingPathComponent("konverter-merge-\(UUID().uuidString)", isDirectory: true)
defer { if !staged.isEmpty { try? FileManager.default.removeItem(at: staging) } }
var sources: [URL] = []
for (index, input) in inputs.enumerated() {
try cancellation?.check()
if FileKind.category(of: input) == .pdf {
sources.append(input)
continue
}
if staged.isEmpty {
try FileManager.default.createDirectory(at: staging, withIntermediateDirectories: true)
}
let name = String(format: "%03d", index) + "-"
+ input.deletingPathExtension().lastPathComponent + ".pdf"
let temp = staging.appendingPathComponent(name)
try Converter.convert(
source: input,
to: .pdf,
at: temp,
cancellation: cancellation,
progress: { fraction in progress?(fraction * 0.5) }
)
staged.append(temp)
sources.append(temp)
}
try PDFConverter.merge(sources, at: destination, cancellation: cancellation)
progress?(1)
return ToolOutcome(outputs: [destination])
@@ -377,6 +407,21 @@ enum ToolRunner {
results.append(MediaInfo.describe(source))
}
return ToolOutcome(message: results.joined(separator: "\n\n"), messageTitle: "Info")
case .createArchive:
let folder = inputs[0].deletingLastPathComponent()
let name = params.string("name", default: "Archive")
let base = name.hasSuffix(".zip") ? String(name.dropLast(4)) : name
let destination = OutputNaming.availableURL(
for: folder.appendingPathComponent(base).appendingPathExtension("zip")
)
try ArchiveConverter.createArchive(
from: inputs,
at: destination,
cancellation: cancellation,
progress: progress
)
return ToolOutcome(outputs: [destination])
}
}