using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; using System.Windows.Media.Imaging; using CamBooth.App.Core.AppSettings; using CamBooth.App.Core.Logging; using CamBooth.App.Features.PhotoPrismUpload; namespace CamBooth.App.Features.PictureGallery; public partial class PictureGalleryPage : Page { private readonly AppSettingsService _appSettingsService; private readonly Logger _logger; private readonly PictureGalleryService _pictureGalleryService; private readonly PhotoPrismUploadService _photoPrismUploadService; private int _currentPage = 1; private int _itemsPerPage = 11; private int _totalPages = 1; // QR Code wird nur einmal erstellt und dann wiederverwendet private Border? _qrCodeBorder = null; public PictureGalleryPage(AppSettingsService appSettingsService, Logger logger, PictureGalleryService pictureGalleryService, PhotoPrismUploadService photoPrismUploadService) { this._appSettingsService = appSettingsService; this._logger = logger; this._pictureGalleryService = pictureGalleryService; this._photoPrismUploadService = photoPrismUploadService; this.InitializeComponent(); this.Initialize(); } private async void Initialize() { try { // QR-Code nur einmal beim Initialisieren erstellen CreateQRCodeBorder(); _currentPage = 1; CalculateTotalPages(); LoadCurrentPage(); UpdatePagerControls(); } catch (Exception e) { this._logger.Error(e.Message); } } private void CreateQRCodeBorder() { try { var qrCodeImage = this._photoPrismUploadService.GenerateAlbumQRCode(); if (qrCodeImage != null) { // QR-Code Container mit Label var qrContainer = new StackPanel { Orientation = Orientation.Vertical }; var qrImageControl = new Image { Source = qrCodeImage, Width = 220, Margin = new Thickness(4) }; var qrSubLabel = new TextBlock { Text = "zum Fotoalbum", Foreground = new SolidColorBrush(Colors.White), FontSize = 11, FontWeight = FontWeights.Bold, TextAlignment = TextAlignment.Center, Margin = new Thickness(4, 0, 4, 2) }; qrContainer.Children.Add(qrSubLabel); qrContainer.Children.Add(qrImageControl); _qrCodeBorder = new Border { Background = new SolidColorBrush(Colors.Black), BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#D4AF37")), BorderThickness = new Thickness(2), CornerRadius = new CornerRadius(6), Padding = new Thickness(4), Child = qrContainer, Margin = new Thickness(4) }; this._logger.Debug("✅ PhotoPrism QR-Code statisch erstellt"); } } catch (Exception ex) { this._logger.Warning($"PhotoPrism QR-Code konnte nicht generiert werden: {ex.Message}"); } } private void LoadPictures(int startIndex, int count) { this.Dispatcher.Invoke( () => { // Clear existing items this.PicturesPanel.Items.Clear(); // Füge den statischen QR-Code als erstes Element hinzu if (_qrCodeBorder != null) { this.PicturesPanel.Items.Add(_qrCodeBorder); } // Jetzt die regulären Bilder hinzufügen int totalThumbnails = this._pictureGalleryService.ThumbnailsOrderedByNewestDescending.Count; int endIndex = Math.Min(startIndex + count, totalThumbnails); for (int i = startIndex; i < endIndex; i++) { BitmapImage thumbnail = this._pictureGalleryService.ThumbnailsOrderedByNewestDescending[i]; TextBlock? textBlock = new(); Hyperlink? hyperlink = new(); hyperlink.Click += this.Hyperlink_OnClick; hyperlink.Tag = thumbnail.UriSource; hyperlink.TextDecorations = null; Image? imageControl = new() { Source = thumbnail, Width = 392, Margin = new Thickness(4) }; hyperlink.Inlines.Add(new InlineUIContainer(imageControl)); textBlock.Inlines.Add(hyperlink); this.PicturesPanel.Items.Add(textBlock); } }); } public void CloseOpenDialog() { if (Dispatcher.CheckAccess()) PhotoDialogOverlay.Hide(); else Dispatcher.Invoke(() => PhotoDialogOverlay.Hide()); } public async Task ShowPhotoDialogAsync(string picturePath) { var imageToShow = new Image { MaxHeight = 570, MaxWidth = 800, Stretch = System.Windows.Media.Stretch.Uniform, HorizontalAlignment = HorizontalAlignment.Center, Source = PictureGalleryService.CreateThumbnail(picturePath, 900, 600) }; PhotoDialogOverlay.DialogContent = imageToShow; await PhotoDialogOverlay.ShowAsync(); } private void Hyperlink_OnClick(object sender, RoutedEventArgs e) { Uri? picturePathUri = ((Hyperlink)sender).Tag as Uri; if (picturePathUri is null) { return; } string picturePath = Uri.UnescapeDataString(picturePathUri.AbsolutePath); _ = this.ShowPhotoDialogAsync(picturePath); } private void CalculateTotalPages() { int totalItems = this._pictureGalleryService.ThumbnailsOrderedByNewestDescending.Count; _totalPages = totalItems > 0 ? (int)Math.Ceiling((double)totalItems / _itemsPerPage) : 1; } private void LoadCurrentPage() { int startIndex = (_currentPage - 1) * _itemsPerPage; LoadPictures(startIndex, _itemsPerPage); } private void UpdatePagerControls() { this.Dispatcher.Invoke(() => { PageInfoText.Text = $"Seite {_currentPage} von {_totalPages}"; FirstPageButton.IsEnabled = _currentPage > 1; PreviousPageButton.IsEnabled = _currentPage > 1; NextPageButton.IsEnabled = _currentPage < _totalPages; LastPageButton.IsEnabled = _currentPage < _totalPages; // Visual feedback for disabled buttons FirstPageButton.Opacity = FirstPageButton.IsEnabled ? 1.0 : 0.5; PreviousPageButton.Opacity = PreviousPageButton.IsEnabled ? 1.0 : 0.5; NextPageButton.Opacity = NextPageButton.IsEnabled ? 1.0 : 0.5; LastPageButton.Opacity = LastPageButton.IsEnabled ? 1.0 : 0.5; }); } private void FirstPageButton_Click(object sender, RoutedEventArgs e) { _currentPage = 1; LoadCurrentPage(); UpdatePagerControls(); GalleryScrollViewer.ScrollToTop(); } private void PreviousPageButton_Click(object sender, RoutedEventArgs e) { if (_currentPage > 1) { _currentPage--; LoadCurrentPage(); UpdatePagerControls(); GalleryScrollViewer.ScrollToTop(); } } private void NextPageButton_Click(object sender, RoutedEventArgs e) { if (_currentPage < _totalPages) { _currentPage++; LoadCurrentPage(); UpdatePagerControls(); GalleryScrollViewer.ScrollToTop(); } } private void LastPageButton_Click(object sender, RoutedEventArgs e) { _currentPage = _totalPages; LoadCurrentPage(); UpdatePagerControls(); GalleryScrollViewer.ScrollToTop(); } private void CloseGallery_Click(object sender, RoutedEventArgs e) { // Finde das MainWindow über die Window.GetWindow Methode var window = Window.GetWindow(this); if (window is MainWindow mainWindow) { mainWindow.ClosePicturePanel(); } else { _logger.Warning("MainWindow konnte nicht gefunden werden, um die Galerie zu schließen"); } } }