Skip to content

Commit ddda03f

Browse files
authored
Fix installer logo handling and update tests (#128)
1 parent 45ee191 commit ddda03f

File tree

9 files changed

+52
-41
lines changed

9 files changed

+52
-41
lines changed

src/DotnetPackaging.Exe.Installer/Core/BrandingLogoFactory.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
using Avalonia.Media;
12
using Avalonia.Media.Imaging;
23
using Zafiro.DivineBytes;
34

45
namespace DotnetPackaging.Exe.Installer.Core;
56

67
internal static class BrandingLogoFactory
78
{
8-
public static IBitmap? FromBytes(IByteSource? bytes)
9+
public static IImage? FromBytes(IByteSource? bytes)
910
{
1011
if (bytes is null)
1112
{

src/DotnetPackaging.Exe.Installer/Core/MetadataFilePayload.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using CSharpFunctionalExtensions;
33
using Zafiro.DivineBytes;
44
using Zafiro.ProgressReporting;
5+
using Path = System.IO.Path;
56

67
namespace DotnetPackaging.Exe.Installer.Core;
78

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
using System.Reactive;
2-
using Avalonia.Media.Imaging;
2+
using Avalonia.Media;
33
using CSharpFunctionalExtensions;
44
using DotnetPackaging.Exe.Installer.Core;
55
using Reactive.Bindings;
@@ -11,7 +11,7 @@ namespace DotnetPackaging.Exe.Installer.Installation.Wizard.Welcome;
1111
public interface IWelcomeViewModel
1212
{
1313
Reactive.Bindings.ReactiveProperty<InstallerMetadata?> Metadata { get; }
14-
ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; }
15-
ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
16-
ReadOnlyReactivePropertySlim<IBitmap?> Logo { get; }
14+
ReactiveUI.ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; }
15+
ReactiveUI.ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
16+
ReadOnlyReactivePropertySlim<IImage?> Logo { get; }
1717
}

src/DotnetPackaging.Exe.Installer/Installation/Wizard/Welcome/WelcomeViewModel.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Reactive;
22
using System.Reactive.Linq;
3+
using Avalonia.Media;
34
using Avalonia.Media.Imaging;
45
using CSharpFunctionalExtensions;
56
using DotnetPackaging.Exe.Installer.Core;
@@ -21,25 +22,25 @@ public sealed class WelcomeViewModel : ReactiveValidationObject, IWelcomeViewMod
2122
public WelcomeViewModel(IInstallerPayload payload)
2223
{
2324
this.payload = payload;
24-
LoadMetadata = ReactiveCommand.CreateFromTask(() => this.payload.GetMetadata());
25-
Metadata = new ReactiveProperty<InstallerMetadata?>(LoadMetadata.Successes());
25+
LoadMetadata = ReactiveUI.ReactiveCommand.CreateFromTask(() => this.payload.GetMetadata());
26+
Metadata = new Reactive.Bindings.ReactiveProperty<InstallerMetadata?>(LoadMetadata.Successes());
2627
this.ValidationRule(model => model.Metadata.Value, m => m is not null, "Metadata is required");
2728

28-
LoadLogo = ReactiveCommand.CreateFromTask(() => payload.GetLogo());
29+
LoadLogo = ReactiveUI.ReactiveCommand.CreateFromTask(() => payload.GetLogo());
2930

3031
Logo = LoadLogo
3132
.Successes()
32-
.Select(logoBytes => logoBytes.Match(BrandingLogoFactory.FromBytes, () => (IBitmap?)null))
33+
.Select(logoBytes => logoBytes.Match(BrandingLogoFactory.FromBytes, () => (IImage?)null))
3334
.ToReadOnlyReactivePropertySlim();
3435
}
3536

36-
public ReactiveProperty<InstallerMetadata?> Metadata { get; }
37+
public Reactive.Bindings.ReactiveProperty<InstallerMetadata?> Metadata { get; }
3738

38-
public ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; }
39+
public ReactiveUI.ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; }
3940

40-
public ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
41+
public ReactiveUI.ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
4142

42-
public ReadOnlyReactivePropertySlim<IBitmap?> Logo { get; }
43+
public ReadOnlyReactivePropertySlim<IImage?> Logo { get; }
4344

