Persist upload queue and uploaded cache
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-13 11:12:26 +01:00
parent ce0b7c951a
commit 0c33c1ddc1
2 changed files with 113 additions and 0 deletions

View File

@@ -40,6 +40,7 @@ public partial class MainWindow : Window
{
InitializeComponent();
_settings = _settingsStore.Load();
EnsureSettingsCollections();
_settings.BaseUrl = NormalizeBaseUrl(_settings.BaseUrl) ?? DefaultBaseUrl;
if (_settings.MaxConcurrentUploads <= 0)
{
@@ -226,6 +227,7 @@ public partial class MainWindow : Window
ResetCounters();
_uploadService.Start(_settings, OnQueued, OnUploading, OnSuccess, OnFailure);
StartWatcher(_settings.WatchFolder);
RestorePendingUploads();
UpdateSteps();
}
@@ -251,6 +253,11 @@ public partial class MainWindow : Window
return;
}
if (ShouldSkipUpload(e.FullPath))
{
return;
}
_uploadService.Enqueue(e.FullPath, OnQueued);
}
@@ -261,6 +268,11 @@ public partial class MainWindow : Window
return;
}
if (ShouldSkipUpload(e.FullPath))
{
return;
}
_uploadService.Enqueue(e.FullPath, OnQueued);
}
@@ -280,6 +292,7 @@ public partial class MainWindow : Window
{
Interlocked.Increment(ref _queuedCount);
UpdateUpload(path, UploadStatus.Queued);
AddPendingUpload(path);
UpdateStatusIfAllowed($"Wartet: {Path.GetFileName(path)}", false);
UpdateCountersText();
}
@@ -299,6 +312,8 @@ public partial class MainWindow : Window
Interlocked.Decrement(ref _uploadingCount);
_lastSuccessAt = DateTimeOffset.Now;
UpdateUpload(path, UploadStatus.Success);
RemovePendingUpload(path);
MarkUploaded(path);
UpdateStatusIfAllowed($"Hochgeladen: {Path.GetFileName(path)}", false);
UpdateCountersText();
UpdateLiveStatus();
@@ -310,6 +325,7 @@ public partial class MainWindow : Window
Interlocked.Decrement(ref _uploadingCount);
Interlocked.Increment(ref _failedCount);
UpdateUpload(path, UploadStatus.Failed);
RemovePendingUpload(path);
UpdateStatusIfAllowed($"Upload fehlgeschlagen: {Path.GetFileName(path)}", true);
SetLastError($"{Path.GetFileName(path)} {message}");
UpdateRetryButton();
@@ -398,6 +414,92 @@ public partial class MainWindow : Window
ReconnectButton.IsEnabled = enabled;
}
private void RestorePendingUploads()
{
EnsureSettingsCollections();
if (_settings.PendingUploads.Count == 0)
{
return;
}
var pending = _settings.PendingUploads.ToList();
var changed = false;
foreach (var path in pending)
{
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path) || ShouldSkipUpload(path))
{
_settings.PendingUploads.Remove(path);
changed = true;
continue;
}
_uploadService.Enqueue(path, OnQueued);
}
if (changed)
{
_settingsStore.Save(_settings);
}
}
private bool ShouldSkipUpload(string path)
{
var signature = GetUploadSignature(path);
if (signature is null)
{
return true;
}
return _settings.UploadedFiles.TryGetValue(path, out var recorded) && recorded == signature;
}
private string? GetUploadSignature(string path)
{
if (!File.Exists(path))
{
return null;
}
var info = new FileInfo(path);
return $"{info.Length}:{info.LastWriteTimeUtc.Ticks}";
}
private void AddPendingUpload(string path)
{
EnsureSettingsCollections();
if (!_settings.PendingUploads.Contains(path))
{
_settings.PendingUploads.Add(path);
_settingsStore.Save(_settings);
}
}
private void RemovePendingUpload(string path)
{
EnsureSettingsCollections();
if (_settings.PendingUploads.Remove(path))
{
_settingsStore.Save(_settings);
}
}
private void MarkUploaded(string path)
{
var signature = GetUploadSignature(path);
if (signature is null)
{
return;
}
EnsureSettingsCollections();
_settings.UploadedFiles[path] = signature;
_settingsStore.Save(_settings);
}
private void TitleText_PointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e)
{
if (e.ClickCount < 2)
@@ -706,4 +808,10 @@ public partial class MainWindow : Window
{
return code.Length == 6 && code.All(ch => ch is >= '0' and <= '9');
}
private void EnsureSettingsCollections()
{
_settings.PendingUploads ??= new List<string>();
_settings.UploadedFiles ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}

View File

@@ -1,3 +1,6 @@
using System;
using System.Collections.Generic;
namespace PhotoboothUploader.Models;
public sealed class PhotoboothSettings
@@ -9,6 +12,8 @@ public sealed class PhotoboothSettings
public string? Password { get; set; }
public string? ResponseFormat { get; set; }
public string? WatchFolder { get; set; }
public List<string> PendingUploads { get; set; } = new();
public Dictionary<string, string> UploadedFiles { get; set; } = new(StringComparer.OrdinalIgnoreCase);
public string? LastError { get; set; }
public string? LastErrorAt { get; set; }
public int MaxConcurrentUploads { get; set; } = 2;