Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 1.2.1

- Enlarged the large PDF/XPS export dialog so every export option is fully visible.
- Added text wrapping and window resizing for improved display scaling compatibility.
- Tightened safe cancellation before finalizing an export, made local-backup copying
cancellable between files, and clarified cancellation behavior.

## 1.2.0

- Improved reliability with a serialized OneNote COM worker, safe cancellation, and bounded connection recovery.
Expand Down
19 changes: 15 additions & 4 deletions Helpers/FileHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ public static BackupAvailability CheckLocalBackupAvailable()
/// <summary>
/// Copies the entire OneNote local backup folder to <paramref name="destPath"/>.
/// </summary>
public static ExportResult CopyLocalBackup(string destPath)
public static ExportResult CopyLocalBackup(
string destPath,
CancellationToken ct = default)
{
var backupPath = GetOneNoteBackupPath();

Expand All @@ -100,10 +102,15 @@ public static ExportResult CopyLocalBackup(string destPath)

try
{
ct.ThrowIfCancellationRequested();
Directory.CreateDirectory(destPath);
CopyDirectory(backupPath, destPath);
CopyDirectory(backupPath, destPath, ct);
return new ExportResult { Success = true, Message = "Local backup copied successfully.", ExportedPath = destPath };
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
return new ExportResult
Expand Down Expand Up @@ -137,20 +144,24 @@ public static void OpenFolder(string path)

// ── private helpers ──────────────────────────────────────────────────────

private static void CopyDirectory(string src, string dst)
private static void CopyDirectory(string src, string dst, CancellationToken ct)
{
ct.ThrowIfCancellationRequested();
Directory.CreateDirectory(dst);

foreach (var file in Directory.GetFiles(src))
{
ct.ThrowIfCancellationRequested();
var dest = Path.Combine(dst, Path.GetFileName(file));
File.Copy(file, dest, overwrite: true);
ct.ThrowIfCancellationRequested();
}

foreach (var dir in Directory.GetDirectories(src))
{
ct.ThrowIfCancellationRequested();
var dest = Path.Combine(dst, Path.GetFileName(dir));
CopyDirectory(dir, dest);
CopyDirectory(dir, dest, ct);
}
}
}
17 changes: 13 additions & 4 deletions MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ private async void ExportButton_Click(object sender, RoutedEventArgs e)
try
{
if (format == "localbackup")
await RunLocalBackupAsync(destPath);
await RunLocalBackupAsync(destPath, _exportCts.Token);
else
{
var prepared = await ApplyRenderedExportGuardAsync(
Expand Down Expand Up @@ -565,8 +565,13 @@ private void CancelButton_Click(object sender, RoutedEventArgs e)
{
if (!_exportInProgress) return;

string cancellationDetails = _isLocalBackupMode
? "The export will stop safely after the current file copy finishes."
: "The export will stop safely without closing OneNote. If OneNote is currently " +
"rendering, cancellation completes as soon as OneNote returns control.";

var confirm = MessageBox.Show(
"Do you really want to cancel the export?\n\nThe current export will stop without closing OneNote.",
$"Do you really want to cancel the export?\n\n{cancellationDetails}",
"Cancel Export",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);
Expand All @@ -580,13 +585,13 @@ private void CancelButton_Click(object sender, RoutedEventArgs e)

// ── Export implementations ───────────────────────────────────────────────

private async Task RunLocalBackupAsync(string destPath)
private async Task RunLocalBackupAsync(string destPath, CancellationToken ct)
{
ShowProgress("Copying local backup files...");

try
{
var result = await Task.Run(() => FileHelper.CopyLocalBackup(destPath));
var result = await Task.Run(() => FileHelper.CopyLocalBackup(destPath, ct), ct);
HideProgress();

if (result.Success)
Expand All @@ -599,6 +604,10 @@ private async Task RunLocalBackupAsync(string destPath)
ShowStatus($"❌ Export failed: {result.Message}", StatusKind.Error);
}
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
HideProgress();
Expand Down
2 changes: 1 addition & 1 deletion OneNoteExporter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<AssemblyName>OneNoteExporter</AssemblyName>
<RootNamespace>OneNoteExporter</RootNamespace>
<Version>1.2.0</Version>
<Version>1.2.1</Version>
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
A Windows desktop application to export OneNote notebooks to portable formats.
Talks directly to OneNote Desktop via the COM API.

![version](https://img.shields.io/badge/version-1.2.0-blueviolet?style=flat-square)
![version](https://img.shields.io/badge/version-1.2.1-blueviolet?style=flat-square)
![platform](https://img.shields.io/badge/platform-Windows%2010%2F11-0078D7?style=flat-square&logo=windows&logoColor=white)
![license](https://img.shields.io/badge/license-MIT-brightgreen?style=flat-square)
![built with](https://img.shields.io/badge/built%20with-.NET%2010%20%2F%20WPF-512BD4?style=flat-square&logo=dotnet&logoColor=white)
Expand Down Expand Up @@ -40,7 +40,7 @@ checksum are available as workflow artifacts for 14 days.
To publish a release:

1. Update `<Version>` in `OneNoteExporter.csproj` and commit the change.
2. Create and push a matching tag, for example `v1.2.0`.
2. Create and push a matching tag, for example `v1.2.1`.
3. GitHub Actions builds the installer, creates the GitHub release with generated notes, and
uploads the installer plus checksum automatically.

Expand Down
87 changes: 50 additions & 37 deletions RenderedExportWarningWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Icon="icon.ico"
Title="Large PDF/XPS export"
Width="560" Height="430"
MinWidth="520" MinHeight="410"
ResizeMode="NoResize"
Width="700" Height="555"
MinWidth="620" MinHeight="520"
ResizeMode="CanResizeWithGrip"
ShowInTaskbar="False"
WindowStartupLocation="CenterOwner"
Background="{StaticResource BgPage}">
Expand All @@ -29,6 +29,7 @@
x:Name="TitleText"
FontSize="18"
FontWeight="Bold"
TextWrapping="Wrap"
Foreground="{StaticResource PrimaryBlue}"/>

<TextBlock Grid.Row="1"
Expand All @@ -51,42 +52,54 @@
Foreground="{StaticResource WarningFg}"/>
</Border>

<StackPanel Grid.Row="3" Margin="0,16,0,0">
<Button x:Name="SectionsButton"
Style="{StaticResource PrimaryButtonStyle}"
IsDefault="True"
HorizontalContentAlignment="Left"
Padding="14,10"
Click="SectionsButton_Click">
<StackPanel>
<TextBlock Text="Recommended: Export as individual sections"
FontWeight="SemiBold"/>
<TextBlock x:Name="SectionsDescriptionText"
Margin="0,3,0,0"
FontSize="11"
FontWeight="Normal"
TextWrapping="Wrap"/>
</StackPanel>
</Button>
<ScrollViewer Grid.Row="3"
Margin="0,16,0,0"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Disabled">
<StackPanel>
<Button x:Name="SectionsButton"
Style="{StaticResource PrimaryButtonStyle}"
IsDefault="True"
HorizontalContentAlignment="Left"
Padding="14,10"
Click="SectionsButton_Click">
<StackPanel>
<TextBlock Text="Recommended: Export as individual sections"
FontWeight="SemiBold"/>
<TextBlock x:Name="SectionsDescriptionText"
Margin="0,3,0,0"
FontSize="11"
FontWeight="Normal"
TextWrapping="Wrap"/>
</StackPanel>
</Button>

<Button x:Name="OneNotePackageButton"
Content="Create a complete OneNote package (.onepkg) instead"
Style="{StaticResource GrayButtonStyle}"
Margin="0,8,0,0"
HorizontalContentAlignment="Left"
Padding="14,9"
Click="OneNotePackageButton_Click"/>
<Button x:Name="OneNotePackageButton"
Style="{StaticResource GrayButtonStyle}"
Margin="0,8,0,0"
HorizontalContentAlignment="Left"
Padding="14,9"
Click="OneNotePackageButton_Click">
<TextBlock x:Name="OneNotePackageButtonText"
Text="Create a complete OneNote package (.onepkg) instead"
TextWrapping="Wrap"/>
</Button>

<Button x:Name="WholeNotebookButton"
Margin="0,8,0,0"
HorizontalAlignment="Left"
Padding="0"
Background="Transparent"
BorderThickness="0"
Foreground="{StaticResource TextSecondary}"
Cursor="Hand"
Click="WholeNotebookButton_Click"/>
</StackPanel>
<Button x:Name="WholeNotebookButton"
Margin="0,8,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Padding="0"
Background="Transparent"
BorderThickness="0"
Foreground="{StaticResource TextSecondary}"
Cursor="Hand"
Click="WholeNotebookButton_Click">
<TextBlock x:Name="WholeNotebookButtonText"
TextWrapping="Wrap"/>
</Button>
</StackPanel>
</ScrollViewer>

<Button Grid.Row="4"
Content="Cancel"
Expand Down
4 changes: 2 additions & 2 deletions RenderedExportWarningWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ public RenderedExportWarningWindow(
$"The app loads all exportable sections automatically and creates one {formatName} " +
"file per section. Locked sections are not included. " +
"Smaller render jobs are significantly more reliable.";
WholeNotebookButton.Content =
WholeNotebookButtonText.Text =
$"Try the whole {formatName} export anyway (may fail for large notebooks)";

if (hasSelectedSections)
{
OneNotePackageButton.IsEnabled = false;
OneNotePackageButton.Content =
OneNotePackageButtonText.Text =
"OneNote package requires no individually selected sections";
OneNotePackageButton.ToolTip =
"Cancel, deselect the individual sections, and try again to create a complete package.";
Expand Down
1 change: 1 addition & 0 deletions Services/OneNoteComWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ private async Task<ExportResult> ExportAsync(
}

progress?.Report("Finalizing export and replacing the previous backup...");
ct.ThrowIfCancellationRequested();
var finalResult = OneNoteService.FinalizeExport(pending, result);
finalResult.AttemptCount = attempt;
finalResult.RecoveredAfterRetry = attempt > 1;
Expand Down
2 changes: 1 addition & 1 deletion innosetup.iss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#define MyAppName "OneNoteBackupExporter"
#ifndef MyAppVersion
#define MyAppVersion "1.2.0"
#define MyAppVersion "1.2.1"
#endif
#define MyAppPublisher "JLI Software"
#define MyAppURL "https://github.com/jli-software/OneNoteBackupExporter"
Expand Down
2 changes: 1 addition & 1 deletion release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
set -euo pipefail

if [[ $# -ne 1 ]]; then
echo "Usage: $0 <version> (for example: $0 1.2.0)"
echo "Usage: $0 <version> (for example: $0 1.2.1)"
exit 1
fi

Expand Down
Loading