From 6bf60c2f42e8341392888d470d385a6171f2eb51 Mon Sep 17 00:00:00 2001 From: kn0wn8 Date: Sat, 22 Aug 2026 06:06:21 +0800 Subject: [PATCH 1/2] fix(search): bundle pinned Everything SDK DLL --- .gitignore | 3 +- .../EverythingSdkBootstrapperTests.cs | 35 ++++++++++++------ .../EasyExtractCrossPlatform.csproj | 8 ++++ .../Services/EverythingSdkBootstrapper.cs | 34 +++-------------- .../ThirdParty/EverythingSdk/Everything64.dll | Bin 0 -> 91304 bytes .../ThirdParty/EverythingSdk/README.md | 9 +++++ 6 files changed, 48 insertions(+), 41 deletions(-) create mode 100644 EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/Everything64.dll create mode 100644 EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/README.md diff --git a/.gitignore b/.gitignore index d9fe42b..909f9f0 100644 --- a/.gitignore +++ b/.gitignore @@ -824,6 +824,7 @@ FodyWeavers.xml.bak *.exe *.pdb *.dll +!EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/Everything64.dll *.dylib # Other @@ -832,4 +833,4 @@ FodyWeavers.xml.bak *.psess *.vsp *.vspx -*.sap \ No newline at end of file +*.sap diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Services/EverythingSdkBootstrapperTests.cs b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Services/EverythingSdkBootstrapperTests.cs index 3e212ec..19b6116 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Services/EverythingSdkBootstrapperTests.cs +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Services/EverythingSdkBootstrapperTests.cs @@ -118,7 +118,8 @@ public async Task EnsureDllForTestsAsync_ReusesValidExistingDllWithoutRewrite() EverythingSdkBootstrapper.ConfigureForTests( appDataPathOverride: () => appDataPath, validateDllHashOverride: (path, _) => - string.Equals(Path.GetFullPath(path), Path.GetFullPath(dllPath), StringComparison.OrdinalIgnoreCase)); + string.Equals(Path.GetFullPath(path), Path.GetFullPath(dllPath), StringComparison.OrdinalIgnoreCase), + localProbeDirectoriesOverride: () => new[] { sdkDirectory }); var resolvedPath = await EverythingSdkBootstrapper.EnsureDllForTestsAsync(); var currentWriteTime = File.GetLastWriteTimeUtc(dllPath); @@ -132,7 +133,7 @@ public async Task EnsureDllForTestsAsync_ReusesValidExistingDllWithoutRewrite() } [Fact] - public async Task EnsureDllForTestsAsync_SerializesConcurrentReuseWhileValidationRetries() + public async Task EnsureDllForTestsAsync_SerializesConcurrentBundledDllResolution() { if (!OperatingSystem.IsWindows()) return; @@ -160,11 +161,10 @@ public async Task EnsureDllForTestsAsync_SerializesConcurrentReuseWhileValidatio StringComparison.OrdinalIgnoreCase)) return true; - if (Interlocked.Increment(ref validationAttempts) == 1) - throw new SharingViolationIOException(); - + Interlocked.Increment(ref validationAttempts); return true; - }); + }, + localProbeDirectoriesOverride: () => new[] { sdkDirectory }); var callers = Enumerable.Range(0, 4) .Select(_ => EverythingSdkBootstrapper.EnsureDllForTestsAsync()) @@ -173,13 +173,13 @@ public async Task EnsureDllForTestsAsync_SerializesConcurrentReuseWhileValidatio var resolvedPaths = await Task.WhenAll(callers); Assert.All(resolvedPaths, path => Assert.Equal(dllPath, path, true)); - Assert.True(validationAttempts >= 2); + Assert.Equal(1, validationAttempts); Directory.Delete(root, true); } [Fact] - public async Task EnsureDllForTestsAsync_CleansOrphanedTemporaryDlls() + public async Task EnsureDllForTestsAsync_LeavesUnrelatedTemporaryFilesUntouched() { if (!OperatingSystem.IsWindows()) return; @@ -214,12 +214,13 @@ public async Task EnsureDllForTestsAsync_CleansOrphanedTemporaryDlls() return string.Equals(Path.GetFullPath(path), Path.GetFullPath(dllPath), StringComparison.OrdinalIgnoreCase); - }); + }, + localProbeDirectoriesOverride: () => new[] { sdkDirectory }); var resolvedPath = await EverythingSdkBootstrapper.EnsureDllForTestsAsync(); Assert.Equal(dllPath, resolvedPath, true); - Assert.False(File.Exists(orphanedTempPath)); + Assert.True(File.Exists(orphanedTempPath)); Directory.Delete(root, true); } @@ -291,6 +292,18 @@ public void IsTransientDownloadFailure_TruncatedHttpResponse_IsRetryable() Assert.True(EverythingSdkBootstrapper.IsTransientDownloadFailure(exception)); } + [Fact] + public async Task EnsureDllForTestsAsync_MissingBundledDll_DoesNotDownload() + { + if (!OperatingSystem.IsWindows()) + return; + + EverythingSdkBootstrapper.ResetForTests(); + EverythingSdkBootstrapper.ConfigureForTests(localProbeDirectoriesOverride: Array.Empty); + + await Assert.ThrowsAsync(() => EverythingSdkBootstrapper.EnsureDllForTestsAsync()); + } + [Fact] public async Task EnsureDllForTestsAsync_FallsBackToDllNextToTheExecutable() { @@ -368,4 +381,4 @@ public SharingViolationIOException() : base("Simulated sharing violation") HResult = SharingViolationHResult; } } -} \ No newline at end of file +} diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj index f78d31c..f631468 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj @@ -48,6 +48,14 @@ + + + + Everything64.dll + PreserveNewest + PreserveNewest + + diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/Services/EverythingSdkBootstrapper.cs b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/Services/EverythingSdkBootstrapper.cs index d31c357..85d756f 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/Services/EverythingSdkBootstrapper.cs +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/Services/EverythingSdkBootstrapper.cs @@ -13,6 +13,7 @@ internal static class EverythingSdkBootstrapper private static readonly TimeSpan DllPromotionInitialDelay = TimeSpan.FromMilliseconds(40); private static readonly TimeSpan DownloadInitialRetryDelay = TimeSpan.FromMilliseconds(500); + // Legacy helpers and their tests remain below, but EnsureDllAsync no longer calls the network path. private static readonly Uri SdkDownloadUri = new("https://www.voidtools.com/Everything-SDK.zip"); private static readonly HttpClient HttpClient = new(); private static readonly SemaphoreSlim DllInstallGate = new(1, 1); @@ -24,7 +25,7 @@ internal static class EverythingSdkBootstrapper private static readonly IReadOnlyDictionary ExpectedDllHashes = new Dictionary(StringComparer.OrdinalIgnoreCase) { - ["Everything64.dll"] = "C7AB8B47F7DD4C41AA735F4BA40B35AD5460A86FA7ABE0C94383F12BCE33BFB6", + ["Everything64.dll"] = "81B5BE18126ACD2C2B913F8F4A821E476B18393CDD3DEBD03387C50AFD8DB88F", ["Everything32.dll"] = "C28CD066AF36CAE4403A9933847AFF01DB928787D86751F014A1FA60D8B97FDA" }; @@ -105,42 +106,17 @@ private static async Task EnsureDllAsync() return _everythingDllPath; } - var appData = (_appDataPathOverride?.Invoke() ?? - Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)).Trim(); - var sdkDirectory = Path.Combine(appData, "EasyExtract", "ThirdParty", "EverythingSdk"); - Directory.CreateDirectory(sdkDirectory); - - var dllPath = Path.Combine(sdkDirectory, TargetDllFileName); - await DllInstallGate.WaitAsync().ConfigureAwait(false); try { - CleanupOrphanedTemporaryDlls(sdkDirectory); - - if (_everythingDllPath is { Length: > 0 } existingPath && File.Exists(existingPath)) - { - LoggingService.LogInformation($"Everything SDK DLL already present at '{existingPath}'."); - return existingPath; - } - - if (await TryReuseExistingDllAsync(dllPath).ConfigureAwait(false)) - { - _everythingDllPath = dllPath; - return dllPath; - } - - // The error messages tell users to drop the SDK DLL next to the executable, so honour - // that before going to the network. It is also the only way out on an offline machine. if (TryUseLocallyShippedDll(out var localDllPath)) { _everythingDllPath = localDllPath; return localDllPath; } - await DownloadDllWithRetryAsync(sdkDirectory, dllPath).ConfigureAwait(false); - - _everythingDllPath = dllPath; - return dllPath; + throw new FileNotFoundException( + $"Bundled {TargetDllFileName} was not found next to the EasyExtract executable."); } finally { @@ -594,4 +570,4 @@ internal static bool ValidateDllHashForTests(string dllPath, bool deleteOnMismat { return ValidateDllHash(dllPath, deleteOnMismatch); } -} \ No newline at end of file +} diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/Everything64.dll b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/Everything64.dll new file mode 100644 index 0000000000000000000000000000000000000000..1df08c3a1a53096fc19828a0241b9583327dc02a GIT binary patch literal 91304 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%0A#irem<)Nx|JnC+@<$kFlFKs5)hhYbbn-fte5c}s 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≧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 literal 0 HcmV?d00001 diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/README.md b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/README.md new file mode 100644 index 0000000..b18c0ba --- /dev/null +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/ThirdParty/EverythingSdk/README.md @@ -0,0 +1,9 @@ +# Everything SDK runtime + +`Everything64.dll` is bundled next to the Windows executable at build and publish time. +It is the x64 file from the Voidtools Everything SDK archive verified on 2026-08-22. + +- SHA-256: `81B5BE18126ACD2C2B913F8F4A821E476B18393CDD3DEBD03387C50AFD8DB88F` +- Size: 91,304 bytes + +The application validates this exact hash and does not download an SDK DLL at runtime. From 4872e6ecc3c7caac6e474943028317549ac2680a Mon Sep 17 00:00:00 2001 From: kn0wn8 Date: Sun, 23 Aug 2026 16:05:25 +0800 Subject: [PATCH 2/2] fix(ui): compact and lock the main window --- .../Utilities/ResponsiveWindowHelperTests.cs | 39 +++++++++ .../EasyExtractCrossPlatform.csproj | 1 + .../MainWindow.Appearance.cs | 17 +++- .../MainWindow.SettingsAndLifecycle.cs | 67 ++++----------- .../EasyExtractCrossPlatform/MainWindow.axaml | 85 ++++++++++++++----- .../MainWindow.axaml.cs | 11 ++- .../Utilities/ResponsiveWindowHelper.cs | 4 +- 7 files changed, 145 insertions(+), 79 deletions(-) create mode 100644 EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Utilities/ResponsiveWindowHelperTests.cs diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Utilities/ResponsiveWindowHelperTests.cs b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Utilities/ResponsiveWindowHelperTests.cs new file mode 100644 index 0000000..12762c1 --- /dev/null +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform.Tests/Utilities/ResponsiveWindowHelperTests.cs @@ -0,0 +1,39 @@ +using Avalonia.Controls; +using Avalonia.Threading; +using EasyExtractCrossPlatform.Tests.Support; +using EasyExtractCrossPlatform.Utilities; +using Xunit; + +namespace EasyExtractCrossPlatform.Tests.Utilities; + +public sealed class ResponsiveWindowHelperTests +{ + [Fact] + public Task Enable_WhenWindowWidthChanges_UpdatesLayoutClasses() + { + return HeadlessUi.RunAsync(() => + { + var window = new Window + { + Width = 1700, + Height = 900 + }; + using var subscription = ResponsiveWindowHelper.Enable(window); + + window.Show(); + Assert.Contains("wide", window.Classes); + + window.Width = 1000; + Dispatcher.UIThread.RunJobs(); + Assert.Contains("cozy", window.Classes); + Assert.DoesNotContain("wide", window.Classes); + + window.Width = 900; + Dispatcher.UIThread.RunJobs(); + Assert.Contains("compact", window.Classes); + Assert.DoesNotContain("cozy", window.Classes); + + window.Close(); + }); + } +} diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj index f631468..4eec19d 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/EasyExtractCrossPlatform.csproj @@ -47,6 +47,7 @@ + diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.Appearance.cs b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.Appearance.cs index aabbcdf..9b0d47d 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.Appearance.cs +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.Appearance.cs @@ -171,6 +171,21 @@ private void ApplyResponsiveLayouts() if (_heroGrid is not null) _heroGrid.ColumnDefinitions = new ColumnDefinitions(isCompact ? "*" : "Auto,*"); + if (_startExtractionHeaderContent is not null) + { + _startExtractionHeaderContent.ColumnDefinitions = + new ColumnDefinitions(isCompact ? "*" : "Auto,*"); + _startExtractionHeaderContent.RowDefinitions = + new RowDefinitions(isCompact ? "Auto,Auto" : "Auto"); + } + + if (_queueHeaderGrid is not null) + { + _queueHeaderGrid.ColumnDefinitions = + new ColumnDefinitions(isCompact ? "Auto,*" : "Auto,*,Auto"); + _queueHeaderGrid.RowDefinitions = new RowDefinitions(isCompact ? "Auto,Auto" : "Auto"); + } + if (_footerGrid is not null) { if (isCompact) @@ -300,4 +315,4 @@ private IBrush ResolveDefaultBackgroundBrush() return Background ?? new SolidColorBrush(Colors.Black); } -} \ No newline at end of file +} diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.SettingsAndLifecycle.cs b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.SettingsAndLifecycle.cs index f5e1dad..4282acf 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.SettingsAndLifecycle.cs +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.SettingsAndLifecycle.cs @@ -16,24 +16,8 @@ private void ApplyWindowPlacement(AppSettings settings) if (sharedPlacement is not null) { ApplyWindowPlacementState(sharedPlacement); - return; } - - var savedWidth = settings.WindowWidth; - var savedHeight = settings.WindowHeight; - - if (savedWidth.HasValue && savedWidth.Value > 0 && !double.IsNaN(savedWidth.Value)) - Width = savedWidth.Value; - - if (savedHeight.HasValue && savedHeight.Value > 0 && !double.IsNaN(savedHeight.Value)) - Height = savedHeight.Value; - - if (savedWidth.HasValue && savedHeight.HasValue && - savedWidth.Value > 0 && savedHeight.Value > 0 && - !double.IsNaN(savedWidth.Value) && !double.IsNaN(savedHeight.Value)) - _lastNormalSize = new Size(savedWidth.Value, savedHeight.Value); - - if (settings.WindowPositionX.HasValue && settings.WindowPositionY.HasValue) + else if (settings.WindowPositionX.HasValue && settings.WindowPositionY.HasValue) { var requestedPosition = new PixelPoint(settings.WindowPositionX.Value, settings.WindowPositionY.Value); var adjustedPosition = EnsureWindowIsVisible(requestedPosition, new Size(Width, Height)); @@ -41,35 +25,11 @@ private void ApplyWindowPlacement(AppSettings settings) _lastNormalPosition = adjustedPosition; } - var restoredState = settings.WindowState == WindowState.Minimized - ? WindowState.Normal - : settings.WindowState; - - WindowState = Enum.IsDefined(typeof(WindowState), restoredState) - ? restoredState - : WindowState.Normal; - - CaptureCurrentBoundsIfNormal(); + EnforceFixedWindowSize(); } private void ApplyWindowPlacementState(WindowPlacementService.WindowPlacementState placement) { - if (placement.Width.HasValue && placement.Width.Value > 0 && !double.IsNaN(placement.Width.Value)) - { - Width = placement.Width.Value; - _settings.WindowWidth = placement.Width.Value; - } - - if (placement.Height.HasValue && placement.Height.Value > 0 && !double.IsNaN(placement.Height.Value)) - { - Height = placement.Height.Value; - _settings.WindowHeight = placement.Height.Value; - } - - if (placement.Width.HasValue && placement.Height.HasValue && - placement.Width.Value > 0 && placement.Height.Value > 0) - _lastNormalSize = new Size(placement.Width.Value, placement.Height.Value); - if (placement.PositionX.HasValue && placement.PositionY.HasValue) { var requestedPosition = new PixelPoint(placement.PositionX.Value, placement.PositionY.Value); @@ -80,15 +40,20 @@ private void ApplyWindowPlacementState(WindowPlacementService.WindowPlacementSta _settings.WindowPositionY = adjustedPosition.Y; } - var restoredState = placement.WindowState == WindowState.Minimized - ? WindowState.Normal - : placement.WindowState; + } - if (Enum.IsDefined(typeof(WindowState), restoredState)) - { - WindowState = restoredState; - _settings.WindowState = restoredState; - } + private void EnforceFixedWindowSize() + { + WindowState = WindowState.Normal; + Width = FixedWindowWidth; + Height = FixedWindowHeight; + _lastNormalSize = new Size(FixedWindowWidth, FixedWindowHeight); + _settings.WindowWidth = FixedWindowWidth; + _settings.WindowHeight = FixedWindowHeight; + _settings.WindowState = WindowState.Normal; + + if (_lastNormalPosition.HasValue) + Position = EnsureWindowIsVisible(_lastNormalPosition.Value, _lastNormalSize.Value); CaptureCurrentBoundsIfNormal(); } @@ -270,4 +235,4 @@ private async void DashboardButton_OnClick(object? sender, RoutedEventArgs e) } } } -} \ No newline at end of file +} diff --git a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.axaml b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.axaml index a36dfec..eaad8f4 100644 --- a/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.axaml +++ b/EasyExtractUnitypackageRework/EasyExtractCrossPlatform/MainWindow.axaml @@ -12,6 +12,14 @@ x:Class="EasyExtractCrossPlatform.MainWindow" Title="{loc:Loc MainWindow_Easyextract}" Icon="/Assets/logo-flat.ico" + Width="1207" + Height="918" + MinWidth="1207" + MaxWidth="1207" + MinHeight="918" + MaxHeight="918" + CanResize="False" + WindowStartupLocation="CenterScreen" TransparencyLevelHint="AcrylicBlur" TransparencyBackgroundFallback="{DynamicResource EasyWindowBackgroundBrush}"> @@ -20,7 +28,7 @@ - + @@ -86,11 +94,11 @@ + + + + + + + + + +