-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add cover preview for EPUB and MOBI files #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -224,6 +224,10 @@ private async void LoadFile(string filePath) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MultiFilePanel.Visibility = Visibility.Collapsed; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| FilePanel.Visibility = Visibility.Visible; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Reset cover | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CoverImage.Source = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CoverBorder.Visibility = Visibility.Collapsed; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SetStatus($"Loading: {fileName}..."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (extension == ".epub") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -242,6 +246,20 @@ private async void LoadFile(string filePath) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Keep filename-based title | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Extract cover (run on background thread) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ = Task.Run(() => _conversionService.ExtractEpubCover(filePath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ContinueWith(t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (t.Result != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Dispatcher.Invoke(() => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CoverImage.Source = t.Result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CoverBorder.Visibility = Visibility.Visible; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, TaskContinuationOptions.OnlyOnRanToCompletion); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Store for Kindle sending (the EPUB itself is the output) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _lastOutputPath = filePath; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _lastTitle = TitleTextBox.Text; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -273,6 +291,20 @@ private async void LoadFile(string filePath) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SetStatus($"Loaded: {fileName}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Extract cover (run on background thread) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ = Task.Run(() => _conversionService.ExtractMobiCover(filePath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .ContinueWith(t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (t.Result != null) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Dispatcher.Invoke(() => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CoverImage.Source = t.Result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CoverBorder.Visibility = Visibility.Visible; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, TaskContinuationOptions.OnlyOnRanToCompletion); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+296
to
+307
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _ = Task.Run(() => _conversionService.ExtractMobiCover(filePath)) | |
| .ContinueWith(t => | |
| { | |
| if (t.Result != null) | |
| { | |
| Dispatcher.Invoke(() => | |
| { | |
| CoverImage.Source = t.Result; | |
| CoverBorder.Visibility = Visibility.Visible; | |
| }); | |
| } | |
| }, TaskContinuationOptions.OnlyOnRanToCompletion); | |
| var coverTask = Task.Run(() => _conversionService.ExtractMobiCover(filePath)); | |
| coverTask.ContinueWith(t => | |
| { | |
| var cover = t.Result; | |
| if (cover != null) | |
| { | |
| Dispatcher.Invoke(() => | |
| { | |
| CoverImage.Source = cover; | |
| CoverBorder.Visibility = Visibility.Visible; | |
| }); | |
| } | |
| }, TaskContinuationOptions.OnlyOnRanToCompletion); | |
| coverTask.ContinueWith(t => | |
| { | |
| // Observe and handle exceptions to avoid unobserved task exceptions | |
| var _ = t.Exception; | |
| Dispatcher.Invoke(() => | |
| { | |
| SetStatus("Failed to extract cover from MOBI file", isError: true); | |
| }); | |
| }, TaskContinuationOptions.OnlyOnFaulted); |
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fire-and-forget tasks can cause exceptions to be silently swallowed and make it difficult to debug issues. Additionally, if these tasks are still running when files are reloaded or the window is closed, they may try to update BookMetadata objects that are no longer in the collection. Consider storing task references and cancelling them when appropriate, or at minimum using proper exception handling in the continuation.
Copilot
AI
Jan 17, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fire-and-forget tasks can cause exceptions to be silently swallowed and make it difficult to debug issues. Additionally, if these tasks are still running when files are reloaded or the window is closed, they may try to update BookMetadata objects that are no longer in the collection. Consider storing task references and cancelling them when appropriate, or at minimum using proper exception handling in the continuation.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| using System.Globalization; | ||
| using System.Windows; | ||
| using System.Windows.Data; | ||
|
|
||
| namespace Booky; | ||
|
|
||
| public class NullToCollapsedConverter : IValueConverter | ||
| { | ||
| public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| { | ||
| return value == null ? Visibility.Collapsed : Visibility.Visible; | ||
| } | ||
|
|
||
| public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) | ||
| { | ||
| throw new NotImplementedException(); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fire-and-forget tasks can cause exceptions to be silently swallowed and make it difficult to debug issues. Additionally, if these tasks are still running when the window is closed or a new file is loaded, they may try to update UI elements that no longer exist or are bound to different data. Consider storing task references and cancelling them when appropriate, or at minimum using proper exception handling in the continuation.