Improve uploader UI and fix rollup platform dependency
This commit is contained in:
@@ -8,6 +8,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
@@ -21,6 +22,7 @@ namespace PhotoboothUploader;
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private const string DefaultUploadUrl = "https://stylegallery.fotospiel.app/api/v1/photobooth/upload";
|
||||
private const double ResponsiveBreakpoint = 900;
|
||||
private readonly SettingsStore _settingsStore = new();
|
||||
private readonly UploadService _uploadService = new();
|
||||
private PhotoboothSettings _settings;
|
||||
@@ -32,6 +34,7 @@ public partial class MainWindow : Window
|
||||
private int _uploadingCount;
|
||||
private int _failedCount;
|
||||
private DateTimeOffset? _lastSuccessAt;
|
||||
private bool _uploadsPaused;
|
||||
private readonly DispatcherTimer _liveTimer = new();
|
||||
private readonly List<string> _logBuffer = new();
|
||||
|
||||
@@ -47,6 +50,7 @@ public partial class MainWindow : Window
|
||||
_settings.UploadUrl = DefaultUploadUrl;
|
||||
_settings.BaseUrl = ExtractBaseUrl(_settings.UploadUrl);
|
||||
}
|
||||
_uploadsPaused = _settings.UploadsPaused;
|
||||
if (_settings.MaxConcurrentUploads <= 0)
|
||||
{
|
||||
_settings.MaxConcurrentUploads = 2;
|
||||
@@ -60,6 +64,7 @@ public partial class MainWindow : Window
|
||||
_liveTimer.Start();
|
||||
Opened += OnWindowOpened;
|
||||
Closing += OnWindowClosing;
|
||||
SizeChanged += (_, _) => UpdateResponsiveLayout();
|
||||
ApplySettings();
|
||||
}
|
||||
|
||||
@@ -85,7 +90,9 @@ public partial class MainWindow : Window
|
||||
|
||||
FolderText.Text = localPath;
|
||||
UpdateFolderHealth();
|
||||
UpdateFirstRunChecklist();
|
||||
StartUploadPipelineIfReady();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private void DslrBoothPresetButton_Click(object? sender, RoutedEventArgs e)
|
||||
@@ -116,7 +123,7 @@ public partial class MainWindow : Window
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_settings.UploadUrl))
|
||||
{
|
||||
StatusText.Text = "Upload bereit.";
|
||||
UpdateStatus("Upload bereit.");
|
||||
PickFolderButton.IsEnabled = true;
|
||||
TestUploadButton.IsEnabled = true;
|
||||
StartUploadPipelineIfReady();
|
||||
@@ -127,16 +134,27 @@ public partial class MainWindow : Window
|
||||
TestUploadButton.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (_uploadsPaused)
|
||||
{
|
||||
_uploadService.Stop();
|
||||
_watcher?.Dispose();
|
||||
_watcher = null;
|
||||
}
|
||||
|
||||
UpdateCountersText();
|
||||
UpdateFolderHealth();
|
||||
UpdateDiagnostics();
|
||||
UpdateFirstRunChecklist();
|
||||
UpdateLogPreview();
|
||||
RefreshProfiles();
|
||||
UpdatePresetButtons();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private void OnWindowOpened(object? sender, EventArgs e)
|
||||
{
|
||||
ApplyWindowSize();
|
||||
UpdateResponsiveLayout();
|
||||
}
|
||||
|
||||
private void OnWindowClosing(object? sender, WindowClosingEventArgs e)
|
||||
@@ -159,10 +177,57 @@ public partial class MainWindow : Window
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateResponsiveLayout()
|
||||
{
|
||||
if (MainContentGrid is null || LeftPanel is null || RightPanel is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var isNarrow = Bounds.Width < ResponsiveBreakpoint;
|
||||
|
||||
if (isNarrow)
|
||||
{
|
||||
MainContentGrid.ColumnDefinitions = new ColumnDefinitions("1*");
|
||||
MainContentGrid.RowDefinitions = new RowDefinitions("Auto,Auto");
|
||||
MainContentGrid.RowSpacing = 16;
|
||||
MainContentGrid.ColumnSpacing = 0;
|
||||
RightPanel.Margin = new Thickness(0, 16, 0, 0);
|
||||
|
||||
Grid.SetColumn(LeftPanel, 0);
|
||||
Grid.SetRow(LeftPanel, 0);
|
||||
|
||||
Grid.SetColumn(RightPanel, 0);
|
||||
Grid.SetRow(RightPanel, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MainContentGrid.ColumnDefinitions = new ColumnDefinitions("*,16,*");
|
||||
MainContentGrid.RowDefinitions = new RowDefinitions("Auto");
|
||||
MainContentGrid.RowSpacing = 0;
|
||||
MainContentGrid.ColumnSpacing = 0;
|
||||
RightPanel.Margin = new Thickness(0, 6, 0, 0);
|
||||
|
||||
Grid.SetColumn(LeftPanel, 0);
|
||||
Grid.SetRow(LeftPanel, 0);
|
||||
|
||||
Grid.SetColumn(RightPanel, 2);
|
||||
Grid.SetRow(RightPanel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartUploadPipelineIfReady()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_settings.UploadUrl) || string.IsNullOrWhiteSpace(_settings.WatchFolder))
|
||||
{
|
||||
UpdateFirstRunChecklist();
|
||||
UpdateUploadControls();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_uploadsPaused)
|
||||
{
|
||||
UpdateUploadControls();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,6 +235,8 @@ public partial class MainWindow : Window
|
||||
_uploadService.Start(_settings, OnQueued, OnUploading, OnSuccess, OnFailure);
|
||||
StartWatcher(_settings.WatchFolder);
|
||||
RestorePendingUploads();
|
||||
UpdateFirstRunChecklist();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private void StartWatcher(string folder)
|
||||
@@ -228,7 +295,11 @@ public partial class MainWindow : Window
|
||||
|
||||
private void UpdateStatus(string message)
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => StatusText.Text = message);
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
var pausedSuffix = _uploadsPaused ? " (PAUSIERT)" : string.Empty;
|
||||
StatusText.Text = message + pausedSuffix;
|
||||
});
|
||||
}
|
||||
|
||||
private void OnQueued(string path)
|
||||
@@ -494,11 +565,13 @@ public partial class MainWindow : Window
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_settings.UploadUrl))
|
||||
{
|
||||
StatusText.Text = "Upload bereit.";
|
||||
UpdateStatus("Upload bereit.");
|
||||
PickFolderButton.IsEnabled = true;
|
||||
TestUploadButton.IsEnabled = true;
|
||||
}
|
||||
UpdateStatus("Einstellungen gespeichert.");
|
||||
UpdateFirstRunChecklist();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private async void TestConnectionButton_Click(object? sender, RoutedEventArgs e)
|
||||
@@ -558,7 +631,7 @@ public partial class MainWindow : Window
|
||||
|
||||
private async Task<string> CreateSampleUploadAsync()
|
||||
{
|
||||
var uri = new Uri("avares://PhotoboothUploader/Assets/sample-upload.png");
|
||||
var uri = new Uri("avares://AIStylegallery.PhotoboothUploader/Assets/sample-upload.png");
|
||||
await using var source = AssetLoader.Open(uri);
|
||||
var tempPath = Path.Combine(Path.GetTempPath(), $"stylegallery-test-{DateTimeOffset.Now:yyyyMMddHHmmss}.png");
|
||||
await using var target = File.Create(tempPath);
|
||||
@@ -704,6 +777,80 @@ public partial class MainWindow : Window
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateUploadControls()
|
||||
{
|
||||
var ready = !string.IsNullOrWhiteSpace(_settings.UploadUrl)
|
||||
&& !string.IsNullOrWhiteSpace(_settings.WatchFolder);
|
||||
|
||||
StartUploadsButton.IsEnabled = ready && _uploadsPaused;
|
||||
PauseUploadsButton.IsEnabled = ready && !_uploadsPaused;
|
||||
}
|
||||
|
||||
private void StartUploadsButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(_settings.UploadUrl) || string.IsNullOrWhiteSpace(_settings.WatchFolder))
|
||||
{
|
||||
UpdateStatus("Bitte Upload-URL speichern und Ordner wählen.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_uploadsPaused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_watcher?.Dispose();
|
||||
_watcher = null;
|
||||
_uploadsPaused = false;
|
||||
_settings.UploadsPaused = false;
|
||||
_settingsStore.Save(_settings);
|
||||
UpdateStatus("Upload gestartet.");
|
||||
StartUploadPipelineIfReady();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private void PauseUploadsButton_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_uploadsPaused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_uploadsPaused = true;
|
||||
_settings.UploadsPaused = true;
|
||||
_settingsStore.Save(_settings);
|
||||
_uploadService.Stop();
|
||||
_watcher?.Dispose();
|
||||
_watcher = null;
|
||||
UpdateStatus("Upload pausiert.");
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private void UpdateFirstRunChecklist()
|
||||
{
|
||||
var hasUpload = !string.IsNullOrWhiteSpace(_settings.UploadUrl);
|
||||
var hasFolder = !string.IsNullOrWhiteSpace(_settings.WatchFolder);
|
||||
var ready = hasUpload && hasFolder;
|
||||
|
||||
StepUploadUrlText.Text = hasUpload ? "1. Upload-URL speichern ✓" : "1. Upload-URL speichern";
|
||||
StepFolderText.Text = hasFolder ? "2. Upload-Ordner wählen ✓" : "2. Upload-Ordner wählen";
|
||||
StepReadyText.Text = ready ? "3. Upload läuft ✓" : "3. Upload läuft";
|
||||
FirstRunCard.IsVisible = !ready;
|
||||
}
|
||||
|
||||
private void UpdateLogPreview()
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (LogTextBox is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LogTextBox.Text = ReadLogForCopy();
|
||||
});
|
||||
}
|
||||
|
||||
private void SetLastError(string message)
|
||||
{
|
||||
_settings.LastError = message;
|
||||
@@ -1050,6 +1197,8 @@ public partial class MainWindow : Window
|
||||
RefreshProfiles();
|
||||
ProfilesBox.SelectedIndex = 0;
|
||||
UpdateStatus("Profil gespeichert.");
|
||||
UpdateFirstRunChecklist();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private async void LogCopyButton_Click(object? sender, RoutedEventArgs e)
|
||||
@@ -1089,6 +1238,8 @@ public partial class MainWindow : Window
|
||||
{
|
||||
// ignore file errors
|
||||
}
|
||||
|
||||
UpdateLogPreview();
|
||||
}
|
||||
|
||||
private string ReadLogForCopy()
|
||||
@@ -1137,7 +1288,9 @@ public partial class MainWindow : Window
|
||||
_settingsStore.Save(_settings);
|
||||
FolderText.Text = folder;
|
||||
UpdateFolderHealth();
|
||||
UpdateFirstRunChecklist();
|
||||
StartUploadPipelineIfReady();
|
||||
UpdateUploadControls();
|
||||
}
|
||||
|
||||
private static string? GetDslrBoothFolder()
|
||||
|
||||
Reference in New Issue
Block a user