4445
public IObservable<bool> IsValid => this.IsValid();
4546
}
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using System;
22
using System.Reactive;
3+
using System.Reactive.Linq;
4+
using Avalonia.Media;
35
using Avalonia.Media.Imaging;
46
using CSharpFunctionalExtensions;
57
using DotnetPackaging.Exe.Installer.Core;
68
using Reactive.Bindings;
79
using Reactive.Bindings.Extensions;
810
using ReactiveUI;
11+
using Zafiro.CSharpFunctionalExtensions;
912
using Zafiro.DivineBytes;
1013

1114
namespace DotnetPackaging.Exe.Installer.Installation.Wizard.Welcome;
@@ -16,33 +19,33 @@ public class WelcomeViewModelMock : IWelcomeViewModel
1619

1720
public WelcomeViewModelMock()
1821
{
19-
Metadata = new ReactiveProperty<InstallerMetadata>(new InstallerMetadata(
22+
Metadata = new Reactive.Bindings.ReactiveProperty<InstallerMetadata?>(new InstallerMetadata(
2023
"com.example.app",
2124
"Example App",
2225
"1.0.0",
2326
"Example, Inc.",
2427
Description: "This is an example app. It does nothing. It's just a demo.",
2528
HasLogo: true));
2629

27-
LoadLogo = ReactiveCommand.Create(() => Result.Success(Maybe<IByteSource>.From(ByteSource.FromBytes(SampleLogo))));
30+
LoadLogo = ReactiveUI.ReactiveCommand.Create(() => Result.Success(Maybe<IByteSource>.From(ByteSource.FromBytes(SampleLogo))));
2831

2932
Logo = LoadLogo
3033
.Successes()
31-
.Select(logoBytes => logoBytes.Match(BrandingLogoFactory.FromBytes, () => (IBitmap?)null))
34+
.Select(logoBytes => logoBytes.Match(BrandingLogoFactory.FromBytes, () => (IImage?)null))
3235
.ToReadOnlyReactivePropertySlim();
3336
}
3437

35-
public ReactiveProperty<InstallerMetadata?> Metadata { get; }
38+
public Reactive.Bindings.ReactiveProperty<InstallerMetadata?> Metadata { get; }
3639

37-
public ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; } = ReactiveCommand.Create(() => Result.Success(new InstallerMetadata(
40+
public ReactiveUI.ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; } = ReactiveUI.ReactiveCommand.Create(() => Result.Success(new InstallerMetadata(
3841
"com.example.app",
3942
"Example App",
4043
"1.0.0",
4144
"Example, Inc.",
4245
Description: "This is an example app. It does nothing. It's just a demo.",
4346
HasLogo: true)));
4447

45-
public ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
48+
public ReactiveUI.ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
4649

47-
public ReadOnlyReactivePropertySlim<IBitmap?> Logo { get; }
50+
public ReadOnlyReactivePropertySlim<IImage?> Logo { get; }
4851
}

src/DotnetPackaging.Exe.Installer/Uninstallation/Wizard/Welcome/UninstallWelcomeViewModel.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Reactive;
22
using System.Reactive.Linq;
3+
using Avalonia.Media;
34
using Avalonia.Media.Imaging;
45
using CSharpFunctionalExtensions;
56
using DotnetPackaging.Exe.Installer.Core;
@@ -21,25 +22,25 @@ public sealed class UninstallWelcomeViewModel : ReactiveValidationObject, IValid
2122
public UninstallWelcomeViewModel(IInstallerPayload payload)
2223
{
2324
this.payload = payload;
24-
LoadMetadata = ReactiveCommand.CreateFromTask(() => this.payload.GetMetadata());
25-
Metadata = new ReactiveProperty<InstallerMetadata?>(LoadMetadata.Successes());
25+
LoadMetadata = ReactiveUI.ReactiveCommand.CreateFromTask(() => this.payload.GetMetadata());
26+
Metadata = new Reactive.Bindings.ReactiveProperty<InstallerMetadata?>(LoadMetadata.Successes());
2627
this.ValidationRule(model => model.Metadata.Value, m => m is not null, "Metadata is required");
2728

28-
LoadLogo = ReactiveCommand.CreateFromTask(() => payload.GetLogo());
29+
LoadLogo = ReactiveUI.ReactiveCommand.CreateFromTask(() => payload.GetLogo());
2930

3031
Logo = LoadLogo
3132
.Successes()
32-
.Select(logoBytes => logoBytes.Match(BrandingLogoFactory.FromBytes, () => (IBitmap?)null))
33+
.Select(logoBytes => logoBytes.Match(BrandingLogoFactory.FromBytes, () => (IImage?)null))
3334
.ToReadOnlyReactivePropertySlim();
3435
}
3536

36-
public ReactiveProperty<InstallerMetadata?> Metadata { get; }
37+
public Reactive.Bindings.ReactiveProperty<InstallerMetadata?> Metadata { get; }
3738

38-
public ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; }
39+
public ReactiveUI.ReactiveCommand<Unit, Result<InstallerMetadata>> LoadMetadata { get; }
3940

40-
public ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
41+
public ReactiveUI.ReactiveCommand<Unit, Result<Maybe<IByteSource>>> LoadLogo { get; }
4142

42-
public ReadOnlyReactivePropertySlim<IBitmap?> Logo { get; }
43+
public ReadOnlyReactivePropertySlim<IImage?> Logo { get; }
4344

4445
public IObservable<bool> IsValid => this.IsValid();
4546
}

