2022-10-11 04:44:13 +03:00
|
|
|
using NAPS2.EtoForms;
|
2023-04-04 06:56:26 +03:00
|
|
|
using NAPS2.EtoForms.Notifications;
|
2022-08-21 03:50:38 +03:00
|
|
|
using NAPS2.ImportExport.Images;
|
2023-02-19 00:04:18 +03:00
|
|
|
using NAPS2.Pdf;
|
2022-08-21 03:50:38 +03:00
|
|
|
using NAPS2.Scan;
|
|
|
|
|
|
|
|
namespace NAPS2.ImportExport;
|
|
|
|
|
|
|
|
public class AutoSaver
|
|
|
|
{
|
|
|
|
private readonly ErrorOutput _errorOutput;
|
|
|
|
private readonly DialogHelper _dialogHelper;
|
|
|
|
private readonly OperationProgress _operationProgress;
|
|
|
|
private readonly ISaveNotify _notify;
|
2023-12-30 21:35:09 +03:00
|
|
|
private readonly PdfExporter _pdfExporter;
|
2022-08-21 03:50:38 +03:00
|
|
|
private readonly IOverwritePrompt _overwritePrompt;
|
|
|
|
private readonly Naps2Config _config;
|
|
|
|
private readonly ImageContext _imageContext;
|
|
|
|
|
|
|
|
public AutoSaver(ErrorOutput errorOutput, DialogHelper dialogHelper,
|
2023-12-30 21:35:09 +03:00
|
|
|
OperationProgress operationProgress, ISaveNotify notify, PdfExporter pdfExporter,
|
2022-09-16 05:02:09 +03:00
|
|
|
IOverwritePrompt overwritePrompt, Naps2Config config, ImageContext imageContext)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
|
|
|
_errorOutput = errorOutput;
|
|
|
|
_dialogHelper = dialogHelper;
|
|
|
|
_operationProgress = operationProgress;
|
|
|
|
_notify = notify;
|
|
|
|
_pdfExporter = pdfExporter;
|
|
|
|
_overwritePrompt = overwritePrompt;
|
|
|
|
_config = config;
|
|
|
|
_imageContext = imageContext;
|
|
|
|
}
|
|
|
|
|
2022-09-28 04:12:36 +03:00
|
|
|
public IAsyncEnumerable<ProcessedImage> Save(AutoSaveSettings settings, IAsyncEnumerable<ProcessedImage> images)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-09-28 04:12:36 +03:00
|
|
|
return AsyncProducers.RunProducer<ProcessedImage>(async produceImage =>
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
|
|
|
var imageList = new List<ProcessedImage>();
|
2022-09-28 04:12:36 +03:00
|
|
|
try
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-09-28 04:12:36 +03:00
|
|
|
await foreach (var img in images)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-09-28 04:12:36 +03:00
|
|
|
imageList.Add(img);
|
|
|
|
if (!settings.ClearImagesAfterSaving)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-12-30 08:50:04 +03:00
|
|
|
produceImage(img.Clone());
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-09-28 04:12:36 +03:00
|
|
|
finally
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-09-28 04:12:36 +03:00
|
|
|
if (!await InternalSave(settings, imageList) && settings.ClearImagesAfterSaving)
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2022-09-28 04:12:36 +03:00
|
|
|
// Fallback in case auto save failed; pipe all the images back at once
|
|
|
|
foreach (var img in imageList)
|
|
|
|
{
|
|
|
|
produceImage(img);
|
|
|
|
}
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
2022-12-30 08:50:04 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
foreach (var img in imageList)
|
|
|
|
{
|
|
|
|
img.Dispose();
|
|
|
|
}
|
|
|
|
}
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private async Task<bool> InternalSave(AutoSaveSettings settings, List<ProcessedImage> images)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
bool ok = true;
|
|
|
|
var placeholders = Placeholders.All.WithDate(DateTime.Now);
|
|
|
|
int i = 0;
|
|
|
|
string? firstFileSaved = null;
|
|
|
|
var scans = SaveSeparatorHelper.SeparateScans(new[] { images }, settings.Separator).ToList();
|
|
|
|
foreach (var imageList in scans)
|
|
|
|
{
|
|
|
|
(bool success, string? filePath) =
|
|
|
|
await SaveOneFile(settings, placeholders, i++, imageList, scans.Count == 1);
|
|
|
|
if (!success)
|
|
|
|
{
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
if (success && firstFileSaved == null)
|
|
|
|
{
|
|
|
|
firstFileSaved = filePath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: Shouldn't this give duplicate notifications?
|
|
|
|
if (scans.Count > 1 && ok)
|
|
|
|
{
|
|
|
|
// Can't just do images.Count because that includes patch codes
|
|
|
|
int imageCount = scans.SelectMany(x => x).Count();
|
|
|
|
_notify.ImagesSaved(imageCount, firstFileSaved!);
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Log.ErrorException(MiscResources.AutoSaveError, ex);
|
|
|
|
_errorOutput.DisplayError(MiscResources.AutoSaveError, ex);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private async Task<(bool, string?)> SaveOneFile(AutoSaveSettings settings, Placeholders placeholders, int i,
|
|
|
|
List<ProcessedImage> images, bool doNotify)
|
|
|
|
{
|
|
|
|
if (images.Count == 0)
|
|
|
|
{
|
|
|
|
return (true, null);
|
|
|
|
}
|
|
|
|
string subPath = placeholders.Substitute(settings.FilePath, true, i);
|
|
|
|
if (settings.PromptForFilePath)
|
|
|
|
{
|
2023-10-09 04:20:09 +03:00
|
|
|
Invoker.Current.Invoke(() =>
|
2022-08-21 03:50:38 +03:00
|
|
|
{
|
2023-10-09 04:20:09 +03:00
|
|
|
if (_dialogHelper.PromptToSavePdfOrImage(subPath, out string? newPath))
|
|
|
|
{
|
|
|
|
subPath = placeholders.Substitute(newPath!, true, i);
|
|
|
|
}
|
|
|
|
});
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
2022-09-28 04:12:36 +03:00
|
|
|
// TODO: This placeholder handling is complex and wrong in some cases (e.g. FilePerScan with ext = "jpg")
|
|
|
|
// TODO: Maybe have initial placeholders that replace date, then rely on the ops to increment the file num
|
2022-08-21 03:50:38 +03:00
|
|
|
var extension = Path.GetExtension(subPath);
|
|
|
|
if (extension != null && extension.Equals(".pdf", StringComparison.InvariantCultureIgnoreCase))
|
|
|
|
{
|
|
|
|
if (File.Exists(subPath))
|
|
|
|
{
|
|
|
|
subPath = placeholders.Substitute(subPath, true, 0, 1);
|
|
|
|
}
|
|
|
|
var op = new SavePdfOperation(_pdfExporter, _overwritePrompt);
|
|
|
|
if (op.Start(subPath, placeholders, images, _config.Get(c => c.PdfSettings), _config.DefaultOcrParams()))
|
|
|
|
{
|
|
|
|
_operationProgress.ShowProgress(op);
|
|
|
|
}
|
|
|
|
bool success = await op.Success;
|
|
|
|
if (success && doNotify)
|
|
|
|
{
|
2024-01-14 02:45:01 +03:00
|
|
|
_notify.PdfSaved(subPath);
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
|
|
|
return (success, subPath);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-09-16 05:02:09 +03:00
|
|
|
var op = new SaveImagesOperation(_overwritePrompt, _imageContext);
|
2022-08-21 03:50:38 +03:00
|
|
|
if (op.Start(subPath, placeholders, images, _config.Get(c => c.ImageSettings)))
|
|
|
|
{
|
|
|
|
_operationProgress.ShowProgress(op);
|
|
|
|
}
|
|
|
|
bool success = await op.Success;
|
|
|
|
if (success && doNotify && op.FirstFileSaved != null)
|
|
|
|
{
|
2024-01-14 02:45:01 +03:00
|
|
|
_notify.ImagesSaved(images.Count, op.FirstFileSaved);
|
2022-08-21 03:50:38 +03:00
|
|
|
}
|
|
|
|
return (success, subPath);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|