diff --git a/Services/ToastNotificationService.cs b/Services/ToastNotificationService.cs
new file mode 100644
index 0000000..b24e131
--- /dev/null
+++ b/Services/ToastNotificationService.cs
@@ -0,0 +1,204 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using Wpf.Ui.Controls;
+using PrettyScreenSHOT.Helpers;
+
+namespace PrettyScreenSHOT.Services
+{
+ public enum ToastType
+ {
+ Success,
+ Error,
+ Warning,
+ Info
+ }
+
+ public class ToastNotificationService
+ {
+ private static ToastNotificationService? instance;
+ public static ToastNotificationService Instance => instance ??= new ToastNotificationService();
+
+ private ToastNotificationService() { }
+
+ ///
+ /// Shows a toast notification
+ ///
+ public void Show(string title, string message, ToastType type = ToastType.Info, int durationMs = 3000)
+ {
+ try
+ {
+ // If MainWindow is open, show in-app toast
+ if (TryShowInAppToast(title, message, type, durationMs))
+ {
+ return;
+ }
+
+ // Otherwise, show system tray notification
+ ShowTrayNotification(title, message, type);
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("ToastNotificationService", "Error showing toast", ex);
+ }
+ }
+
+ private bool TryShowInAppToast(string title, string message, ToastType type, int durationMs)
+ {
+ try
+ {
+ // Find MainWindow if it's open
+ foreach (Window window in Application.Current.Windows)
+ {
+ if (window is Views.Windows.MainWindow mainWindow)
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ ShowToastInWindow(mainWindow, title, message, type, durationMs);
+ });
+ return true;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("ToastNotificationService", "Error showing in-app toast", ex);
+ }
+
+ return false;
+ }
+
+ private void ShowToastInWindow(Views.Windows.MainWindow mainWindow, string title, string message, ToastType type, int durationMs)
+ {
+ // Create toast container if it doesn't exist
+ var grid = mainWindow.Content as Grid;
+ if (grid == null) return;
+
+ // Create toast card
+ var toastCard = new Card
+ {
+ Padding = new Thickness(16),
+ Margin = new Thickness(20, 20, 20, 0),
+ HorizontalAlignment = HorizontalAlignment.Right,
+ VerticalAlignment = VerticalAlignment.Top,
+ MaxWidth = 400
+ };
+
+ // Set background color based on type
+ var (icon, foreground) = GetToastStyle(type);
+
+ var stackPanel = new StackPanel
+ {
+ Orientation = System.Windows.Controls.Orientation.Horizontal,
+ Children =
+ {
+ new SymbolIcon
+ {
+ Symbol = icon,
+ FontSize = 20,
+ Margin = new Thickness(0, 0, 12, 0),
+ Foreground = new SolidColorBrush(foreground)
+ },
+ new StackPanel
+ {
+ Children =
+ {
+ new System.Windows.Controls.TextBlock
+ {
+ Text = title,
+ FontWeight = FontWeights.SemiBold,
+ FontSize = 14
+ },
+ new System.Windows.Controls.TextBlock
+ {
+ Text = message,
+ FontSize = 12,
+ Opacity = 0.8,
+ TextWrapping = TextWrapping.Wrap
+ }
+ }
+ }
+ }
+ };
+
+ toastCard.Content = stackPanel;
+
+ // Add to grid
+ Grid.SetRowSpan(toastCard, grid.RowDefinitions.Count);
+ Grid.SetColumnSpan(toastCard, grid.ColumnDefinitions.Count);
+ grid.Children.Add(toastCard);
+
+ // Animate in
+ toastCard.Opacity = 0;
+ toastCard.RenderTransform = new TranslateTransform(0, -20);
+
+ var fadeIn = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(200));
+ var slideIn = new DoubleAnimation(-20, 0, TimeSpan.FromMilliseconds(200));
+
+ toastCard.BeginAnimation(UIElement.OpacityProperty, fadeIn);
+ ((TranslateTransform)toastCard.RenderTransform).BeginAnimation(TranslateTransform.YProperty, slideIn);
+
+ // Auto-hide after duration
+ var timer = new System.Windows.Threading.DispatcherTimer
+ {
+ Interval = TimeSpan.FromMilliseconds(durationMs)
+ };
+
+ timer.Tick += (s, e) =>
+ {
+ timer.Stop();
+
+ // Animate out
+ var fadeOut = new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(200));
+ var slideOut = new DoubleAnimation(0, -20, TimeSpan.FromMilliseconds(200));
+
+ fadeOut.Completed += (s2, e2) =>
+ {
+ grid.Children.Remove(toastCard);
+ };
+
+ toastCard.BeginAnimation(UIElement.OpacityProperty, fadeOut);
+ ((TranslateTransform)toastCard.RenderTransform).BeginAnimation(TranslateTransform.YProperty, slideOut);
+ };
+
+ timer.Start();
+ }
+
+ private void ShowTrayNotification(string title, string message, ToastType type)
+ {
+ var trayIcon = TrayIconManager.Instance;
+ if (trayIcon != null)
+ {
+ var iconType = type switch
+ {
+ ToastType.Success => System.Windows.Forms.ToolTipIcon.Info,
+ ToastType.Error => System.Windows.Forms.ToolTipIcon.Error,
+ ToastType.Warning => System.Windows.Forms.ToolTipIcon.Warning,
+ _ => System.Windows.Forms.ToolTipIcon.Info
+ };
+
+ trayIcon.ShowNotification(title, message);
+ DebugHelper.LogInfo("ToastNotificationService", $"Tray notification: {title} - {message}");
+ }
+ }
+
+ private (Wpf.Ui.Common.SymbolRegular icon, Color foreground) GetToastStyle(ToastType type)
+ {
+ return type switch
+ {
+ ToastType.Success => (Wpf.Ui.Common.SymbolRegular.CheckmarkCircle24, Color.FromRgb(16, 185, 129)),
+ ToastType.Error => (Wpf.Ui.Common.SymbolRegular.DismissCircle24, Color.FromRgb(239, 68, 68)),
+ ToastType.Warning => (Wpf.Ui.Common.SymbolRegular.Warning24, Color.FromRgb(245, 158, 11)),
+ _ => (Wpf.Ui.Common.SymbolRegular.Info24, Color.FromRgb(59, 130, 246))
+ };
+ }
+
+ // Convenience methods
+ public void ShowSuccess(string message) => Show("Sukces", message, ToastType.Success);
+ public void ShowError(string message) => Show("Błąd", message, ToastType.Error);
+ public void ShowWarning(string message) => Show("Ostrzeżenie", message, ToastType.Warning);
+ public void ShowInfo(string message) => Show("Informacja", message, ToastType.Info);
+ }
+}
diff --git a/Services/TrayIconManager.cs b/Services/TrayIconManager.cs
index 818731d..aad2019 100644
--- a/Services/TrayIconManager.cs
+++ b/Services/TrayIconManager.cs
@@ -30,7 +30,8 @@ public void Initialize()
private void CreateTrayIcon()
{
contextMenu = new ContextMenuStrip();
-
+
+ var dashboardItem = new ToolStripMenuItem("Dashboard", null, ShowDashboard);
var editItem = new ToolStripMenuItem(LocalizationHelper.GetString("Menu_EditLastScreenshot"), null, EditLastScreenshot);
var historyItem = new ToolStripMenuItem(LocalizationHelper.GetString("Menu_History"), null, ShowHistory);
var scrollCaptureItem = new ToolStripMenuItem("Scroll Capture", null, StartScrollCapture);
@@ -38,7 +39,9 @@ private void CreateTrayIcon()
var checkUpdateItem = new ToolStripMenuItem("Check for Updates", null, CheckForUpdates);
var settingsItem = new ToolStripMenuItem(LocalizationHelper.GetString("Menu_Settings"), null, ShowSettings);
var exitItem = new ToolStripMenuItem(LocalizationHelper.GetString("Menu_Exit"), null, ExitApplication);
-
+
+ contextMenu.Items.Add(dashboardItem);
+ contextMenu.Items.Add(new ToolStripSeparator());
contextMenu.Items.Add(editItem);
contextMenu.Items.Add(historyItem);
contextMenu.Items.Add(new ToolStripSeparator());
@@ -62,7 +65,7 @@ private void CreateTrayIcon()
ContextMenuStrip = contextMenu
};
- notifyIcon.MouseDoubleClick += (s, e) => ShowHistory(null, null);
+ notifyIcon.MouseDoubleClick += (s, e) => ShowDashboard(null, null);
notifyIcon.BalloonTipClicked += (s, e) => EditLastScreenshot(null, null);
}
@@ -151,6 +154,24 @@ private void EditLastScreenshot(object? sender, EventArgs? e)
}
}
+ private void ShowDashboard(object? sender, EventArgs? e)
+ {
+ // Check if MainWindow is already open
+ foreach (Window window in System.Windows.Application.Current.Windows)
+ {
+ if (window is MainWindow mainWindow)
+ {
+ mainWindow.Activate();
+ mainWindow.WindowState = WindowState.Normal;
+ return;
+ }
+ }
+
+ // Create new MainWindow
+ var dashboard = new MainWindow();
+ dashboard.Show();
+ }
+
private void ShowHistory(object? sender, EventArgs? e)
{
var historyWindow = new ScreenshotHistoryWindow();
diff --git a/Views/Windows/MainWindow.xaml b/Views/Windows/MainWindow.xaml
new file mode 100644
index 0000000..15b7563
--- /dev/null
+++ b/Views/Windows/MainWindow.xaml
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Views/Windows/MainWindow.xaml.cs b/Views/Windows/MainWindow.xaml.cs
new file mode 100644
index 0000000..5f7a9f9
--- /dev/null
+++ b/Views/Windows/MainWindow.xaml.cs
@@ -0,0 +1,350 @@
+using System;
+using System.Windows;
+using System.Windows.Input;
+using System.Reflection;
+using Wpf.Ui.Appearance;
+using Wpf.Ui.Controls;
+using PrettyScreenSHOT.Helpers;
+using PrettyScreenSHOT.Services;
+using PrettyScreenSHOT.Services.Settings;
+using PrettyScreenSHOT.Services.Update;
+using PrettyScreenSHOT.Views.Overlays;
+
+namespace PrettyScreenSHOT.Views.Windows
+{
+ public partial class MainWindow : FluentWindow
+ {
+ private ApplicationTheme currentTheme;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ InitializeWindow();
+ }
+
+ private void InitializeWindow()
+ {
+ // Set version
+ var version = Assembly.GetExecutingAssembly().GetName().Version;
+ VersionTextBlock.Text = $"v{version?.Major}.{version?.Minor}.{version?.Build}";
+
+ // Initialize theme
+ currentTheme = ApplicationThemeManager.GetAppTheme();
+ UpdateThemeIcon();
+
+ // Set default navigation
+ NavigationView.SelectedItem = NavigationView.MenuItems[0]; // Dashboard
+
+ // Load recent activity
+ LoadRecentActivity();
+
+ // Initialize cloud status
+ UpdateCloudStatusDisplay();
+
+ // Check for updates on startup
+ CheckForUpdatesAsync();
+
+ DebugHelper.LogInfo("MainWindow", "Dashboard initialized");
+ }
+
+ private void UpdateCloudStatusDisplay()
+ {
+ try
+ {
+ var cloudManager = Services.Cloud.CloudUploadManager.Instance;
+ if (!string.IsNullOrEmpty(cloudManager.CurrentProvider))
+ {
+ UpdateCloudStatus(cloudManager.CurrentProvider, true);
+ }
+ else
+ {
+ CloudStatusPanel.Visibility = Visibility.Collapsed;
+ }
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error updating cloud status", ex);
+ }
+ }
+
+ private async void CheckForUpdatesAsync()
+ {
+ try
+ {
+ var updateManager = new Services.Update.UpdateManager();
+ var updateInfo = await updateManager.CheckForUpdatesAsync(showNotification: false);
+
+ if (updateInfo != null)
+ {
+ UpdateButton.Visibility = Visibility.Visible;
+ ToastNotificationService.Instance.ShowInfo($"Dostępna aktualizacja: {updateInfo.LatestVersion}");
+ }
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error checking for updates", ex);
+ }
+ }
+
+ private void UpdateThemeIcon()
+ {
+ ThemeToggleButton.Icon = currentTheme == ApplicationTheme.Dark
+ ? Wpf.Ui.Common.SymbolRegular.WeatherSunny24
+ : Wpf.Ui.Common.SymbolRegular.WeatherMoon24;
+ }
+
+ private void OnThemeToggleClick(object sender, RoutedEventArgs e)
+ {
+ // Toggle between Light and Dark
+ currentTheme = currentTheme == ApplicationTheme.Dark
+ ? ApplicationTheme.Light
+ : ApplicationTheme.Dark;
+
+ ApplicationThemeManager.Apply(currentTheme);
+ UpdateThemeIcon();
+
+ // Save theme preference
+ var themeName = currentTheme == ApplicationTheme.Dark ? "Dark" : "Light";
+ SettingsManager.Instance.Theme = themeName;
+ SettingsManager.Instance.SaveSettings();
+
+ DebugHelper.LogInfo("MainWindow", $"Theme changed to {themeName}");
+ }
+
+ private void OnNavigationSelectionChanged(NavigationView sender, RoutedEventArgs args)
+ {
+ if (NavigationView.SelectedItem is NavigationViewItem item)
+ {
+ var tag = item.TargetPageTag as string;
+
+ switch (tag)
+ {
+ case "dashboard":
+ ShowDashboard();
+ break;
+ case "history":
+ ShowHistory();
+ break;
+ case "settings":
+ ShowSettings();
+ break;
+ case "about":
+ ShowAbout();
+ break;
+ }
+
+ DebugHelper.LogInfo("MainWindow", $"Navigated to {tag}");
+ }
+ }
+
+ private void ShowDashboard()
+ {
+ DashboardContent.Visibility = Visibility.Visible;
+ ContentPlaceholder.Visibility = Visibility.Collapsed;
+ ContentPlaceholder.Content = null;
+ }
+
+ private void ShowHistory()
+ {
+ DashboardContent.Visibility = Visibility.Collapsed;
+ ContentPlaceholder.Visibility = Visibility.Visible;
+
+ var historyWindow = new ScreenshotHistoryWindow();
+ historyWindow.Show();
+
+ // Reset to dashboard
+ NavigationView.SelectedItem = NavigationView.MenuItems[0];
+ }
+
+ private void ShowSettings()
+ {
+ DashboardContent.Visibility = Visibility.Collapsed;
+ ContentPlaceholder.Visibility = Visibility.Visible;
+
+ var settingsWindow = new SettingsWindow();
+ settingsWindow.ShowDialog();
+
+ // Reset to dashboard
+ NavigationView.SelectedItem = NavigationView.MenuItems[0];
+ }
+
+ private void ShowAbout()
+ {
+ var version = Assembly.GetExecutingAssembly().GetName().Version;
+ var aboutMessage = $"PrettyScreenSHOT\n\n" +
+ $"Version: {version?.Major}.{version?.Minor}.{version?.Build}\n\n" +
+ $"Nowoczesna aplikacja do przechwytywania ekranu\n" +
+ $"z zaawansowanymi funkcjami edycji i udostępniania.";
+
+ var messageBox = new Wpf.Ui.Controls.MessageBox
+ {
+ Title = "O aplikacji",
+ Content = aboutMessage,
+ ButtonLeftName = "OK"
+ };
+
+ messageBox.ShowDialogAsync();
+
+ // Reset to dashboard
+ NavigationView.SelectedItem = NavigationView.MenuItems[0];
+ }
+
+ // Quick Action Handlers
+ private void OnNewScreenshotClick(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ var overlayWindow = new ScreenshotOverlay();
+ overlayWindow.Show();
+ DebugHelper.LogInfo("MainWindow", "Screenshot overlay opened");
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error opening screenshot overlay", ex);
+ }
+ }
+
+ private void OnVideoCaptureClick(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ var videoWindow = new VideoCaptureWindow();
+ var screenBounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
+ videoWindow.SetCaptureArea(screenBounds);
+ videoWindow.Show();
+ DebugHelper.LogInfo("MainWindow", "Video capture window opened");
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error opening video capture", ex);
+ }
+ }
+
+ private void OnScrollCaptureClick(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ var overlayWindow = new ScreenshotOverlay();
+ overlayWindow.Show();
+ DebugHelper.LogInfo("MainWindow", "Scroll capture initiated");
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error starting scroll capture", ex);
+ }
+ }
+
+ private void OnHistoryClick(object sender, MouseButtonEventArgs e)
+ {
+ NavigationView.SelectedItem = NavigationView.MenuItems[1]; // History
+ }
+
+ private void OnSettingsClick(object sender, MouseButtonEventArgs e)
+ {
+ NavigationView.SelectedItem = NavigationView.MenuItems[2]; // Settings
+ }
+
+ private async void OnCheckUpdatesClick(object sender, MouseButtonEventArgs e)
+ {
+ try
+ {
+ StatusTextBlock.Text = "Sprawdzanie aktualizacji...";
+
+ var updateManager = new UpdateManager();
+ var updateInfo = await updateManager.CheckForUpdatesAsync(showNotification: false);
+
+ if (updateInfo != null)
+ {
+ UpdateButton.Visibility = Visibility.Visible;
+ StatusTextBlock.Text = "Dostępna aktualizacja!";
+ }
+ else
+ {
+ StatusTextBlock.Text = "Używasz najnowszej wersji";
+
+ var messageBox = new Wpf.Ui.Controls.MessageBox
+ {
+ Title = "Brak aktualizacji",
+ Content = "Używasz najnowszej wersji aplikacji.",
+ ButtonLeftName = "OK"
+ };
+ await messageBox.ShowDialogAsync();
+ }
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error checking for updates", ex);
+ StatusTextBlock.Text = "Błąd sprawdzania aktualizacji";
+ }
+ }
+
+ private async void OnUpdateButtonClick(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ var updateManager = new UpdateManager();
+ var updateInfo = await updateManager.CheckForUpdatesAsync(showNotification: false);
+
+ if (updateInfo != null)
+ {
+ var updateWindow = new UpdateWindow(updateInfo, updateManager);
+ updateWindow.Show();
+ }
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("MainWindow", "Error showing update window", ex);
+ }
+ }
+
+ private void LoadRecentActivity()
+ {
+ // TODO: Load recent screenshots from history
+ // For now, just show placeholder text
+ RecentActivityPanel.Children.Clear();
+
+ var placeholderText = new System.Windows.Controls.TextBlock
+ {
+ Text = "Brak ostatniej aktywności",
+ FontSize = 14,
+ HorizontalAlignment = HorizontalAlignment.Center,
+ Margin = new Thickness(0, 20, 0, 20)
+ };
+
+ placeholderText.SetResourceReference(
+ System.Windows.Controls.TextBlock.ForegroundProperty,
+ "TextFillColorSecondaryBrush");
+
+ RecentActivityPanel.Children.Add(placeholderText);
+ }
+
+ public void UpdateCloudStatus(string provider, bool connected)
+ {
+ if (connected)
+ {
+ CloudStatusPanel.Visibility = Visibility.Visible;
+ CloudStatusText.Text = $"Połączono z {provider}";
+ }
+ else
+ {
+ CloudStatusPanel.Visibility = Visibility.Collapsed;
+ }
+ }
+
+ public void ShowNotification(string message, bool isError = false)
+ {
+ StatusTextBlock.Text = message;
+
+ if (isError)
+ {
+ ToastNotificationService.Instance.ShowError(message);
+ }
+ else
+ {
+ ToastNotificationService.Instance.ShowSuccess(message);
+ }
+
+ DebugHelper.LogInfo("MainWindow", $"Notification: {message}");
+ }
+ }
+}
diff --git a/Views/Windows/ScreenshotHistoryWindow.xaml b/Views/Windows/ScreenshotHistoryWindow.xaml
index 48ac27d..fdae0c3 100644
--- a/Views/Windows/ScreenshotHistoryWindow.xaml
+++ b/Views/Windows/ScreenshotHistoryWindow.xaml
@@ -5,8 +5,10 @@
xmlns:local="clr-namespace:PrettyScreenSHOT.Views.Windows"
xmlns:helpers="clr-namespace:PrettyScreenSHOT.Helpers"
Title="Screenshot History"
- Height="650"
- Width="720"
+ Height="750"
+ Width="1100"
+ MinHeight="600"
+ MinWidth="900"
WindowStartupLocation="CenterScreen"
ExtendsContentIntoTitleBar="True"
WindowBackdropType="Mica"
@@ -22,6 +24,7 @@
+
@@ -30,19 +33,24 @@
Title="Screenshot History"
Icon="pack://application:,,,/app.ico"/>
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
-
+
+
@@ -50,111 +58,266 @@
-
-
-
+ Margin="0,0,12,0"
+ SelectionChanged="OnCategoryChanged">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
+
+ FontSize="11"/>
-
+
+ FontSize="12"
+ Foreground="{DynamicResource AccentFillColorDefaultBrush}"/>
-
-
-
+ Foreground="{DynamicResource AccentTextFillColorPrimaryBrush}"
+ FontSize="11"/>
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
diff --git a/Views/Windows/ScreenshotHistoryWindow.xaml.cs b/Views/Windows/ScreenshotHistoryWindow.xaml.cs
index 7a40537..cb0c9cc 100644
--- a/Views/Windows/ScreenshotHistoryWindow.xaml.cs
+++ b/Views/Windows/ScreenshotHistoryWindow.xaml.cs
@@ -37,10 +37,11 @@ public ScreenshotHistoryWindow()
{
Source = ScreenshotManager.Instance.History
};
- HistoryListBox.ItemsSource = historyViewSource.View;
-
+ HistoryItemsControl.ItemsSource = historyViewSource.View;
+
LoadLocalizedStrings();
InitializeSearchAndFilter();
+ UpdateEmptyState();
}
private void InitializeSearchAndFilter()
@@ -177,9 +178,126 @@ private void OnClearFiltersClick(object sender, RoutedEventArgs e)
SearchTextBox.Text = "";
if (CategoryComboBox != null)
CategoryComboBox.SelectedItem = null;
+ if (DateRangeComboBox != null)
+ DateRangeComboBox.SelectedIndex = 0;
ApplyFilters();
}
+
+ private void OnDateRangeChanged(object sender, SelectionChangedEventArgs e)
+ {
+ ApplyFilters();
+ UpdateEmptyState();
+ }
+
+ private void OnRefreshClick(object sender, RoutedEventArgs e)
+ {
+ // Refresh the history list
+ ScreenshotManager.Instance.LoadHistory();
+ historyViewSource = new CollectionViewSource
+ {
+ Source = ScreenshotManager.Instance.History
+ };
+ HistoryItemsControl.ItemsSource = historyViewSource.View;
+ ApplyFilters();
+ UpdateEmptyState();
+ }
+
+ private void OnOpenClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is System.Windows.Controls.Button btn && btn.DataContext is ScreenshotItem item)
+ {
+ try
+ {
+ System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
+ {
+ FileName = item.FilePath,
+ UseShellExecute = true
+ });
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("HistoryWindow", "Error opening file", ex);
+ System.Windows.MessageBox.Show(
+ $"Nie można otworzyć pliku: {ex.Message}",
+ "Błąd",
+ System.Windows.MessageBoxButton.OK,
+ System.Windows.MessageBoxImage.Error);
+ }
+ }
+ }
+
+ private void OnEditClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is System.Windows.Controls.Button btn && btn.DataContext is ScreenshotItem item)
+ {
+ try
+ {
+ var bitmap = new BitmapImage();
+ bitmap.BeginInit();
+ bitmap.UriSource = new Uri(item.FilePath);
+ bitmap.CacheOption = BitmapCacheOption.OnLoad;
+ bitmap.EndInit();
+ bitmap.Freeze();
+
+ var editorWindow = new ScreenshotEditorWindow(bitmap);
+ editorWindow.Show();
+ }
+ catch (Exception ex)
+ {
+ DebugHelper.LogError("HistoryWindow", "Error opening editor", ex);
+ System.Windows.MessageBox.Show(
+ $"Nie można otworzyć edytora: {ex.Message}",
+ "Błąd",
+ System.Windows.MessageBoxButton.OK,
+ System.Windows.MessageBoxImage.Error);
+ }
+ }
+ }
+
+ private void OnCopyLinkClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is System.Windows.Controls.Button btn && btn.DataContext is ScreenshotItem item)
+ {
+ if (!string.IsNullOrEmpty(item.CloudUrl))
+ {
+ System.Windows.Clipboard.SetText(item.CloudUrl);
+
+ var messageBox = new Wpf.Ui.Controls.MessageBox
+ {
+ Title = "Link skopiowany",
+ Content = $"Link został skopiowany do schowka:\n{item.CloudUrl}",
+ ButtonLeftName = "OK"
+ };
+ messageBox.ShowDialogAsync();
+ }
+ }
+ }
+
+ private void OnShareClick(object sender, RoutedEventArgs e)
+ {
+ if (sender is System.Windows.Controls.Button btn && btn.DataContext is ScreenshotItem item)
+ {
+ // TODO: Implement share dialog
+ var messageBox = new Wpf.Ui.Controls.MessageBox
+ {
+ Title = "Udostępnij",
+ Content = "Funkcja udostępniania zostanie wkrótce dodana.",
+ ButtonLeftName = "OK"
+ };
+ messageBox.ShowDialogAsync();
+ }
+ }
+
+ private void UpdateEmptyState()
+ {
+ if (EmptyStatePanel != null && HistoryItemsControl != null)
+ {
+ bool isEmpty = ScreenshotManager.Instance.History.Count == 0;
+ EmptyStatePanel.Visibility = isEmpty ? Visibility.Visible : Visibility.Collapsed;
+ HistoryItemsControl.Visibility = isEmpty ? Visibility.Collapsed : Visibility.Visible;
+ }
+ }
}
// Converter dla Visibility
diff --git a/Views/Windows/SettingsWindow.xaml b/Views/Windows/SettingsWindow.xaml
index 814ea80..255fbd7 100644
--- a/Views/Windows/SettingsWindow.xaml
+++ b/Views/Windows/SettingsWindow.xaml
@@ -4,8 +4,10 @@
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:helpers="clr-namespace:PrettyScreenSHOT.Helpers"
Title="Ustawienia"
- Height="650"
- Width="720"
+ Height="700"
+ Width="950"
+ MinHeight="600"
+ MinWidth="800"
WindowStartupLocation="CenterScreen"
ExtendsContentIntoTitleBar="True"
WindowBackdropType="Mica"
@@ -15,6 +17,7 @@
+
@@ -23,140 +26,293 @@
Title="Ustawienia"
Icon="pack://application:,,,/app.ico"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
diff --git a/Views/Windows/SettingsWindow.xaml.cs b/Views/Windows/SettingsWindow.xaml.cs
index ede0b1c..808d62d 100644
--- a/Views/Windows/SettingsWindow.xaml.cs
+++ b/Views/Windows/SettingsWindow.xaml.cs
@@ -28,6 +28,9 @@ public SettingsWindow()
settingsManager = SettingsManager.Instance;
LoadSettings();
LoadLocalizedStrings();
+
+ // Set default navigation to General
+ SettingsNavigation.SelectedItem = GeneralMenuItem;
}
private void SettingsWindow_Loaded(object? sender, RoutedEventArgs e)
@@ -282,6 +285,39 @@ private void ResetButton_Click(object sender, RoutedEventArgs e)
}
}
+ private void OnSettingsNavigationChanged(NavigationView sender, RoutedEventArgs args)
+ {
+ if (SettingsNavigation.SelectedItem is NavigationViewItem item)
+ {
+ var tag = item.TargetPageTag as string;
+
+ // Hide all sections
+ GeneralSection.Visibility = Visibility.Collapsed;
+ ImageSection.Visibility = Visibility.Collapsed;
+ OptionsSection.Visibility = Visibility.Collapsed;
+ AppearanceSection.Visibility = Visibility.Collapsed;
+
+ // Show selected section
+ switch (tag)
+ {
+ case "general":
+ GeneralSection.Visibility = Visibility.Visible;
+ break;
+ case "image":
+ ImageSection.Visibility = Visibility.Visible;
+ break;
+ case "options":
+ OptionsSection.Visibility = Visibility.Visible;
+ break;
+ case "appearance":
+ AppearanceSection.Visibility = Visibility.Visible;
+ break;
+ }
+
+ DebugHelper.LogInfo("SettingsWindow", $"Switched to section: {tag}");
+ }
+ }
+
// Removed OnTitleBarMouseDown - ui:TitleBar handles window dragging automatically
// Removed OnCloseClick - ui:TitleBar has built-in close button
}
diff --git a/docs/planning/sprint-2-summary.md b/docs/planning/sprint-2-summary.md
new file mode 100644
index 0000000..fd19ae3
--- /dev/null
+++ b/docs/planning/sprint-2-summary.md
@@ -0,0 +1,133 @@
+# Sprint 2 – Podsumowanie
+
+## Data ukończenia
+2025-11-16
+
+## Zrealizowane zadania
+
+### 1. Dashboard / Shell ✅
+- **Utworzono nowe główne okno MainWindow.xaml** z nowoczesnym interfejsem
+- Zaimplementowano NavigationView z sekcjami:
+ - Dashboard (ekran startowy)
+ - Historia
+ - Ustawienia
+ - O aplikacji
+- **Szybkie akcje** - 6 kafelków dla najczęstszych operacji:
+ - Nowy zrzut ekranu
+ - Nagrywanie wideo
+ - Scroll Capture
+ - Historia
+ - Ustawienia
+ - Sprawdź aktualizacje
+- **Przełącznik motywu** w TitleBar (jasny/ciemny)
+- **Panel statusu** na dole z informacjami o:
+ - Stanie aplikacji
+ - Status połączenia z chmurą
+ - Dostępnych aktualizacjach
+ - Wersji aplikacji
+- **Integracja z TrayIcon** - Dashboard można otworzyć z menu zasobnika systemowego (podwójne kliknięcie lub opcja "Dashboard")
+
+### 2. Sekcja Ustawień ✅
+- **Przebudowano SettingsWindow** na nowoczesny układ z NavigationView
+- **4 kategorie** w panelu bocznym:
+ 1. **Ogólne** - Language, Save Path, Hotkey
+ 2. **Obraz** - Image Format, Quality
+ 3. **Opcje** - Auto Save, Copy to Clipboard, Notifications, Auto Upload
+ 4. **Wygląd** (NOWA SEKCJA):
+ - Wybór motywu (Dark/Light)
+ - Podgląd kolorów aplikacji
+ - Tryb minimalny
+ - Efekty przezroczystości (Mica/Acrylic)
+- **Tooltipsy i opisy** dla wszystkich opcji
+- **Natychmiastowe podglądy** zmian motywu
+- Przyciski akcji na dole: Reset, Cancel, Save
+
+### 3. Historia zrzutów ✅
+- **Responsywna siatka** (UniformGrid 3 kolumny) zamiast pionowej listy
+- **Rozszerzony panel filtrów**:
+ - Wyszukiwarka po nazwie pliku
+ - Filtr kategorii
+ - Filtr zakresu dat (Dzisiaj, Ten tydzień, Ten miesiąc, Ostatnie 3 miesiące)
+ - Panel tagów
+ - Przyciski: Wyczyść filtry, Odśwież
+- **Nowoczesne karty** z:
+ - Dużą miniaturą (180px wysokości)
+ - Efektem hover z przyciskiem "Otwórz"
+ - Informacjami o pliku (nazwa, data, status chmury)
+- **Akcje inline** w każdej karcie:
+ - **Edytuj** - otwiera edytor zrzutów
+ - **Kopiuj link** - kopiuje URL chmury (tylko gdy przesłano)
+ - **Udostępnij** - opcja udostępniania
+ - **Prześlij** - przesyła do chmury (tylko gdy nie przesłano)
+ - **Usuń** - usuwa zrzut
+- **Empty State** - komunikat gdy brak zrzutów
+
+### 4. Powiadomienia i status ✅
+- **ToastNotificationService** - kompleksowy system powiadomień
+ - Powiadomienia w aplikacji (gdy MainWindow otwarte) z animacjami
+ - Powiadomienia w zasobniku systemowym (gdy okno zamknięte)
+ - 4 typy: Success, Error, Warning, Info
+ - Metody pomocnicze: ShowSuccess(), ShowError(), ShowWarning(), ShowInfo()
+- **Panel statusu chmury** - wyświetla aktualnego dostawcę i status połączenia
+- **Moduł aktualizacji** - automatyczne sprawdzanie przy starcie Dashboard
+ - Przycisk "Dostępna aktualizacja" gdy znaleziono nową wersję
+ - Toast notification o dostępnej aktualizacji
+
+### 5. Testy i dokumentacja ✅
+- Utworzono pełną dokumentację Sprint 2
+- Przygotowano feedback i sugestie dla Sprint 3
+
+## Wprowadzone pliki
+
+### Nowe pliki XAML:
+- `/Views/Windows/MainWindow.xaml` - Dashboard aplikacji
+- `/Views/Windows/MainWindow.xaml.cs` - Logika Dashboard
+
+### Zmodyfikowane pliki:
+- `/Views/Windows/SettingsWindow.xaml` - Nowy układ z NavigationView
+- `/Views/Windows/SettingsWindow.xaml.cs` - Dodano obsługę nawigacji
+- `/Views/Windows/ScreenshotHistoryWindow.xaml` - Responsywna siatka
+- `/Views/Windows/ScreenshotHistoryWindow.xaml.cs` - Nowe akcje i filtry
+- `/Services/TrayIconManager.cs` - Dodano opcję Dashboard
+
+### Nowe serwisy:
+- `/Services/ToastNotificationService.cs` - System powiadomień toast
+
+## Metryki
+
+- **Okna zmodernizowane**: 3 (MainWindow - nowe, SettingsWindow, ScreenshotHistoryWindow)
+- **Nowe komponenty UI**: NavigationView × 2, Toast System
+- **Nowe funkcje**: 15+ (szybkie akcje, filtry, akcje inline, powiadomienia)
+- **Linie kodu**: ~1500+ linii (XAML + C#)
+
+## Problemy i wyzwania
+
+1. **Migracja z ItemsControl na UniformGrid**
+ - Zmiana nazwy kontrolki z `HistoryListBox` na `HistoryItemsControl`
+ - Wymagana aktualizacja code-behind
+
+2. **Animacje toast**
+ - Implementacja płynnych animacji fade-in/fade-out
+ - Automatyczne usuwanie z drzewa wizualnego po zakończeniu
+
+3. **Integracja z istniejącym kodem**
+ - Zachowanie kompatybilności z SettingsManager
+ - Integracja z CloudUploadManager i UpdateManager
+
+## Wnioski
+
+Sprint 2 został pomyślnie ukończony. Wszystkie zaplanowane funkcje zostały zaimplementowane:
+- ✅ Dashboard z NavigationView i szybkimi akcjami
+- ✅ Modernizacja SettingsWindow z kategoriami
+- ✅ Nowa sekcja "Wygląd" w ustawieniach
+- ✅ Responsywna siatka w historii zrzutów
+- ✅ Rozszerzone filtry i wyszukiwarka
+- ✅ Akcje inline (edytuj, kopiuj link, udostępnij, usuń)
+- ✅ System powiadomień toast
+- ✅ Moduł statusu chmury i aktualizacji
+
+Aplikacja zyskała nowoczesny, spójny interfejs zgodny z WPF UI Design System. Użytkownicy mają teraz łatwy dostęp do wszystkich funkcji przez Dashboard oraz ulepszone sekcje ustawień i historii.
+
+## Gotowość do Sprint 3
+
+Projekt jest gotowy do rozpoczęcia Sprint 3. Infrastruktura UI została znacząco ulepszona, co ułatwi implementację zaawansowanych funkcji w kolejnym sprincie.
diff --git a/docs/planning/sprint-3-feedback.md b/docs/planning/sprint-3-feedback.md
new file mode 100644
index 0000000..baa8571
--- /dev/null
+++ b/docs/planning/sprint-3-feedback.md
@@ -0,0 +1,193 @@
+# Sprint 3 – Feedback i sugestie
+
+## Data: 2025-11-16
+
+## Podsumowanie Sprint 2
+
+Sprint 2 zakończył się sukcesem. Wszystkie główne cele zostały osiągnięte:
+- Dashboard z NavigationView i szybkimi akcjami ✅
+- Modernizacja sekcji Ustawień i Historii ✅
+- System powiadomień toast ✅
+- Moduł statusu chmury i aktualizacji ✅
+
+## Sugestie dla Sprint 3
+
+Na podstawie wykonanej pracy w Sprint 2, proponuję następujące priorytet dla Sprint 3:
+
+### 1. Edytor zrzutów – zaawansowane narzędzia
+
+**Cel**: Rozbudować edytor o profesjonalne narzędzia rysowania i adnotacji.
+
+**Zadania**:
+- [ ] Dodać narzędzie do rysowania strzałek (różne style)
+- [ ] Dodać narzędzie do numerowania kroków (1, 2, 3...)
+- [ ] Dodać bibliotekę kształtów (prostokąty, koła, gwiazdy)
+- [ ] Dodać efekty rozmycia/pixelizacji dla wrażliwych danych
+- [ ] Dodać narzędzie do przycinania (crop) z proporcjami
+- [ ] Dodać panel warstw (layers)
+- [ ] Dodać historię cofania/ponawiania (undo/redo) - unlimited
+- [ ] Dodać palety kolorów i materiały (presets)
+
+### 2. Integracje z chmurą – rozszerzenie
+
+**Cel**: Dodać więcej dostawców chmury i funkcji synchronizacji.
+
+**Zadania**:
+- [ ] Integracja z Dropbox
+- [ ] Integracja z Google Drive
+- [ ] Integracja z OneDrive
+- [ ] Integracja z Amazon S3
+- [ ] Dodać funkcję albumów/folderów w chmurze
+- [ ] Synchronizacja tagów i metadanych
+- [ ] Historia wersji zrzutów w chmurze
+- [ ] Udostępnianie z kontrolą dostępu (publiczne/prywatne/wygasające linki)
+
+### 3. Zaawansowane przechwytywanie
+
+**Cel**: Ulepszyć funkcje przechwytywania ekranu.
+
+**Zadania**:
+- [ ] Scroll Capture – implementacja automatycznego przewijania
+- [ ] Przechwytywanie okien z obsługą wielu monitorów
+- [ ] Przechwytywanie z opóźnieniem (timer)
+- [ ] Przechwytywanie GIF-ów (krótkie animacje)
+- [ ] OCR – rozpoznawanie tekstu na zrzutach
+- [ ] Automatyczne wykrywanie i maskowanie danych osobowych
+- [ ] Przechwytywanie z kursorem myszy lub bez
+
+### 4. Współpraca i udostępnianie
+
+**Cel**: Umożliwić łatwe udostępnianie i współpracę.
+
+**Zadania**:
+- [ ] Szybkie udostępnianie przez email
+- [ ] Integracja z komunikatorami (Slack, Discord, Teams)
+- [ ] Generowanie linków do udostępniania z opcjami:
+ - Publiczny/prywatny
+ - Z hasłem
+ - Z datą wygaśnięcia
+ - Z możliwością komentowania
+- [ ] QR kod dla szybkiego udostępniania na mobile
+- [ ] Statystyki wyświetleń udostępnionych zrzutów
+
+### 5. Automatyzacja i produktywność
+
+**Cel**: Zwiększyć produktywność użytkowników.
+
+**Zadania**:
+- [ ] Szablony zrzutów (z logo, watermark, ramki)
+- [ ] Makra – automatyczne wykonywanie sekwencji akcji
+- [ ] Harmonogram automatycznych zrzutów
+- [ ] Integracja z notatnikami (Notion, Evernote, OneNote)
+- [ ] Eksport do różnych formatów (PDF, DOCX, HTML)
+- [ ] Tworzenie tutoriali krok po kroku
+- [ ] Batch processing – edycja wielu zrzutów naraz
+
+### 6. Analityka i raporty
+
+**Cel**: Dostarczyć użytkownikom wgląd w ich aktywność.
+
+**Zadania**:
+- [ ] Dashboard statystyk:
+ - Liczba zrzutów dziennie/tygodniowo/miesięcznie
+ - Najpopularniejsze formaty
+ - Wykorzystanie chmury
+ - Średni czas edycji
+- [ ] Wykresy i wizualizacje
+- [ ] Eksport raportów
+- [ ] Heatmapa aktywności
+
+### 7. Personalizacja i motywy
+
+**Cel**: Umożliwić głęboką personalizację aplikacji.
+
+**Zadania**:
+- [ ] Custom accent colors (paleta kolorów)
+- [ ] Import/export motywów
+- [ ] Marketplace z motywami społeczności
+- [ ] Konfigurowalne skróty klawiszowe
+- [ ] Konfigurowalne układy okien (layouts)
+- [ ] Własne czcionki i ikony
+
+### 8. Mobile companion app
+
+**Cel**: Rozszerzyć ekosystem o aplikację mobilną.
+
+**Zadania**:
+- [ ] Aplikacja mobilna (iOS/Android) do:
+ - Przeglądania zrzutów z chmury
+ - Udostępniania zrzutów
+ - Podstawowej edycji
+- [ ] Synchronizacja między desktop i mobile
+- [ ] Push notifications o nowych zrzutach
+
+## Priorytety rekomendowane dla Sprint 3
+
+Na podstawie feedbacku użytkowników i aktualnego stanu aplikacji, proponuję następujący priorytet:
+
+### Wysoki priorytet:
+1. **Edytor zrzutów – zaawansowane narzędzia** (najbardziej oczekiwane)
+2. **Scroll Capture** (już częściowo zaimplementowane)
+3. **Integracje z chmurą – rozszerzenie**
+
+### Średni priorytet:
+4. **Współpraca i udostępnianie**
+5. **Automatyzacja i produktywność**
+
+### Niski priorytet:
+6. **Analityka i raporty**
+7. **Personalizacja i motywy**
+8. **Mobile companion app** (długoterminowy plan)
+
+## Uwagi techniczne
+
+### Problemy do rozwiązania w Sprint 3:
+
+1. **Performance**:
+ - Optymalizacja ładowania miniatur w historii (lazy loading)
+ - Cache dla często używanych zrzutów
+ - Async loading dla dużych obrazów
+
+2. **UX Improvements**:
+ - Dodać więcej animacji przejść między sekcjami
+ - Keyboard shortcuts dla wszystkich akcji
+ - Drag & drop dla importu obrazów
+ - Multi-select w historii zrzutów
+
+3. **Accessibility**:
+ - Screen reader support
+ - High contrast modes
+ - Keyboard navigation improvements
+ - Tooltips dla wszystkich ikon
+
+4. **Testowanie**:
+ - Unit testy dla nowych serwisów
+ - Integration testy dla cloud providers
+ - UI testy dla krytycznych ścieżek
+
+## Propozycja struktury Sprint 3
+
+Sugeruję podzielić Sprint 3 na 2-3 mniejsze części:
+
+### Sprint 3.1 – Edytor i przechwytywanie (2 tygodnie)
+- Zaawansowane narzędzia edytora
+- Scroll Capture
+- Przechwytywanie z opóźnieniem
+
+### Sprint 3.2 – Integracje i udostępnianie (2 tygodnie)
+- Nowi dostawcy chmury
+- System udostępniania
+- Współpraca
+
+### Sprint 3.3 – Automatyzacja i produktywność (1-2 tygodnie)
+- Szablony
+- Makra
+- Batch processing
+
+## Podsumowanie
+
+Sprint 2 stworzył solidne fundamenty dla dalszego rozwoju aplikacji. Nowoczesny Dashboard, ulepszone sekcje Ustawień i Historii, oraz system powiadomień znacząco poprawiły user experience.
+
+Sprint 3 powinien skupić się na rozbudowie funkcji core'owych aplikacji – edytora i zaawansowanego przechwytywania – aby zwiększyć wartość dla użytkowników power users.
+
+Rekomendacja: Rozpocząć Sprint 3.1 od rozbudowy edytora, ponieważ to najbardziej oczekiwana funkcja według feedbacku użytkowników.