src/DotnetPackaging.Exe/ExePackagingService.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -579,12 +579,14 @@ private static async Task<Result<string>> CreateInstallerPayloadZip(string publi
579579
await src.CopyToAsync(dst);
580580
}
581581

582-
foreach (var bytes in logoBytes)
583-
{
584-
var logoEntry = zip.CreateEntry(BrandingLogoEntry, CompressionLevel.NoCompression);
585-
await using var logoStream = logoEntry.Open();
586-
await logoStream.WriteAsync(bytes, 0, bytes.Length);
587-
}
582+
await logoBytes.Match(
583+
async bytes =>
584+
{
585+
var logoEntry = zip.CreateEntry(BrandingLogoEntry, CompressionLevel.NoCompression);
586+
await using var logoStream = logoEntry.Open();
587+
await logoStream.WriteAsync(bytes, 0, bytes.Length);
588+
},
589+
() => Task.CompletedTask);
588590

589591
return Result.Success(zipPath);
590592
}

src/DotnetPackaging.Exe/SimpleExePacker.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,13 @@ private static async Task CreatePayloadZip(string zipPath, string publishDir, In
8888
await src.CopyToAsync(dst);
8989
}
9090

91-
foreach (var bytes in logoBytes)
92-
{
93-
var logoEntry = zip.CreateEntry(BrandingLogoEntry, CompressionLevel.NoCompression);
94-
await using var stream = logoEntry.Open();
95-
await stream.WriteAsync(bytes, 0, bytes.Length);
96-
}
91+
await logoBytes.Match(
92+
async bytes =>
93+
{
94+
var logoEntry = zip.CreateEntry(BrandingLogoEntry, CompressionLevel.NoCompression);
95+
await using var stream = logoEntry.Open();
96+
await stream.WriteAsync(bytes, 0, bytes.Length);
97+
},
98+
() => Task.CompletedTask);
9799
}
98100
}

test/DotnetPackaging.Exe.Tests/ExeSfxEndToEndTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public async Task From_project_builds_setup_with_expected_metadata_when_external
2727

2828
// Act: build the SFX installer from the project
2929
var service = new ExePackagingService();
30-
var result = await service.BuildFromProject(new FileInfo(projectPath), "win-x64", true, "Release", true, false, new FileInfo(outputExe), new Options(), vendor: null, stubFile: null);
30+
var result = await service.BuildFromProject(new FileInfo(projectPath), "win-x64", true, "Release", true, false, new FileInfo(outputExe), new Options(), vendor: null, stubFile: null, setupLogo: null);
3131
result.IsSuccess.Should().BeTrue(result.IsFailure ? result.Error : string.Empty);
3232

3333
// Run the produced installer with the env hook to dump metadata and exit

0 commit comments

Comments
 (0)