From 5eef007dd89ce81cd257686b87ddb1e1d73c4ac9 Mon Sep 17 00:00:00 2001 From: rstewa <70178227+rstewa@users.noreply.github.com> Date: Wed, 3 Jul 2024 00:17:41 -0500 Subject: [PATCH] wip #50 --- Audibly.App/AppShell.xaml.cs | 8 +- Audibly.App/Audibly.App.csproj | 6 + Audibly.App/Services/AppDataService.cs | 20 +++ Audibly.App/Services/EditMetadataService.cs | 10 ++ .../Services/Interfaces/IAppDataService.cs | 1 + .../Interfaces/IEditMetadataService.cs | 10 ++ Audibly.App/UserControls/AudiobookTile.xaml | 4 + .../UserControls/AudiobookTile.xaml.cs | 17 ++ Audibly.App/Views/EditMetadataPage.xaml | 110 +++++++++++++ Audibly.App/Views/EditMetadataPage.xaml.cs | 147 ++++++++++++++++++ Audibly.App/Views/LibraryCardPage.xaml | 3 +- Audibly.App/Views/LibraryCardPage.xaml.cs | 13 ++ 12 files changed, 346 insertions(+), 3 deletions(-) create mode 100644 Audibly.App/Services/EditMetadataService.cs create mode 100644 Audibly.App/Services/Interfaces/IEditMetadataService.cs create mode 100644 Audibly.App/Views/EditMetadataPage.xaml create mode 100644 Audibly.App/Views/EditMetadataPage.xaml.cs diff --git a/Audibly.App/AppShell.xaml.cs b/Audibly.App/AppShell.xaml.cs index 2417a1c..ec9ee2b 100644 --- a/Audibly.App/AppShell.xaml.cs +++ b/Audibly.App/AppShell.xaml.cs @@ -50,9 +50,13 @@ public AppShell() { InitializeComponent(); // set the title bar - AppShellFrame.Navigate(typeof(LibraryCardPage)); + // AppShellFrame.Navigate(typeof(LibraryCardPage)); - Loaded += (_, _) => { NavView.SelectedItem = LibraryCardMenuItem; }; + Loaded += (_, _) => + { + AppShellFrame.Navigate(typeof(LibraryCardPage)); + NavView.SelectedItem = LibraryCardMenuItem; + }; ViewModel.MessageService.ShowDialogRequested += OnShowDialogRequested; App.ViewModel.FileImporter.ImportCompleted += HideImportDialog; diff --git a/Audibly.App/Audibly.App.csproj b/Audibly.App/Audibly.App.csproj index 2a83cf6..5406cfc 100644 --- a/Audibly.App/Audibly.App.csproj +++ b/Audibly.App/Audibly.App.csproj @@ -27,6 +27,7 @@ + @@ -139,6 +140,11 @@ Changelog.resx + + + MSBuild:Compile + + MSBuild:Compile diff --git a/Audibly.App/Services/AppDataService.cs b/Audibly.App/Services/AppDataService.cs index f0257a8..5953ad9 100644 --- a/Audibly.App/Services/AppDataService.cs +++ b/Audibly.App/Services/AppDataService.cs @@ -19,6 +19,26 @@ public class AppDataService : IAppDataService { private static StorageFolder StorageFolder => ApplicationData.Current.LocalFolder; + public async Task> WriteCoverImageAsync(string path, string newCoverImagePath) + { + var bookAppdataDir = await StorageFolder.CreateFolderAsync(path, + CreationCollisionOption.OpenIfExists); + var coverImagePath = Path.Combine(bookAppdataDir.Path, "CoverImage.png"); + File.Copy(newCoverImagePath, coverImagePath, true); + + // create 400x400 thumbnail + var thumbnailPath = Path.Combine(bookAppdataDir.Path, "Thumbnail.jpeg"); + var result = await ShrinkAndSaveAsync(coverImagePath, thumbnailPath, 400, 400); + if (!result) thumbnailPath = string.Empty; // return empty string if thumbnail creation failed + + // leaving this commented out for now because it increases the import time an absurd amount + // create .ico file + // var coverImagePath = Path.Combine(bookAppdataDir.Path, "CoverImage.png"); + // FolderIcon.SetFolderIcon(coverImagePath, bookAppdataDir.Path); + + return new Tuple(coverImagePath, thumbnailPath); + } + public async Task> WriteCoverImageAsync(string path, byte[]? imageBytes) { var bookAppdataDir = await StorageFolder.CreateFolderAsync(path, diff --git a/Audibly.App/Services/EditMetadataService.cs b/Audibly.App/Services/EditMetadataService.cs new file mode 100644 index 0000000..cfad0bb --- /dev/null +++ b/Audibly.App/Services/EditMetadataService.cs @@ -0,0 +1,10 @@ +// Author: rstewa · https://github.com/rstewa +// Created: 06/29/2024 +// Updated: 06/29/2024 + +namespace Audibly.App.Services; + +public class EditMetadataService +{ + +} \ No newline at end of file diff --git a/Audibly.App/Services/Interfaces/IAppDataService.cs b/Audibly.App/Services/Interfaces/IAppDataService.cs index 60ff9fc..380cb0a 100644 --- a/Audibly.App/Services/Interfaces/IAppDataService.cs +++ b/Audibly.App/Services/Interfaces/IAppDataService.cs @@ -10,6 +10,7 @@ namespace Audibly.App.Services.Interfaces; public interface IAppDataService { + Task> WriteCoverImageAsync(string path, string newCoverImagePath); Task> WriteCoverImageAsync(string path, byte[]? imageBytes); Task DeleteCoverImageAsync(string path); diff --git a/Audibly.App/Services/Interfaces/IEditMetadataService.cs b/Audibly.App/Services/Interfaces/IEditMetadataService.cs new file mode 100644 index 0000000..5e0ca84 --- /dev/null +++ b/Audibly.App/Services/Interfaces/IEditMetadataService.cs @@ -0,0 +1,10 @@ +// Author: rstewa · https://github.com/rstewa +// Created: 06/29/2024 +// Updated: 06/29/2024 + +namespace Audibly.App.Services.Interfaces; + +public interface IEditMetadataService +{ + // update metadata property for an audiobook +} \ No newline at end of file diff --git a/Audibly.App/UserControls/AudiobookTile.xaml b/Audibly.App/UserControls/AudiobookTile.xaml index 8128a3f..5f4d9e3 100644 --- a/Audibly.App/UserControls/AudiobookTile.xaml +++ b/Audibly.App/UserControls/AudiobookTile.xaml @@ -27,6 +27,10 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Audibly.App/Views/EditMetadataPage.xaml.cs b/Audibly.App/Views/EditMetadataPage.xaml.cs new file mode 100644 index 0000000..b6e4fb5 --- /dev/null +++ b/Audibly.App/Views/EditMetadataPage.xaml.cs @@ -0,0 +1,147 @@ +// Author: rstewa · https://github.com/rstewa +// Created: 07/02/2024 +// Updated: 07/03/2024 + +using System; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using Windows.Storage.Pickers; +using ATL; +using Audibly.App.ViewModels; +using CommunityToolkit.WinUI; +using Microsoft.UI.Dispatching; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Navigation; +using WinRT.Interop; + +namespace Audibly.App.Views; + +public sealed partial class EditMetadataPage : Page +{ + public EditMetadataPage() + { + InitializeComponent(); + } + + private readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + private Track Track { get; set; } + private AudiobookViewModel ViewModel { get; set; } + + protected override void OnNavigatedTo(NavigationEventArgs e) + { + ViewModel = (AudiobookViewModel)e.Parameter; + Track = new Track(ViewModel.FilePath); + + // Use reflection to get all properties of the Track object + var properties = Track.GetType().GetProperties(); + + // observable collection + var trackProperties = new ObservableCollection(); + + // Iterate over each property + foreach (var property in properties) + { + if (property.Name == "EmbeddedPictures") + { + // var embeddedPictures = property.GetValue(Track) as List; + // var imageBytes = embeddedPictures.FirstOrDefault()?.PictureData; + } + + var trackProperty = new TrackProperty + { + Name = $"{property.Name}:", + Value = property.GetValue(Track)?.ToString() ?? "N/A" + }; + + trackProperties.Add(trackProperty); + } + + TrackPropertiesListView.ItemsSource = trackProperties; + + base.OnNavigatedTo(e); + } + + private async void EditCoverImageButton_Click(object sender, RoutedEventArgs e) + { + // Open file picker + var filePicker = new FileOpenPicker(); + var window = App.Window; + var hWnd = WindowNative.GetWindowHandle(window); + InitializeWithWindow.Initialize(filePicker, hWnd); + + filePicker.ViewMode = PickerViewMode.Thumbnail; + filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; + filePicker.FileTypeFilter.Add(".jpg"); + filePicker.FileTypeFilter.Add(".jpeg"); + filePicker.FileTypeFilter.Add(".png"); + + var file = await filePicker.PickSingleFileAsync(); + if (file != null) + { + // Get the file path + var filePath = file.Path; + + // Write the cover image to the app data folder + // get directory path + var path = Path.GetFileName(Path.GetDirectoryName(ViewModel.CoverImagePath)); + + if (path == null) + { + // log the error + App.ViewModel.LoggingService.LogError( + new Exception("Could not get the directory path for the cover image")); + App.ViewModel.EnqueueNotification(new Notification + { + Message = "Could not get the directory path for the cover image.", + Severity = InfoBarSeverity.Error + }); + return; + } + + var (coverImagePath, thumbnailPath) = + await App.ViewModel.AppDataService.WriteCoverImageAsync(path, filePath); + + // var viewModel2 = App.ViewModel.Audiobooks.FirstOrDefault(x => x.FilePath == ViewModel.FilePath); + + _ = _dispatcherQueue.EnqueueAsync(() => + { + ViewModel.CoverImagePath = coverImagePath; + ViewModel.ThumbnailPath = thumbnailPath; + }); + + await ViewModel.SaveAsync(); + } + } + + private void CoverImageTile_OnPointerEntered(object sender, PointerRoutedEventArgs e) + { + BlackOverlayGrid.Visibility = Visibility.Visible; + } + + private void CoverImageTile_OnPointerExited(object sender, PointerRoutedEventArgs e) + { + BlackOverlayGrid.Visibility = Visibility.Collapsed; + } +} + +public class TrackProperty : BindableBase +{ + private string _name; + + public string Name + { + get => _name; + set => Set(ref _name, value); + } + + private string _value; + + public string Value + { + get => _value; + set => Set(ref _value, value); + } +} \ No newline at end of file diff --git a/Audibly.App/Views/LibraryCardPage.xaml b/Audibly.App/Views/LibraryCardPage.xaml index 21639d7..4db1ecd 100644 --- a/Audibly.App/Views/LibraryCardPage.xaml +++ b/Audibly.App/Views/LibraryCardPage.xaml @@ -203,7 +203,8 @@ + x:Name="LibraryCardView" + ElementPrepared="LibraryCardView_ElementPrepared"> public PlayerViewModel PlayerViewModel => App.PlayerViewModel; + public Frame PageFrame => Frame; + public LibraryCardPage() { InitializeComponent(); @@ -121,4 +124,14 @@ private void TestSentryLoggingButton_OnClick(object sender, RoutedEventArgs e) Severity = InfoBarSeverity.Success }); } + + private void LibraryCardView_ElementPrepared(Microsoft.UI.Xaml.Controls.ItemsRepeater sender, Microsoft.UI.Xaml.Controls.ItemsRepeaterElementPreparedEventArgs args) + { + if (args.Element is AudiobookTile audiobookTile) + { + // Assuming your AudiobookTile UserControl has a property named PageFrame + audiobookTile.PageFrame = this.Frame; + } + } + } \ No newline at end of file