Compare commits

...

10 Commits

Author SHA1 Message Date
Shawn Yuan (from Dev Box)
219b0046df Merge branch 'main' into shawn/supportWinML 2025-11-17 10:33:03 +08:00
Kai Tao
34c37f2d38 Add not signed dll (#43631)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This dll is not signed, will fail the pipeline

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-11-17 09:48:32 +08:00
Niels Laute
47aed03c03 [AP] Loc fix (#43617)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-11-16 22:13:40 +08:00
Niels Laute
6423c7693d [CmdPal] Settings page refresh (#43487)
- Refreshed the CmdPal page.
- CmdPal can now also be activated from this page by clicking a button
- Added a Preview InfoBar for FL in AP

<img width="1384" height="1067" alt="image"
src="https://github.com/user-attachments/assets/f670e13b-5b4a-4f6a-bcb0-e1dc357afb1e"
/>

## Summary of the Pull Request

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

---------

Co-authored-by: vanzue <vanzue@outlook.com>
2025-11-16 22:02:38 +08:00
Kai Tao
3e14d50f65 Advanced paste: Add more error handle for foundry local (#43600)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request
Foundry local sdk will not run models that is not in catalog, when
catalog removes some, the old ones will fail executing,
so add error hint for users to re-configure the models in settings.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
<img width="864" height="216" alt="image"
src="https://github.com/user-attachments/assets/654207b3-ff50-4888-a638-82136216de7b"
/>
2025-11-16 15:26:05 +08:00
Jaylyn Barbee
db7c9e180e [Light Switch] Removed logs from every tick, only logging key events. (#43572)
Title
2025-11-15 21:08:20 +08:00
Michael Jolley
bcc3ded280 CmdPal: Adding page Id to OpenPage telemetry event (#43584)
@niels9001 requested this.

As the name says
2025-11-15 21:07:52 +08:00
Mario Hewardt
24a3cdd486 Fixes regressions introduced with GIF support (#43589)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Fixes regressions introduced with GIF support:
- Switches default recording format back to MP4
- Fixes framerate issues between the two formats
- Fixes file path names

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [x ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx

<!-- Provide a more detailed description of the PR, other things fixed,
or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments
- Switches default recording format back to MP4
- Fixes framerate issues between the two formats
- Fixes file path names
- 
<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
Manual testing
2025-11-15 09:36:31 +08:00
Shawn Yuan (from Dev Box)
d2cf2be2cb add ui
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-11 16:37:34 +08:00
Shawn Yuan (from Dev Box)
c953d5146a upgrade winappsdk
Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-11 14:54:05 +08:00
53 changed files with 1166 additions and 272 deletions

View File

@@ -291,6 +291,7 @@
"Mono.Cecil.Rocks.dll",
"Newtonsoft.Json.dll",
"CommunityToolkit.WinUI.Controls.TitleBar.dll",
"CommunityToolkit.WinUI.Controls.OpacityMaskView.dll",
"NLog.dll",
"HtmlAgilityPack.dll",

View File

@@ -7,6 +7,7 @@
<PackageVersion Include="AdaptiveCards.ObjectModel.WinUI3" Version="2.0.0-beta" />
<PackageVersion Include="AdaptiveCards.Rendering.WinUI3" Version="2.1.0-beta" />
<PackageVersion Include="AdaptiveCards.Templating" Version="2.0.5" />
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" Version="0.1.251101-build.2372" />
<PackageVersion Include="Microsoft.Bot.AdaptiveExpressions.Core" Version="4.23.0" />
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
<PackageVersion Include="CoenM.ImageSharp.ImageHash" Version="1.3.6" />
@@ -69,9 +70,17 @@
-->
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4948" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.37" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.ML.OnnxRuntimeGenAI.WinML" Version="0.10.1" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.251003001" />
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="1.8.38" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Base" Version="1.8.250831001" />
<PackageVersion Include="Microsoft.WindowsAppSDK.DWrite" Version="1.8.25090401" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="1.8.250906002" />
<PackageVersion Include="Microsoft.WindowsAppSDK.InteractiveExperiences" Version="1.8.250906004" />
<PackageVersion Include="Microsoft.WindowsAppSDK.ML" Version="1.8.2095" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="1.8.251003001" />
<PackageVersion Include="Microsoft.WindowsAppSDK.Widgets" Version="1.8.250904007" />
<PackageVersion Include="Microsoft.WindowsAppSDK.WinUI" Version="1.8.250906003" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
@@ -110,6 +119,7 @@
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
<PackageVersion Include="System.Management" Version="9.0.10" />
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
<PackageVersion Include="System.Numerics.Tensors" Version="9.0.10" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Reactive" Version="6.0.1" />
<PackageVersion Include="System.Runtime.Caching" Version="9.0.10" />

View File

@@ -1498,6 +1498,7 @@ SOFTWARE.
- CoenM.ImageSharp.ImageHash
- CommunityToolkit.Common
- CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock
- CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView
- CommunityToolkit.Mvvm
- CommunityToolkit.WinUI.Animations
- CommunityToolkit.WinUI.Collections

View File

@@ -169,41 +169,23 @@ internal sealed class FoundryClient
public async Task<bool> EnsureModelLoaded(string modelId)
{
try
Logger.LogInfo($"[FoundryClient] EnsureModelLoaded called with: {modelId}");
// Check if already loaded
if (await IsModelLoaded(modelId).ConfigureAwait(false))
{
Logger.LogInfo($"[FoundryClient] EnsureModelLoaded called with: {modelId}");
// Check if already loaded
if (await IsModelLoaded(modelId).ConfigureAwait(false))
{
Logger.LogInfo($"[FoundryClient] Model already loaded: {modelId}");
return true;
}
// Check if model exists in cache
var cachedModels = await ListCachedModels().ConfigureAwait(false);
Logger.LogInfo($"[FoundryClient] Cached models: {string.Join(", ", cachedModels.Select(m => m.Name))}");
if (!cachedModels.Any(m => m.Name == modelId))
{
Logger.LogWarning($"[FoundryClient] Model not found in cache: {modelId}");
return false;
}
// Load the model
Logger.LogInfo($"[FoundryClient] Loading model: {modelId}");
await _foundryManager.LoadModelAsync(modelId).ConfigureAwait(false);
// Verify it's loaded
var loaded = await IsModelLoaded(modelId).ConfigureAwait(false);
Logger.LogInfo($"[FoundryClient] Model load result: {loaded}");
return loaded;
}
catch (Exception ex)
{
Logger.LogError($"[FoundryClient] EnsureModelLoaded exception: {ex.Message}");
return false;
Logger.LogInfo($"[FoundryClient] Model already loaded: {modelId}");
return true;
}
// Load the model
Logger.LogInfo($"[FoundryClient] Loading model: {modelId}");
await _foundryManager.LoadModelAsync(modelId).ConfigureAwait(false);
// Verify it's loaded
var loaded = await IsModelLoaded(modelId).ConfigureAwait(false);
Logger.LogInfo($"[FoundryClient] Model load result: {loaded}");
return loaded;
}
public async Task EnsureRunning()

View File

@@ -13,6 +13,7 @@ namespace LanguageModelProvider;
public sealed class FoundryLocalModelProvider : ILanguageModelProvider
{
private IEnumerable<ModelDetails>? _downloadedModels;
private IEnumerable<FoundryCatalogModel>? _catalogModels;
private FoundryClient? _foundryClient;
private string? _serviceUrl;
@@ -24,22 +25,8 @@ public sealed class FoundryLocalModelProvider : ILanguageModelProvider
public IChatClient? GetIChatClient(string modelId)
{
try
{
Logger.LogInfo($"[FoundryLocal] GetIChatClient called with url: {modelId}");
InitializeAsync().GetAwaiter().GetResult();
}
catch (Exception ex)
{
Logger.LogError($"[FoundryLocal] Failed to initialize: {ex.Message}");
return null;
}
if (string.IsNullOrWhiteSpace(_serviceUrl) || _foundryClient == null)
{
Logger.LogError("[FoundryLocal] Service URL or manager is null");
return null;
}
Logger.LogInfo($"[FoundryLocal] GetIChatClient called with url: {modelId}");
InitializeAsync().GetAwaiter().GetResult();
if (string.IsNullOrWhiteSpace(modelId))
{
@@ -47,35 +34,43 @@ public sealed class FoundryLocalModelProvider : ILanguageModelProvider
return null;
}
// Ensure the model is loaded before returning chat client
try
// Check if model is in catalog
var isInCatalog = _catalogModels?.Any(m => m.Name == modelId) ?? false;
if (!isInCatalog)
{
var isLoaded = _foundryClient.EnsureModelLoaded(modelId).GetAwaiter().GetResult();
if (!isLoaded)
{
Logger.LogError($"[FoundryLocal] Failed to load model: {modelId}");
return null;
}
Logger.LogInfo($"[FoundryLocal] Model is loaded: {modelId}");
var errorMessage = $"{modelId} is not supported in Foundry Local. Please configure supported models in Settings.";
Logger.LogError($"[FoundryLocal] {errorMessage}");
throw new InvalidOperationException(errorMessage);
}
catch (Exception ex)
// Check if model is cached
var isInCache = _downloadedModels?.Any(m => m.ProviderModelDetails is FoundryCachedModel cached && cached.Name == modelId) ?? false;
if (!isInCache)
{
Logger.LogError($"[FoundryLocal] Exception ensuring model loaded: {ex.Message}");
return null;
var errorMessage = $"The requested model '{modelId}' is not cached. Please download it using Foundry Local.";
Logger.LogError($"[FoundryLocal] {errorMessage}");
throw new InvalidOperationException(errorMessage);
}
// Ensure the model is loaded before returning chat client
var isLoaded = _foundryClient!.EnsureModelLoaded(modelId).GetAwaiter().GetResult();
if (!isLoaded)
{
Logger.LogError($"[FoundryLocal] Failed to load model: {modelId}");
throw new InvalidOperationException($"Failed to load the model '{modelId}'.");
}
// Use ServiceUri instead of Endpoint since Endpoint already includes /v1
var baseUri = _foundryClient.GetServiceUri();
if (baseUri == null)
{
Logger.LogError("[FoundryLocal] Service URI is null");
return null;
const string message = "Foundry Local service URL is not available. Please make sure Foundry Local is installed and running.";
Logger.LogError($"[FoundryLocal] {message}");
throw new InvalidOperationException(message);
}
var endpointUri = new Uri($"{baseUri.ToString().TrimEnd('/')}/v1");
Logger.LogInfo($"[FoundryLocal] Creating OpenAI client with endpoint: {endpointUri}");
Logger.LogInfo($"[FoundryLocal] Model ID for chat client: {modelId}");
return new OpenAIClient(
new ApiKeyCredential("none"),
@@ -122,12 +117,13 @@ public sealed class FoundryLocalModelProvider : ILanguageModelProvider
private void Reset()
{
_downloadedModels = null;
_catalogModels = null;
_ = InitializeAsync();
}
private async Task InitializeAsync(CancellationToken cancelationToken = default)
{
if (_foundryClient != null && _downloadedModels != null && _downloadedModels.Any())
if (_foundryClient != null && _downloadedModels != null && _downloadedModels.Any() && _catalogModels != null && _catalogModels.Any())
{
await _foundryClient.EnsureRunning().ConfigureAwait(false);
return;
@@ -138,13 +134,18 @@ public sealed class FoundryLocalModelProvider : ILanguageModelProvider
if (_foundryClient == null)
{
Logger.LogError("[FoundryLocal] Failed to create Foundry client");
return;
const string message = "Foundry Local client could not be created. Please make sure Foundry Local is installed and running.";
Logger.LogError($"[FoundryLocal] {message}");
throw new InvalidOperationException(message);
}
_serviceUrl ??= await _foundryClient.GetServiceUrl();
Logger.LogInfo($"[FoundryLocal] Service URL: {_serviceUrl}");
var catalogModels = await _foundryClient.ListCatalogModels();
Logger.LogInfo($"[FoundryLocal] Found {catalogModels.Count} catalog models");
_catalogModels = catalogModels;
var cachedModels = await _foundryClient.ListCachedModels();
Logger.LogInfo($"[FoundryLocal] Found {cachedModels.Count} cached models");

View File

@@ -57,6 +57,8 @@ internal sealed class IntegrationTestUserSettings : IUserSettings
public PasteAIConfiguration PasteAIConfiguration => _configuration;
public string CustomModelStoragePath => AdvancedPasteProperties.GetDefaultCustomModelStoragePath();
public event EventHandler Changed;
public Task SetActiveAIProviderAsync(string providerId)

View File

@@ -144,7 +144,7 @@ public sealed class AIServiceBatchIntegrationTests
switch (format)
{
case PasteFormats.CustomTextTransformation:
var transformResult = await services.CustomActionTransformService.TransformTextAsync(batchTestInput.Prompt, batchTestInput.Clipboard, CancellationToken.None, progress);
var transformResult = await services.CustomActionTransformService.TransformTextAsync(null, batchTestInput.Prompt, batchTestInput.Clipboard, CancellationToken.None, progress);
return DataPackageHelpers.CreateFromText(transformResult.Content ?? string.Empty);
case PasteFormats.KernelQuery:

View File

@@ -68,6 +68,7 @@
<PackageReference Include="Microsoft.WindowsAppSDK" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" />
<PackageReference Include="System.ClientModel" />
<PackageReference Include="System.Numerics.Tensors" />
<PackageReference Include="Microsoft.Windows.Compatibility" />
<PackageReference Include="Microsoft.Windows.CsWin32" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />

View File

@@ -558,7 +558,7 @@
<TextBlock
x:Uid="AIProvidersFlyoutHeader"
Grid.Row="0"
Style="{StaticResource BodyStrongTextBlockStyle}" />
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<ListView
x:Name="AIProviderListView"
Grid.Row="1"

View File

@@ -27,6 +27,8 @@ namespace AdvancedPaste.Settings
public PasteAIConfiguration PasteAIConfiguration { get; }
public string CustomModelStoragePath { get; }
public event EventHandler Changed;
Task SetActiveAIProviderAsync(string providerId);

View File

@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Threading;
@@ -48,6 +49,8 @@ namespace AdvancedPaste.Settings
public PasteAIConfiguration PasteAIConfiguration { get; private set; }
public string CustomModelStoragePath { get; private set; }
public UserSettings(IFileSystem fileSystem)
{
_settingsUtils = new SettingsUtils(fileSystem);
@@ -57,6 +60,8 @@ namespace AdvancedPaste.Settings
CloseAfterLosingFocus = false;
EnableClipboardPreview = true;
PasteAIConfiguration = new PasteAIConfiguration();
CustomModelStoragePath = NormalizeDirectoryPath(AdvancedPasteProperties.GetDefaultCustomModelStoragePath());
EnsureDirectoryExists(CustomModelStoragePath);
_additionalActions = [];
_customActions = [];
_taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
@@ -112,6 +117,8 @@ namespace AdvancedPaste.Settings
CloseAfterLosingFocus = properties.CloseAfterLosingFocus;
EnableClipboardPreview = properties.EnableClipboardPreview;
PasteAIConfiguration = properties.PasteAIConfiguration ?? new PasteAIConfiguration();
CustomModelStoragePath = NormalizeDirectoryPath(properties.CustomModelStoragePath);
EnsureDirectoryExists(CustomModelStoragePath);
var sourceAdditionalActions = properties.AdditionalActions;
(PasteFormats Format, IAdvancedPasteAction[] Actions)[] additionalActionFormats =
@@ -398,5 +405,39 @@ namespace AdvancedPaste.Settings
{
Dispose(false);
}
private static string NormalizeDirectoryPath(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
return AdvancedPasteProperties.GetDefaultCustomModelStoragePath();
}
try
{
path = Environment.ExpandEnvironmentVariables(path.Trim());
return Path.GetFullPath(path);
}
catch (Exception)
{
return path;
}
}
private static void EnsureDirectoryExists(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
return;
}
try
{
Directory.CreateDirectory(path);
}
catch (Exception)
{
}
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using Microsoft.PowerToys.Settings.UI.Library;
namespace AdvancedPaste.Models;
@@ -32,12 +33,13 @@ public sealed class PasteFormat
IsSavedQuery = false,
};
public static PasteFormat CreateCustomAIFormat(PasteFormats format, string name, string prompt, bool isSavedQuery, ClipboardFormat clipboardFormats, bool isAIServiceEnabled) =>
public static PasteFormat CreateCustomAIFormat(PasteFormats format, string name, string prompt, bool isSavedQuery, ClipboardFormat clipboardFormats, bool isAIServiceEnabled, AdvancedPasteCustomAction customAction = null) =>
new(format, clipboardFormats, isAIServiceEnabled)
{
Name = name,
Prompt = prompt,
IsSavedQuery = isSavedQuery,
CustomAction = customAction,
};
public PasteFormatMetadataAttribute Metadata => MetadataDict[Format];
@@ -52,6 +54,8 @@ public sealed class PasteFormat
public bool IsSavedQuery { get; private init; }
public AdvancedPasteCustomAction CustomAction { get; private init; }
public bool IsEnabled { get; private init; }
public string AccessibleName => $"{Name} ({ShortcutText})";

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
@@ -40,10 +41,12 @@ namespace AdvancedPaste.Services.CustomActions
this.userSettings = userSettings;
}
public async Task<CustomActionTransformResult> TransformTextAsync(string prompt, string inputText, CancellationToken cancellationToken, IProgress<double> progress)
public async Task<CustomActionTransformResult> TransformTextAsync(AdvancedPasteCustomAction customAction, string prompt, string inputText, CancellationToken cancellationToken, IProgress<double> progress)
{
var pasteConfig = userSettings?.PasteAIConfiguration;
var providerConfig = BuildProviderConfig(pasteConfig);
var providerConfig = customAction?.UseCustomModel == true
? BuildCustomModelConfig(customAction)
: BuildProviderConfig(pasteConfig);
return await TransformAsync(prompt, inputText, providerConfig, cancellationToken, progress);
}
@@ -171,6 +174,24 @@ namespace AdvancedPaste.Services.CustomActions
return providerConfig;
}
private PasteAIConfig BuildCustomModelConfig(AdvancedPasteCustomAction customAction)
{
ArgumentNullException.ThrowIfNull(customAction);
var modelPath = ResolveCustomModelPath(customAction);
var systemPrompt = DetermineCustomModelSystemPrompt();
return new PasteAIConfig
{
ProviderType = AIServiceType.ML,
Model = Path.GetFileNameWithoutExtension(modelPath),
LocalModelPath = modelPath,
ModelPath = modelPath,
SystemPrompt = systemPrompt,
ModerationEnabled = false,
};
}
private string AcquireApiKey(AIServiceType serviceType)
{
if (!RequiresApiKey(serviceType))
@@ -201,5 +222,57 @@ namespace AdvancedPaste.Services.CustomActions
return providerConfig.ProviderType == AIServiceType.OpenAI || providerConfig.ProviderType == AIServiceType.AzureOpenAI;
}
private string ResolveCustomModelPath(AdvancedPasteCustomAction customAction)
{
var modelPath = customAction.CustomModelPath?.Trim() ?? string.Empty;
if (string.IsNullOrWhiteSpace(modelPath))
{
throw new PasteActionException(GetCustomModelMissingMessage(), new FileNotFoundException());
}
var storagePath = userSettings?.CustomModelStoragePath;
var expandedPath = Environment.ExpandEnvironmentVariables(modelPath);
if (!Path.IsPathRooted(expandedPath) && !string.IsNullOrEmpty(storagePath))
{
expandedPath = Path.Combine(storagePath, expandedPath);
}
string fullPath;
try
{
fullPath = Path.GetFullPath(expandedPath);
}
catch (Exception ex)
{
throw new PasteActionException(GetCustomModelMissingMessage(), ex);
}
if (!File.Exists(fullPath))
{
throw new PasteActionException(GetCustomModelMissingMessage(), new FileNotFoundException(fullPath));
}
return fullPath;
}
private static string GetCustomModelMissingMessage()
{
var message = ResourceLoaderInstance.ResourceLoader.GetString("AdvancedPasteCustomModelNotFound");
return string.IsNullOrWhiteSpace(message) ? "The selected custom model could not be found." : message;
}
private string DetermineCustomModelSystemPrompt()
{
var customPrompt = userSettings?.PasteAIConfiguration?.ActiveProvider?.SystemPrompt
?? userSettings?.PasteAIConfiguration?.Providers?.FirstOrDefault()?.SystemPrompt;
if (string.IsNullOrWhiteSpace(customPrompt))
{
return DefaultSystemPrompt;
}
return customPrompt;
}
}
}

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AdvancedPaste.Helpers;
using AdvancedPaste.Models;
using LanguageModelProvider;
using Microsoft.Extensions.AI;
@@ -33,10 +34,6 @@ public sealed class FoundryLocalPasteProvider : IPasteAIProvider
_config = config;
}
public string ProviderName => AIServiceType.FoundryLocal.ToNormalizedKey();
public string DisplayName => string.IsNullOrWhiteSpace(_config?.Model) ? "Foundry Local" : _config.Model;
public async Task<bool> IsAvailableAsync(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -76,13 +73,20 @@ public sealed class FoundryLocalPasteProvider : IPasteAIProvider
}
cancellationToken.ThrowIfCancellationRequested();
var chatClient = _modelProvider.GetIChatClient(modelReference);
if (chatClient is null)
IChatClient chatClient;
try
{
chatClient = _modelProvider.GetIChatClient(modelReference);
}
catch (InvalidOperationException ex)
{
// GetIChatClient throws InvalidOperationException for user-facing errors
var errorMessage = string.Format(System.Globalization.CultureInfo.CurrentCulture, ResourceLoaderInstance.ResourceLoader.GetString("FoundryLocal_UnableToLoadModel"), modelReference);
throw new PasteActionException(
$"Unable to load Foundry Local model: {modelReference}",
new InvalidOperationException("Chat client resolution failed"),
aiServiceMessage: "The model may not be downloaded or the Foundry Local service may not be running. Please check the model status in settings.");
errorMessage,
ex,
aiServiceMessage: ex.Message);
}
var userMessageContent = $"""

View File

@@ -7,11 +7,12 @@ using System.Threading;
using System.Threading.Tasks;
using AdvancedPaste.Settings;
using Microsoft.PowerToys.Settings.UI.Library;
namespace AdvancedPaste.Services.CustomActions
{
public interface ICustomActionTransformService
{
Task<CustomActionTransformResult> TransformTextAsync(string prompt, string inputText, CancellationToken cancellationToken, IProgress<double> progress);
Task<CustomActionTransformResult> TransformTextAsync(AdvancedPasteCustomAction customAction, string prompt, string inputText, CancellationToken cancellationToken, IProgress<double> progress);
}
}

View File

@@ -3,11 +3,15 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AdvancedPaste.Helpers;
using AdvancedPaste.Models;
using Microsoft.PowerToys.Settings.UI.Library;
using Windows.AI.MachineLearning;
namespace AdvancedPaste.Services.CustomActions
{
@@ -23,6 +27,8 @@ namespace AdvancedPaste.Services.CustomActions
private readonly PasteAIConfig _config;
private static readonly ConcurrentDictionary<string, Lazy<Task<LearningModel>>> ModelCache = new(StringComparer.OrdinalIgnoreCase);
public LocalModelPasteProvider(PasteAIConfig config)
{
_config = config ?? throw new ArgumentNullException(nameof(config));
@@ -30,14 +36,120 @@ namespace AdvancedPaste.Services.CustomActions
public Task<bool> IsAvailableAsync(CancellationToken cancellationToken) => Task.FromResult(true);
public Task<string> ProcessPasteAsync(PasteAIRequest request, CancellationToken cancellationToken, IProgress<double> progress)
public async Task<string> ProcessPasteAsync(PasteAIRequest request, CancellationToken cancellationToken, IProgress<double> progress)
{
ArgumentNullException.ThrowIfNull(request);
// TODO: Implement local model inference logic using _config.LocalModelPath/_config.ModelPath
var content = request.InputText ?? string.Empty;
request.Usage = AIServiceUsage.None;
return Task.FromResult(content);
cancellationToken.ThrowIfCancellationRequested();
var modelPath = _config.LocalModelPath ?? _config.ModelPath;
if (string.IsNullOrWhiteSpace(modelPath))
{
throw new PasteActionException(GetInferenceErrorMessage(), new InvalidOperationException("Local model path not provided."));
}
try
{
var model = await GetOrLoadModelAsync(modelPath).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
using LearningModelSession session = new(model);
var binding = new LearningModelBinding(session);
BindInputs(session.Model, binding, request);
var correlationId = Guid.NewGuid().ToString();
var evaluation = await session.EvaluateAsync(binding, correlationId).AsTask(cancellationToken).ConfigureAwait(false);
var output = ExtractStringOutput(session.Model, evaluation);
request.Usage = AIServiceUsage.None;
progress?.Report(1.0);
return output ?? string.Empty;
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
throw new PasteActionException(GetInferenceErrorMessage(), ex);
}
}
private static async Task<LearningModel> GetOrLoadModelAsync(string modelPath)
{
var loader = ModelCache.GetOrAdd(modelPath, path => new Lazy<Task<LearningModel>>(() => Task.Run(() => LearningModel.LoadFromFilePath(path))));
return await loader.Value.ConfigureAwait(false);
}
private static void BindInputs(LearningModel model, LearningModelBinding binding, PasteAIRequest request)
{
var stringInputs = model.InputFeatures
.OfType<TensorFeatureDescriptor>()
.Where(descriptor => descriptor.TensorKind == TensorKind.String)
.ToList();
if (stringInputs.Count == 0)
{
throw new PasteActionException(GetInferenceErrorMessage(), new InvalidOperationException("Model does not expose string inputs."));
}
var prompt = request.Prompt ?? string.Empty;
var input = request.InputText ?? string.Empty;
var combined = string.IsNullOrWhiteSpace(prompt) ? input : string.Join(Environment.NewLine + Environment.NewLine, prompt, input);
foreach (var inputDescriptor in stringInputs)
{
var value = ResolveInputValue(inputDescriptor.Name, prompt, input, combined);
var tensor = TensorString.CreateFromArray(new long[] { 1 }, new[] { value });
binding.Bind(inputDescriptor.Name, tensor);
}
}
private static string ResolveInputValue(string featureName, string prompt, string input, string combined)
{
if (string.IsNullOrEmpty(featureName))
{
return combined;
}
switch (featureName.ToLowerInvariant())
{
case "prompt":
case "instruction":
case "instructions":
return prompt;
case "input":
case "text":
case "input_text":
case "inputtext":
return input;
default:
return combined;
}
}
private static string ExtractStringOutput(LearningModel model, LearningModelEvaluationResult evaluation)
{
foreach (var outputDescriptor in model.OutputFeatures.OfType<TensorFeatureDescriptor>().Where(descriptor => descriptor.TensorKind == TensorKind.String))
{
if (evaluation.Outputs.TryGetValue(outputDescriptor.Name, out var value) && value is TensorString tensor)
{
var vector = tensor.GetAsVectorView();
if (vector.Count > 0)
{
return vector[0];
}
}
}
throw new PasteActionException(GetInferenceErrorMessage(), new InvalidOperationException("Model did not return a string output."));
}
private static string GetInferenceErrorMessage()
{
var message = ResourceLoaderInstance.ResourceLoader.GetString("AdvancedPasteCustomModelInferenceError");
return string.IsNullOrWhiteSpace(message) ? "The custom model failed to generate a response." : message;
}
}
}

View File

@@ -247,7 +247,7 @@ public abstract class KernelServiceBase(
? $"Runs the \"{customAction.Name}\" custom action."
: customAction.Description;
return KernelFunctionFactory.CreateFromMethod(
method: async (Kernel kernel) => await ExecuteCustomActionAsync(kernel, customAction.Prompt),
method: async (Kernel kernel) => await ExecuteCustomActionAsync(kernel, customAction),
functionName: functionName,
description: description,
parameters: null,
@@ -296,14 +296,14 @@ public abstract class KernelServiceBase(
return string.IsNullOrEmpty(sanitized) ? "_CustomAction" : sanitized;
}
private Task<string> ExecuteCustomActionAsync(Kernel kernel, string fixedPrompt) =>
private Task<string> ExecuteCustomActionAsync(Kernel kernel, AdvancedPasteCustomAction customAction) =>
ExecuteTransformAsync(
kernel,
new ActionChainItem(PasteFormats.CustomTextTransformation, Arguments: new() { { PromptParameterName, fixedPrompt } }),
new ActionChainItem(PasteFormats.CustomTextTransformation, Arguments: new() { { PromptParameterName, customAction?.Prompt ?? string.Empty } }),
async dataPackageView =>
{
var input = await dataPackageView.GetClipboardTextOrThrowAsync(kernel.GetCancellationToken());
var result = await _customActionTransformService.TransformTextAsync(fixedPrompt, input, kernel.GetCancellationToken(), kernel.GetProgress());
var result = await _customActionTransformService.TransformTextAsync(customAction, customAction?.Prompt ?? string.Empty, input, kernel.GetCancellationToken(), kernel.GetProgress());
return DataPackageHelpers.CreateFromText(result?.Content ?? string.Empty);
});
@@ -321,7 +321,7 @@ public abstract class KernelServiceBase(
private async Task<string> GetPromptBasedOutput(PasteFormats format, string prompt, string input, CancellationToken cancellationToken, IProgress<double> progress) =>
format switch
{
PasteFormats.CustomTextTransformation => (await _customActionTransformService.TransformTextAsync(prompt, input, cancellationToken, progress))?.Content ?? string.Empty,
PasteFormats.CustomTextTransformation => (await _customActionTransformService.TransformTextAsync(null, prompt, input, cancellationToken, progress))?.Content ?? string.Empty,
_ => throw new ArgumentException($"Unsupported format {format} for prompt transform", nameof(format)),
};

View File

@@ -37,7 +37,7 @@ public sealed class PasteFormatExecutor(IKernelService kernelService, ICustomAct
pasteFormat.Format switch
{
PasteFormats.KernelQuery => await _kernelService.TransformClipboardAsync(pasteFormat.Prompt, clipboardData, pasteFormat.IsSavedQuery, cancellationToken, progress),
PasteFormats.CustomTextTransformation => DataPackageHelpers.CreateFromText((await _customActionTransformService.TransformTextAsync(pasteFormat.Prompt, await clipboardData.GetClipboardTextOrThrowAsync(cancellationToken), cancellationToken, progress))?.Content ?? string.Empty),
PasteFormats.CustomTextTransformation => DataPackageHelpers.CreateFromText((await _customActionTransformService.TransformTextAsync(pasteFormat.CustomAction, pasteFormat.Prompt, await clipboardData.GetClipboardTextOrThrowAsync(cancellationToken), cancellationToken, progress))?.Content ?? string.Empty),
_ => await TransformHelpers.TransformAsync(format, clipboardData, cancellationToken, progress),
});
}

View File

@@ -160,10 +160,10 @@
<value>Active provider: {0}</value>
</data>
<data name="AIProvidersFlyoutHeader.Text" xml:space="preserve">
<value>AI providers</value>
<value>Configured models</value>
</data>
<data name="AIProvidersEmptyText.Text" xml:space="preserve">
<value>No AI providers configured</value>
<value>No models configured</value>
</data>
<data name="AIProvidersManageButtonContent.Content" xml:space="preserve">
<value>Configure models in Settings</value>
@@ -364,8 +364,12 @@
<data name="CustomEndpointWarning" xml:space="preserve">
<value>You are using a custom endpoint. Verify all answers.</value>
</data>
<data name="LocalModelBadge" xml:space="preserve">
<data name="LocalModelBadge.Text" xml:space="preserve">
<value>Local</value>
<comment>Badge label displayed next to local AI model providers (e.g., Ollama, Foundry Local) to indicate the model runs locally</comment>
</data>
<data name="FoundryLocal_UnableToLoadModel" xml:space="preserve">
<value>Unable to load Foundry Local model: {0}</value>
<comment>{0} is the model identifier. Do not translate {0}.</comment>
</data>
</root>

View File

@@ -343,8 +343,8 @@ namespace AdvancedPaste.ViewModels
private PasteFormat CreateStandardPasteFormat(PasteFormats format) =>
PasteFormat.CreateStandardFormat(format, AvailableClipboardFormats, IsCustomAIServiceEnabled, ResourceLoaderInstance.ResourceLoader.GetString);
private PasteFormat CreateCustomAIPasteFormat(string name, string prompt, bool isSavedQuery) =>
PasteFormat.CreateCustomAIFormat(CustomAIFormat, name, prompt, isSavedQuery, AvailableClipboardFormats, IsCustomAIServiceEnabled);
private PasteFormat CreateCustomAIPasteFormat(string name, string prompt, bool isSavedQuery, AdvancedPasteCustomAction customAction = null) =>
PasteFormat.CreateCustomAIFormat(CustomAIFormat, name, prompt, isSavedQuery, AvailableClipboardFormats, IsCustomAIServiceEnabled, customAction);
private void UpdateAIProviderActiveFlags()
{
@@ -417,7 +417,7 @@ namespace AdvancedPaste.ViewModels
UpdateFormats(
CustomActionPasteFormats,
IsCustomAIServiceEnabled ? _userSettings.CustomActions.Select(customAction => CreateCustomAIPasteFormat(customAction.Name, customAction.Prompt, isSavedQuery: true)) : []);
IsCustomAIServiceEnabled ? _userSettings.CustomActions.Select(customAction => CreateCustomAIPasteFormat(customAction.Name, customAction.Prompt, isSavedQuery: true, customAction)) : []);
}
public void Dispose()
@@ -742,7 +742,7 @@ namespace AdvancedPaste.ViewModels
if (customAction != null)
{
await ReadClipboardAsync();
await ExecutePasteFormatAsync(CreateCustomAIPasteFormat(customAction.Name, customAction.Prompt, isSavedQuery: true), source);
await ExecutePasteFormatAsync(CreateCustomAIPasteFormat(customAction.Name, customAction.Prompt, isSavedQuery: true, customAction), source);
}
}
@@ -751,7 +751,7 @@ namespace AdvancedPaste.ViewModels
var customAction = _userSettings.CustomActions
.FirstOrDefault(customAction => Models.KernelQueryCache.CacheKey.PromptComparer.Equals(customAction.Prompt, Query));
await ExecutePasteFormatAsync(CreateCustomAIPasteFormat(customAction?.Name ?? "Default", Query, isSavedQuery: customAction != null), triggerSource);
await ExecutePasteFormatAsync(CreateCustomAIPasteFormat(customAction?.Name ?? "Default", Query, isSavedQuery: customAction != null, customAction), triggerSource);
}
private void HideWindow()

View File

@@ -271,7 +271,6 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
if (wait == WAIT_OBJECT_0 + (hParent ? (hManualOverride ? 3 : 2) : 2))
{
Logger::info(L"[LightSwitchService] Settings file changed event detected.");
ResetEvent(hSettingsChanged);
LightSwitchSettings::instance().LoadSettings();
stateManager.OnSettingsChanged();

View File

@@ -17,12 +17,10 @@ LightSwitchStateManager::LightSwitchStateManager()
void LightSwitchStateManager::OnSettingsChanged()
{
std::lock_guard<std::mutex> lock(_stateMutex);
Logger::info(L"[LightSwitchStateManager] Settings changed event received");
// If manual override was active, clear it so new settings take effect
if (_state.isManualOverride)
{
Logger::info(L"[LightSwitchStateManager] Clearing manual override due to settings update.");
_state.isManualOverride = false;
}
@@ -33,7 +31,6 @@ void LightSwitchStateManager::OnSettingsChanged()
void LightSwitchStateManager::OnTick(int currentMinutes)
{
std::lock_guard<std::mutex> lock(_stateMutex);
Logger::debug(L"[LightSwitchStateManager] Tick received: {}", currentMinutes);
EvaluateAndApplyIfNeeded();
}
@@ -51,7 +48,7 @@ void LightSwitchStateManager::OnManualOverride()
_state.isAppsLightActive = GetCurrentAppsTheme();
Logger::info(L"[LightSwitchStateManager] Synced internal theme state to current system theme ({}) and apps theme ({}).",
Logger::debug(L"[LightSwitchStateManager] Synced internal theme state to current system theme ({}) and apps theme ({}).",
(_state.isSystemLightActive ? L"light" : L"dark"),
(_state.isAppsLightActive ? L"light" : L"dark"));
}
@@ -79,9 +76,9 @@ void LightSwitchStateManager::SyncInitialThemeState()
std::lock_guard<std::mutex> lock(_stateMutex);
_state.isSystemLightActive = GetCurrentSystemTheme();
_state.isAppsLightActive = GetCurrentAppsTheme();
Logger::info(L"[LightSwitchStateManager] Synced initial state to current system theme ({})",
Logger::debug(L"[LightSwitchStateManager] Synced initial state to current system theme ({})",
_state.isSystemLightActive ? L"light" : L"dark");
Logger::info(L"[LightSwitchStateManager] Synced initial state to current apps theme ({})",
Logger::debug(L"[LightSwitchStateManager] Synced initial state to current apps theme ({})",
_state.isAppsLightActive ? L"light" : L"dark");
}
@@ -127,7 +124,6 @@ void LightSwitchStateManager::EvaluateAndApplyIfNeeded()
// Early exit: OFF mode just pauses activity
if (_currentSettings.scheduleMode == ScheduleMode::Off)
{
Logger::debug(L"[LightSwitchStateManager] Mode is OFF — pausing service logic.");
_state.lastTickMinutes = now;
return;
}
@@ -145,7 +141,6 @@ void LightSwitchStateManager::EvaluateAndApplyIfNeeded()
if (newDay || modeChangedToSun)
{
Logger::info(L"[LightSwitchStateManager] Recalculating sun times (mode/day change).");
auto [newLightTime, newDarkTime] = update_sun_times(_currentSettings);
_state.lastEvaluatedDay = st.wDay;
_state.effectiveLightMinutes = newLightTime + _currentSettings.sunrise_offset;
@@ -188,12 +183,10 @@ void LightSwitchStateManager::EvaluateAndApplyIfNeeded()
if (crossedBoundary)
{
Logger::info(L"[LightSwitchStateManager] Manual override cleared after crossing boundary.");
_state.isManualOverride = false;
}
else
{
Logger::debug(L"[LightSwitchStateManager] Manual override active — skipping auto apply.");
_state.lastTickMinutes = now;
return;
}
@@ -206,7 +199,7 @@ void LightSwitchStateManager::EvaluateAndApplyIfNeeded()
bool appsNeedsToChange = _currentSettings.changeApps && (_state.isAppsLightActive != shouldBeLight);
bool systemNeedsToChange = _currentSettings.changeSystem && (_state.isSystemLightActive != shouldBeLight);
Logger::debug(
/* Logger::debug(
L"[LightSwitchStateManager] now = {:02d}:{:02d}, light boundary = {:02d}:{:02d} ({}), dark boundary = {:02d}:{:02d} ({})",
now / 60,
now % 60,
@@ -215,12 +208,12 @@ void LightSwitchStateManager::EvaluateAndApplyIfNeeded()
_state.effectiveLightMinutes,
_state.effectiveDarkMinutes / 60,
_state.effectiveDarkMinutes % 60,
_state.effectiveDarkMinutes);
_state.effectiveDarkMinutes); */
Logger::debug("should be light = {}, apps needs change = {}, system needs change = {}",
/* Logger::debug("should be light = {}, apps needs change = {}, system needs change = {}",
shouldBeLight ? "true" : "false",
appsNeedsToChange ? "true" : "false",
systemNeedsToChange ? "true" : "false");
systemNeedsToChange ? "true" : "false"); */
// Only apply theme if there's a change or no override active
if (!_state.isManualOverride && (appsNeedsToChange || systemNeedsToChange))
@@ -230,10 +223,6 @@ void LightSwitchStateManager::EvaluateAndApplyIfNeeded()
_state.isSystemLightActive = GetCurrentSystemTheme();
_state.isAppsLightActive = GetCurrentAppsTheme();
Logger::debug(L"[LightSwitchStateManager] Synced post-apply theme state — System: {}, Apps: {}",
_state.isSystemLightActive ? L"light" : L"dark",
_state.isAppsLightActive ? L"light" : L"dark");
}
_state.lastTickMinutes = now;

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
@@ -147,13 +148,14 @@
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
@@ -165,16 +167,18 @@
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />

View File

@@ -4,14 +4,15 @@
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.ML" version="1.8.2095" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
@@ -152,11 +152,11 @@
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
@@ -167,16 +167,16 @@
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Windows.CppWinRT.2.0.240111.5\\build\\native\\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.Web.WebView2.1.0.2903.40\\build\\native\\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.Web.WebView2.1.0.2903.40\\build\\native\\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Base.1.8.250831001\\build\\native\\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\\build\\native\\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\\build\\native\\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\\build\\native\\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\\build\\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\\..\\..\\..\\packages\\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\\build\\native\\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.ML" version="1.8.2095" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
</packages>

View File

@@ -39,6 +39,10 @@ type_pEnableThemeDialogTexture pEnableThemeDialogTexture;
#define WIN7_VERSION 0x106
#define WIN10_VERSION 0x206
// Default recording format frame rates
#define RECORDING_FORMAT_GIF_DEFAULT_FRAMERATE 15
#define RECORDING_FORMAT_MP4_DEFAULT_FRAMERATE 30
// Time that we'll cache live zoom window to avoid flicker
// of live zooming on Vista/ws2k8
#define LIVEZOOM_WINDOW_TIMEOUT 2*3600*1000

View File

@@ -44,11 +44,11 @@ LOGFONT g_LogFont;
BOOLEAN g_DemoTypeUserDriven = false;
TCHAR g_DemoTypeFile[MAX_PATH] = {0};
DWORD g_DemoTypeSpeedSlider = static_cast<int>(((MIN_TYPING_SPEED - MAX_TYPING_SPEED) / 2) + MAX_TYPING_SPEED);
DWORD g_RecordFrameRate = 30;
DWORD g_RecordFrameRate = 30; // We default to 30 here, but g_RecordFrameRate can be different depending on recording format and gets set accordingly
DWORD g_RecordScaling = 100;
DWORD g_RecordScalingGIF = 50;
DWORD g_RecordScalingMP4 = 100;
RecordingFormat g_RecordingFormat = RecordingFormat::GIF;
RecordingFormat g_RecordingFormat = RecordingFormat::MP4;
BOOLEAN g_CaptureAudio = FALSE;
TCHAR g_MicrophoneDeviceId[MAX_PATH] = {0};
@@ -87,8 +87,7 @@ REG_SETTING RegSettings[] = {
{ L"SnapToGrid", SETTING_TYPE_BOOLEAN, 0, &g_SnapToGrid, static_cast<DOUBLE>(g_SnapToGrid) },
{ L"ZoominSliderLevel", SETTING_TYPE_DWORD, 0, &g_SliderZoomLevel, static_cast<DOUBLE>(g_SliderZoomLevel) },
{ L"Font", SETTING_TYPE_BINARY, sizeof g_LogFont, &g_LogFont, static_cast<DOUBLE>(0) },
{ L"RecordFrameRate", SETTING_TYPE_DWORD, 0, &g_RecordFrameRate, static_cast<DOUBLE>(g_RecordFrameRate) },
{ L"RecordingFormat", SETTING_TYPE_DWORD, 0, &g_RecordingFormat, static_cast<DOUBLE>(0) },
{ L"RecordingFormat", SETTING_TYPE_DWORD, 0, &g_RecordingFormat, static_cast<DOUBLE>(g_RecordingFormat) },
{ L"RecordScalingGIF", SETTING_TYPE_DWORD, 0, &g_RecordScalingGIF, static_cast<DOUBLE>(g_RecordScalingGIF) },
{ L"RecordScalingMP4", SETTING_TYPE_DWORD, 0, &g_RecordScalingMP4, static_cast<DOUBLE>(g_RecordScalingMP4) },
{ L"CaptureAudio", SETTING_TYPE_BOOLEAN, 0, &g_CaptureAudio, static_cast<DOUBLE>(g_CaptureAudio) },

View File

@@ -168,6 +168,7 @@ BOOL g_RecordToggle = FALSE;
BOOL g_RecordCropping = FALSE;
SelectRectangle g_SelectRectangle;
std::wstring g_RecordingSaveLocation;
std::wstring g_RecordingSaveLocationGIF;
winrt::IDirect3DDevice g_RecordDevice{ nullptr };
std::shared_ptr<VideoRecordingSession> g_RecordingSession = nullptr;
std::shared_ptr<GifRecordingSession> g_GifRecordingSession = nullptr;
@@ -2173,7 +2174,10 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
CheckDlgButton( g_OptionsTabs[RECORD_PAGE].hPage, IDC_CAPTURE_AUDIO,
g_CaptureAudio ? BST_CHECKED: BST_UNCHECKED );
for (int i = 0; i < _countof(g_FramerateOptions); i++) {
//
// The framerate drop down list is not used in the current version (might be added in the future)
//
/*for (int i = 0; i < _countof(g_FramerateOptions); i++) {
_stprintf(text, L"%d", g_FramerateOptions[i]);
SendMessage(GetDlgItem(g_OptionsTabs[RECORD_PAGE].hPage, IDC_RECORD_FRAME_RATE), static_cast<UINT>(CB_ADDSTRING),
@@ -2182,7 +2186,7 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
SendMessage(GetDlgItem(g_OptionsTabs[RECORD_PAGE].hPage, IDC_RECORD_FRAME_RATE), CB_SETCURSEL, static_cast<WPARAM>(i), static_cast<LPARAM>(0));
}
}
}*/
// Add the recording format to the combo box and set the current selection
size_t selection = 0;
@@ -2345,17 +2349,8 @@ INT_PTR CALLBACK OptionsProc( HWND hDlg, UINT message,
text[2] = 0;
newTimeout = _tstoi( text );
if( g_RecordingFormat == RecordingFormat::GIF )
{
// Hardcode lower frame rate for GIFs
g_RecordFrameRate = 15;
}
else
{
g_RecordFrameRate = g_FramerateOptions[SendMessage(GetDlgItem(g_OptionsTabs[RECORD_PAGE].hPage, IDC_RECORD_FRAME_RATE), static_cast<UINT>(CB_GETCURSEL), static_cast<WPARAM>(0), static_cast<LPARAM>(0))];
}
g_RecordingFormat = static_cast<RecordingFormat>(SendMessage(GetDlgItem(g_OptionsTabs[RECORD_PAGE].hPage, IDC_RECORD_FORMAT), static_cast<UINT>(CB_GETCURSEL), static_cast<WPARAM>(0), static_cast<LPARAM>(0)));
g_RecordFrameRate = (g_RecordingFormat == RecordingFormat::GIF) ? RECORDING_FORMAT_GIF_DEFAULT_FRAMERATE : RECORDING_FORMAT_MP4_DEFAULT_FRAMERATE;
g_RecordScaling = static_cast<int>(SendMessage(GetDlgItem(g_OptionsTabs[RECORD_PAGE].hPage, IDC_RECORD_SCALING), static_cast<UINT>(CB_GETCURSEL), static_cast<WPARAM>(0), static_cast<LPARAM>(0)) * 10 + 10);
// Get the selected microphone
@@ -3536,7 +3531,16 @@ void StopRecording()
//----------------------------------------------------------------------------
auto GetUniqueRecordingFilename()
{
std::filesystem::path path{ g_RecordingSaveLocation };
std::filesystem::path path;
if (g_RecordingFormat == RecordingFormat::GIF)
{
path = g_RecordingSaveLocationGIF;
}
else
{
path = g_RecordingSaveLocation;
}
// Chop off index if it's there
auto base = std::regex_replace( path.stem().wstring(), std::wregex( L" [(][0-9]+[)]$" ), L"" );
@@ -3591,6 +3595,7 @@ winrt::fire_and_forget StartRecordingAsync( HWND hWnd, LPRECT rcCrop, HWND hWndR
auto stream = co_await file.OpenAsync( winrt::FileAccessMode::ReadWrite );
// Create the appropriate recording session based on format
OutputDebugStringW((L"Starting recording session. Framerate: " + std::to_wstring(g_RecordFrameRate) + L" scaling: " + std::to_wstring(g_RecordScaling) + L" Format: " + (g_RecordingFormat == RecordingFormat::GIF ? L"GIF" : L"MP4") + L"\n").c_str());
if (g_RecordingFormat == RecordingFormat::GIF)
{
g_GifRecordingSession = GifRecordingSession::Create(
@@ -3657,18 +3662,44 @@ winrt::fire_and_forget StartRecordingAsync( HWND hWnd, LPRECT rcCrop, HWND hWndR
saveDialog->SetFileTypes( _countof( fileTypes ), fileTypes );
}
if( g_RecordingSaveLocation.size() == 0) {
// Peek the folder Windows has chosen to display
static std::filesystem::path lastSaveFolder;
wil::unique_cotaskmem_string chosenFolderPath;
wil::com_ptr<IShellItem> currentSelectedFolder;
bool bFolderChanged = false;
if (SUCCEEDED(saveDialog->GetFolder(currentSelectedFolder.put())))
{
if (SUCCEEDED(currentSelectedFolder->GetDisplayName(SIGDN_FILESYSPATH, chosenFolderPath.put())))
{
if (lastSaveFolder != chosenFolderPath.get())
{
lastSaveFolder = chosenFolderPath.get() ? chosenFolderPath.get() : std::filesystem::path{};
bFolderChanged = true;
}
}
}
if( (g_RecordingFormat == RecordingFormat::GIF && g_RecordingSaveLocationGIF.size() == 0) || (g_RecordingFormat == RecordingFormat::MP4 && g_RecordingSaveLocation.size() == 0) || (bFolderChanged)) {
wil::com_ptr<IShellItem> shellItem;
wil::unique_cotaskmem_string folderPath;
if (SUCCEEDED(saveDialog->GetFolder(shellItem.put())) && SUCCEEDED(shellItem->GetDisplayName(SIGDN_FILESYSPATH, folderPath.put())))
g_RecordingSaveLocation = folderPath.get();
if (SUCCEEDED(saveDialog->GetFolder(shellItem.put())) && SUCCEEDED(shellItem->GetDisplayName(SIGDN_FILESYSPATH, folderPath.put()))) {
if (g_RecordingFormat == RecordingFormat::GIF) {
g_RecordingSaveLocationGIF = folderPath.get();
std::filesystem::path currentPath{ g_RecordingSaveLocationGIF };
g_RecordingSaveLocationGIF = currentPath / DEFAULT_GIF_RECORDING_FILE;
}
else {
g_RecordingSaveLocation = folderPath.get();
if (g_RecordingFormat == RecordingFormat::MP4) {
std::filesystem::path currentPath{ g_RecordingSaveLocation };
g_RecordingSaveLocation = currentPath / DEFAULT_RECORDING_FILE;
}
}
}
}
// Always use appropriate default filename based on current format
std::filesystem::path currentPath{ g_RecordingSaveLocation };
const wchar_t* defaultFile = (g_RecordingFormat == RecordingFormat::GIF) ? DEFAULT_GIF_RECORDING_FILE : DEFAULT_RECORDING_FILE;
g_RecordingSaveLocation = currentPath.parent_path() / defaultFile;
auto suggestedName = GetUniqueRecordingFilename();
saveDialog->SetFileName( suggestedName.c_str() );
@@ -3696,9 +3727,15 @@ winrt::fire_and_forget StartRecordingAsync( HWND hWnd, LPRECT rcCrop, HWND hWndR
}
else {
co_await file.MoveAndReplaceAsync( destFile );
g_RecordingSaveLocation = file.Path();
SaveToClipboard(g_RecordingSaveLocation.c_str(), hWnd);
co_await file.MoveAndReplaceAsync(destFile);
if (g_RecordingFormat == RecordingFormat::GIF) {
g_RecordingSaveLocationGIF = file.Path();
SaveToClipboard(g_RecordingSaveLocationGIF.c_str(), hWnd);
}
else {
g_RecordingSaveLocation = file.Path();
SaveToClipboard(g_RecordingSaveLocation.c_str(), hWnd);
}
}
g_bSaveInProgress = false;
@@ -4039,8 +4076,10 @@ LRESULT APIENTRY MainWndProc(
// Set g_RecordScaling based on the current recording format
if (g_RecordingFormat == RecordingFormat::GIF) {
g_RecordScaling = g_RecordScalingGIF;
g_RecordFrameRate = RECORDING_FORMAT_GIF_DEFAULT_FRAMERATE;
} else {
g_RecordScaling = g_RecordScalingMP4;
g_RecordFrameRate = RECORDING_FORMAT_MP4_DEFAULT_FRAMERATE;
}
// to support migrating from
@@ -6332,6 +6371,17 @@ LRESULT APIENTRY MainWndProc(
{
// Reload the settings. This message is called from PowerToys after a setting is changed by the user.
reg.ReadRegSettings(RegSettings);
if (g_RecordingFormat == RecordingFormat::GIF)
{
g_RecordScaling = g_RecordScalingGIF;
g_RecordFrameRate = RECORDING_FORMAT_GIF_DEFAULT_FRAMERATE;
}
else
{
g_RecordScaling = g_RecordScalingMP4;
g_RecordFrameRate = RECORDING_FORMAT_MP4_DEFAULT_FRAMERATE;
}
// Apply tray icon setting
EnableDisableTrayIcon(hWnd, g_ShowTrayIcon);

View File

@@ -64,6 +64,8 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
public string Title { get => string.IsNullOrEmpty(field) ? Name : field; protected set; } = string.Empty;
public string Id { get; protected set; } = string.Empty;
// This property maps to `IPage.IsLoading`, but we want to expose our own
// `IsLoading` property as a combo of this value and `IsInitialized`
public bool ModelIsLoading { get; protected set; } = true;
@@ -142,6 +144,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
return; // throw?
}
Id = page.Id;
Name = page.Name;
ModelIsLoading = page.IsLoading;
Title = page.Title;

View File

@@ -10,7 +10,7 @@
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools.MSIX" Version="1.7.20250829.1" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.250907003" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.251003001" />
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
<PackageVersion Include="System.Text.Json" Version="9.0.8" />

View File

@@ -15,9 +15,12 @@ public class OpenPage : EventBase, IEvent
{
public int PageDepth { get; set; }
public OpenPage(int pageDepth)
public string Id { get; set; }
public OpenPage(int pageDepth, string id)
{
PageDepth = pageDepth;
Id = id;
EventName = "CmdPal_OpenPage";
}

View File

@@ -21,7 +21,6 @@ using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Input;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media.Animation;
@@ -160,7 +159,7 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
new AsyncNavigationRequest(message.Page, message.CancellationToken),
message.WithAnimation ? DefaultPageAnimation : _noAnimation);
PowerToysTelemetry.Log.WriteEvent(new OpenPage(RootFrame.BackStackDepth));
PowerToysTelemetry.Log.WriteEvent(new OpenPage(RootFrame.BackStackDepth, message.Page.Id));
if (!ViewModel.IsNested)
{
@@ -655,15 +654,15 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page,
e.Handled = true;
break;
default:
{
// The CommandBar is responsible for handling all the item keybindings,
// since the bound context item may need to then show another
// context menu
TryCommandKeybindingMessage msg = new(ctrlPressed, altPressed, shiftPressed, winPressed, e.Key);
WeakReferenceMessenger.Default.Send(msg);
e.Handled = msg.Handled;
break;
}
{
// The CommandBar is responsible for handling all the item keybindings,
// since the bound context item may need to then show another
// context menu
TryCommandKeybindingMessage msg = new(ctrlPressed, altPressed, shiftPressed, winPressed, e.Key);
WeakReferenceMessenger.Default.Send(msg);
e.Handled = msg.Handled;
break;
}
}
}

View File

@@ -3,13 +3,13 @@
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup>
<PathToRoot>..\..\..\..\</PathToRoot>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.250907003</WasdkNuget>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.251003001</WasdkNuget>
</PropertyGroup>
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<PropertyGroup Label="Globals">
@@ -209,7 +209,7 @@
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(MSBuildThisFileDirectory)..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
@@ -228,8 +228,8 @@
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />

View File

@@ -4,14 +4,15 @@
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.ML" version="1.8.2095" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -2,7 +2,7 @@
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PathToRoot>..\..\..\..\..\</PathToRoot>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.250907003</WasdkNuget>
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.8.251003001</WasdkNuget>
<CppWinRTNuget>$(PathToRoot)packages\Microsoft.Windows.CppWinRT.2.0.240111.5</CppWinRTNuget>
<WindowsSdkBuildToolsNuget>$(PathToRoot)packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188</WindowsSdkBuildToolsNuget>
<WebView2Nuget>$(PathToRoot)packages\Microsoft.Web.WebView2.1.0.2903.40</WebView2Nuget>

View File

@@ -3,15 +3,16 @@
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.ML" version="1.8.2095" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props')" />
@@ -218,13 +219,14 @@
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets')" />
<Import Project="..\..\..\..\packages\boost.1.87.0\build\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.87.0\build\boost.targets')" />
<Import Project="..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets" Condition="Exists('..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets')" />
</ImportGroup>
@@ -240,20 +242,22 @@
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.MSIX.1.7.20250829.1\build\Microsoft.Windows.SDK.BuildTools.MSIX.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\boost.1.87.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost.1.87.0\build\boost.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost_regex-vc143.1.87.0\build\boost_regex-vc143.targets'))" />
</Target>

View File

@@ -6,14 +6,15 @@
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.ML" version="1.8.2095" targetFramework="native" />
<package id="Microsoft.Windows.SDK.BuildTools.MSIX" version="1.7.20250829.1" targetFramework="native" />
</packages>

View File

@@ -3,14 +3,15 @@
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
<!-- Windows App SDK and all transitive dependencies -->
<package id="Microsoft.WindowsAppSDK" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Base" version="1.8.250831001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Foundation" version="1.8.250906002" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.WinUI" version="1.8.250906003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.250907003" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Runtime" version="1.8.251003001" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.DWrite" version="1.8.25090401" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.InteractiveExperiences" version="1.8.250906004" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.Widgets" version="1.8.250904007" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.AI" version="1.8.37" targetFramework="native" />
<package id="Microsoft.WindowsAppSDK.ML" version="1.8.2095" targetFramework="native" />
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
</packages>

View File

@@ -14,13 +14,14 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="..\..\deps\expected.props" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" />
<Import Project="..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props" Condition="Exists('..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props')" />
<Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<ImportGroup Label="Shared" />
<PropertyGroup Label="Configuration">
@@ -141,13 +142,14 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
@@ -156,20 +158,22 @@
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.1.8.250907003\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.1.8.251003001\build\native\Microsoft.WindowsAppSDK.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Base.1.8.250831001\build\native\Microsoft.WindowsAppSDK.Base.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Foundation.1.8.250906002\build\native\Microsoft.WindowsAppSDK.Foundation.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.WinUI.1.8.250906003\build\native\Microsoft.WindowsAppSDK.WinUI.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.250907003\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.Runtime.1.8.251003001\build\native\Microsoft.WindowsAppSDK.Runtime.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.DWrite.1.8.25090401\build\Microsoft.WindowsAppSDK.DWrite.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.InteractiveExperiences.1.8.250906004\build\native\Microsoft.WindowsAppSDK.InteractiveExperiences.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WindowsAppSDK.ML.1.8.2095\build\native\Microsoft.WindowsAppSDK.ML.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />

View File

@@ -23,6 +23,8 @@ public sealed class AdvancedPasteCustomAction : Observable, IAdvancedPasteAction
private bool _isValid;
private bool _hasConflict;
private string _tooltip;
private bool _useCustomModel;
private string _customModelPath = string.Empty;
[JsonPropertyName("id")]
public int Id
@@ -122,6 +124,32 @@ public sealed class AdvancedPasteCustomAction : Observable, IAdvancedPasteAction
set => Set(ref _tooltip, value);
}
[JsonPropertyName("useCustomModel")]
public bool UseCustomModel
{
get => _useCustomModel;
set
{
if (Set(ref _useCustomModel, value))
{
UpdateIsValid();
}
}
}
[JsonPropertyName("customModelPath")]
public string CustomModelPath
{
get => _customModelPath;
set
{
if (Set(ref _customModelPath, value ?? string.Empty))
{
UpdateIsValid();
}
}
}
[JsonIgnore]
public IEnumerable<IAdvancedPasteAction> SubActions => [];
@@ -144,6 +172,8 @@ public sealed class AdvancedPasteCustomAction : Observable, IAdvancedPasteAction
CanMoveDown = other.CanMoveDown;
HasConflict = other.HasConflict;
Tooltip = other.Tooltip;
UseCustomModel = other.UseCustomModel;
CustomModelPath = other.CustomModelPath;
}
private HotkeySettings GetShortcutClone()
@@ -159,6 +189,10 @@ public sealed class AdvancedPasteCustomAction : Observable, IAdvancedPasteAction
private void UpdateIsValid()
{
IsValid = !string.IsNullOrWhiteSpace(Name) && !string.IsNullOrWhiteSpace(Prompt);
bool hasPrompt = !string.IsNullOrWhiteSpace(Prompt);
bool hasName = !string.IsNullOrWhiteSpace(Name);
bool hasModel = !UseCustomModel || !string.IsNullOrWhiteSpace(CustomModelPath);
IsValid = hasName && hasPrompt && hasModel;
}
}

View File

@@ -2,7 +2,9 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -29,6 +31,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
CloseAfterLosingFocus = false;
EnableClipboardPreview = true;
PasteAIConfiguration = new();
CustomModelStoragePath = GetDefaultCustomModelStoragePath();
}
[JsonConverter(typeof(BoolPropertyJsonConverter))]
@@ -103,7 +106,36 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[CmdConfigureIgnoreAttribute]
public PasteAIConfiguration PasteAIConfiguration { get; set; }
[JsonPropertyName("custom-model-storage-path")]
[CmdConfigureIgnoreAttribute]
public string CustomModelStoragePath { get; set; }
public override string ToString()
=> JsonSerializer.Serialize(this);
public static string GetDefaultCustomModelStoragePath()
{
try
{
var userProfile = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
if (string.IsNullOrWhiteSpace(userProfile))
{
userProfile = Environment.GetEnvironmentVariable("USERPROFILE");
}
if (string.IsNullOrWhiteSpace(userProfile))
{
var temp = Path.GetTempPath();
return Path.Combine(temp, "PowerToys", "Models");
}
return Path.Combine(userProfile, ".cache", "PowerToys");
}
catch (Exception)
{
var temp = Path.GetTempPath();
return Path.Combine(temp, "PowerToys", "Models");
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

View File

@@ -28,6 +28,8 @@
<None Remove="Assets\Settings\Icons\Models\WindowsML.svg" />
<None Remove="Assets\Settings\Modules\APDialog.dark.png" />
<None Remove="Assets\Settings\Modules\APDialog.light.png" />
<None Remove="Assets\Settings\Modules\CmdPal_Background.png" />
<None Remove="Assets\Settings\Modules\CmdPal_Hero.png" />
<None Remove="Assets\Settings\Modules\LightSwitch.png" />
<None Remove="SettingsXAML\Controls\Dashboard\CheckUpdateControl.xaml" />
<None Remove="SettingsXAML\Controls\Dashboard\ShortcutConflictControl.xaml" />
@@ -71,6 +73,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />

View File

@@ -30,6 +30,24 @@
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<InfoBar
x:Uid="AdvancedPaste_FL_PreviewMessage"
Grid.Row="1"
Padding="4"
IsClosable="False"
IsOpen="True"
Message="Foundry Local is still in Public Preview">
<InfoBar.ActionButton>
<HyperlinkButton
x:Uid="AdvancedPaste_FL_LearnMoreFoundryLocal"
Content="Learn more"
NavigateUri="https://learn.microsoft.com/azure/ai-foundry/foundry-local/what-is-foundry-local" />
</InfoBar.ActionButton>
</InfoBar>
<StackPanel
x:Name="LoadingPanel"
HorizontalAlignment="Center"
@@ -106,7 +124,7 @@
<ComboBox.Header>
<TextBlock>
<Run x:Uid="AdvancedPaste_FL_LocalModel" /><LineBreak /><Run
x:Uid="AdvancedPaste_FL_UseCLIToDownloadModels"
x:Uid="AdvancedPaste_FL_UseCliToDownloadModels"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
@@ -152,7 +170,7 @@
Spacing="8">
<Image Width="36" Source="ms-appx:///Assets/Settings/Icons/Models/FoundryLocal.svg" />
<TextBlock
x:Uid="AdvancedPaste_FL_FLNotavailableYet"
x:Uid="AdvancedPaste_FL_FLNotAvailableYet"
HorizontalAlignment="Center"
FontWeight="SemiBold"
TextAlignment="Center"

View File

@@ -381,6 +381,20 @@
</DataTemplate>
</tkcontrols:SettingsExpander.ItemTemplate>
</tkcontrols:SettingsExpander>
<tkcontrols:SettingsCard
x:Uid="AdvancedPaste_CustomModelStoragePath"
HeaderIcon="{ui:FontIcon Glyph=&#xE8B7;}"
IsEnabled="{x:Bind ViewModel.IsAIEnabled, Mode=OneWay}">
<StackPanel Orientation="Horizontal" Spacing="8">
<TextBox
Width="320"
Text="{x:Bind ViewModel.CustomModelStoragePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button
x:Uid="AdvancedPaste_CustomModelStoragePath_BrowseButton"
Click="BrowseCustomModelStoragePath_Click"
Style="{ThemeResource AccentButtonStyle}" />
</StackPanel>
</tkcontrols:SettingsCard>
<InfoBar
x:Uid="AdvancedPaste_ShortcutWarning"
IsClosable="False"
@@ -423,6 +437,31 @@
AcceptsReturn="true"
Text="{Binding Prompt, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
<ToggleSwitch
x:Uid="AdvancedPasteUI_CustomAction_UseCustomModel"
HorizontalAlignment="Left"
IsOn="{Binding UseCustomModel, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
OffContent=""
OnContent=""
Toggled="CustomActionUseCustomModel_Toggled" />
<StackPanel
Orientation="Vertical"
Spacing="8"
Visibility="{Binding UseCustomModel, Converter={StaticResource BoolToVisibilityConverter}}">
<ComboBox
x:Name="CustomActionModelComboBox"
x:Uid="AdvancedPasteUI_CustomAction_ModelPath"
Width="340"
HorizontalAlignment="Left"
ItemsSource="{x:Bind CustomModelOptions, Mode=OneWay}"
SelectedItem="{Binding CustomModelPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ToolTipService.ToolTip="{Binding CustomModelPath, Mode=OneWay}" />
<Button
x:Uid="AdvancedPasteUI_CustomAction_SelectModelButton"
HorizontalAlignment="Left"
Click="BrowseCustomActionModel_Click"
Style="{ThemeResource AccentButtonStyle}" />
</StackPanel>
</StackPanel>
</ContentDialog>

View File

@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
@@ -38,10 +39,14 @@ namespace Microsoft.PowerToys.Settings.UI.Views
private static readonly string AdvancedAISystemPromptNormalized = AdvancedAISystemPrompt.Trim();
private static readonly string SimpleAISystemPromptNormalized = SimpleAISystemPrompt.Trim();
private readonly ObservableCollection<string> _customModelOptions = new();
private AdvancedPasteViewModel ViewModel { get; set; }
public ICommand EnableAdvancedPasteAICommand => new RelayCommand(EnableAdvancedPasteAI);
public ObservableCollection<string> CustomModelOptions => _customModelOptions;
public AdvancedPastePage()
{
var settingsUtils = new SettingsUtils();
@@ -53,6 +58,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
ViewModel.PropertyChanged += AdvancedPasteViewModel_PropertyChanged;
if (FoundryLocalPicker is not null)
{
FoundryLocalPicker.CachedModels = _foundryCachedModels;
@@ -133,6 +140,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
CustomActionDialog.Title = resourceLoader.GetString("AddCustomAction");
CustomActionDialog.DataContext = ViewModel.GetNewCustomAction(resourceLoader.GetString("AdvancedPasteUI_NewCustomActionPrefix"));
CustomActionDialog.PrimaryButtonText = resourceLoader.GetString("CustomActionSave");
RefreshCustomActionModelOptions(CustomActionDialog.DataContext as AdvancedPasteCustomAction);
await CustomActionDialog.ShowAsync();
}
@@ -143,6 +151,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
CustomActionDialog.Title = resourceLoader.GetString("EditCustomAction");
CustomActionDialog.DataContext = GetBoundCustomAction(sender, e).Clone();
CustomActionDialog.PrimaryButtonText = resourceLoader.GetString("CustomActionUpdate");
RefreshCustomActionModelOptions(CustomActionDialog.DataContext as AdvancedPasteCustomAction);
await CustomActionDialog.ShowAsync();
}
@@ -256,7 +265,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
if (!string.IsNullOrEmpty(selectedFile))
{
PasteAIModelPathTextBox.Text = selectedFile;
if (ViewModel?.PasteAIProviderDraft is not null)
{
ViewModel.PasteAIProviderDraft.ModelPath = selectedFile;
@@ -264,6 +272,37 @@ namespace Microsoft.PowerToys.Settings.UI.Views
}
}
private void BrowseCustomActionModel_Click(object sender, RoutedEventArgs e)
{
string selectedFile = PickFileDialog(
"Model Files\0*.onnx;*.zip;*.model\0All Files\0*.*\0",
"Select Model File",
ViewModel?.CustomModelStoragePath);
if (string.IsNullOrEmpty(selectedFile))
{
return;
}
if (CustomActionDialog?.DataContext is AdvancedPasteCustomAction action)
{
action.CustomModelPath = NormalizeCustomModelSelectionPath(selectedFile);
RefreshCustomActionModelOptions(action);
}
}
private void BrowseCustomModelStoragePath_Click(object sender, RoutedEventArgs e)
{
IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.GetSettingsWindow());
string selectedFolder = ShellGetFolder.GetFolderDialogWithFlags(hwnd, ShellGetFolder.FolderDialogFlags._BIF_NEWDIALOGSTYLE);
if (!string.IsNullOrEmpty(selectedFolder) && ViewModel is not null)
{
ViewModel.CustomModelStoragePath = selectedFolder;
RefreshCustomActionModelOptions(CustomActionDialog?.DataContext as AdvancedPasteCustomAction);
}
}
private static string PickFileDialog(string filter, string title, string initialDir = null, int initialFilter = 0)
{
// Use Win32 OpenFileName dialog as FileOpenPicker doesn't work with elevated permissions
@@ -293,6 +332,121 @@ namespace Microsoft.PowerToys.Settings.UI.Views
return null;
}
private string NormalizeCustomModelSelectionPath(string selectedFile)
{
if (string.IsNullOrWhiteSpace(selectedFile))
{
return string.Empty;
}
try
{
var fullSelection = Path.GetFullPath(selectedFile);
var storagePath = ViewModel?.CustomModelStoragePath;
if (!string.IsNullOrWhiteSpace(storagePath))
{
var fullStorage = Path.GetFullPath(storagePath);
if (fullSelection.StartsWith(fullStorage, StringComparison.OrdinalIgnoreCase))
{
var relative = Path.GetRelativePath(fullStorage, fullSelection);
if (!string.IsNullOrEmpty(relative) && !relative.StartsWith("..", StringComparison.Ordinal))
{
return relative;
}
}
}
return fullSelection;
}
catch (Exception)
{
return selectedFile;
}
}
private void RefreshCustomActionModelOptions(AdvancedPasteCustomAction action)
{
var options = new List<string>();
var storageRoot = GetCustomModelStorageRoot();
if (!string.IsNullOrWhiteSpace(storageRoot) && Directory.Exists(storageRoot))
{
try
{
foreach (var file in Directory.EnumerateFiles(storageRoot, "*.onnx", SearchOption.AllDirectories))
{
var option = NormalizeCustomModelSelectionPath(file);
if (!string.IsNullOrWhiteSpace(option))
{
options.Add(option);
}
}
}
catch (Exception)
{
// Enumeration failures are non-fatal; leave the list empty and allow manual selection.
}
}
if (action?.UseCustomModel == true && !string.IsNullOrWhiteSpace(action.CustomModelPath))
{
options.Add(action.CustomModelPath);
}
var uniqueOptions = options
.Where(option => !string.IsNullOrWhiteSpace(option))
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(option => option, StringComparer.OrdinalIgnoreCase)
.ToList();
_customModelOptions.Clear();
foreach (var option in uniqueOptions)
{
_customModelOptions.Add(option);
}
if (action?.UseCustomModel == true && string.IsNullOrWhiteSpace(action.CustomModelPath) && _customModelOptions.Count > 0)
{
action.CustomModelPath = _customModelOptions[0];
}
}
private string GetCustomModelStorageRoot()
{
var path = ViewModel?.CustomModelStoragePath;
if (string.IsNullOrWhiteSpace(path))
{
return string.Empty;
}
try
{
path = Environment.ExpandEnvironmentVariables(path.Trim());
return Path.GetFullPath(path);
}
catch (Exception)
{
return path;
}
}
private void AdvancedPasteViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (string.Equals(e.PropertyName, nameof(AdvancedPasteViewModel.CustomModelStoragePath), StringComparison.Ordinal))
{
RefreshCustomActionModelOptions(CustomActionDialog?.DataContext as AdvancedPasteCustomAction);
}
}
private void CustomActionUseCustomModel_Toggled(object sender, RoutedEventArgs e)
{
if (CustomActionDialog?.DataContext is AdvancedPasteCustomAction action && action.UseCustomModel)
{
RefreshCustomActionModelOptions(action);
}
}
private void ShowApiKeySavedMessage(string configType)
{
// This would typically show a TeachingTip or InfoBar
@@ -992,7 +1146,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
FoundryLocalPicker.LoadRequested -= FoundryLocalPicker_LoadRequested;
}
ViewModel?.Dispose();
if (ViewModel is not null)
{
ViewModel.PropertyChanged -= AdvancedPasteViewModel_PropertyChanged;
ViewModel.Dispose();
}
_disposed = true;
GC.SuppressFinalize(this);

View File

@@ -10,40 +10,200 @@
xmlns:ui="using:CommunityToolkit.WinUI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<Grid>
<Grid
MaxWidth="1000"
Padding="16,0,16,0"
VerticalAlignment="Top"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="16"
RowSpacing="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<tkcontrols:OpacityMaskView Margin="-16,0,-16,0" HorizontalAlignment="Stretch">
<tkcontrols:OpacityMaskView.OpacityMask>
<Rectangle>
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0.50" Color="Black" />
<GradientStop Offset="0.75" Color="#80000000" />
<GradientStop Offset="0.95" Color="Transparent" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</tkcontrols:OpacityMaskView.OpacityMask>
<Grid Height="560">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image
Grid.RowSpan="3"
HorizontalAlignment="Stretch"
Source="/Assets/Settings/Modules/CmdPal_Background.png"
Stretch="UniformToFill" />
<TextBlock
Margin="0,24,0,12"
HorizontalAlignment="Center"
FontSize="36"
FontWeight="Bold"
Text="Command Palette">
<TextBlock.Foreground>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0.0" Color="#FFB9EBFF" />
<GradientStop Offset="0.49" Color="#FF86CBFF" />
<GradientStop Offset="1.0" Color="#FFA1E7FF" />
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<TextBlock
Grid.Row="1"
HorizontalAlignment="Center"
Foreground="White"
TextAlignment="Center"
TextWrapping="Wrap">
<Run x:Uid="CmdPal_Description" />
<Hyperlink NavigateUri="">
<Run x:Uid="LearnMore_CmdPal.Text" Foreground="White" />
</Hyperlink>
</TextBlock>
<Image
Grid.Row="2"
Margin="0,16,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Source="/Assets/Settings/Modules/CmdPal_Hero.png"
Stretch="Uniform" />
</Grid>
</tkcontrols:OpacityMaskView>
<controls:SettingsPageControl x:Uid="CmdPal" ModuleImageSource="ms-appx:///Assets/Settings/Modules/CmdPal.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel ChildrenTransitions="{StaticResource SettingsCardsAnimations}" Orientation="Vertical">
<Grid
Grid.Row="1"
Margin="0,-12,0,24"
ColumnSpacing="32"
RowSpacing="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<FontIcon
HorizontalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Glyph="&#xEB3B;" />
<TextBlock
Grid.Row="1"
HorizontalAlignment="Center"
TextAlignment="Center"
TextWrapping="Wrap">
<Run x:Uid="CmdPal_ExtensibleHeader" FontWeight="SemiBold" /> <LineBreak />
<Run
x:Uid="CmdPal_ExtensibleDescription"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
<FontIcon
Grid.Column="1"
HorizontalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Glyph="&#xE945;" />
<TextBlock
Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
TextAlignment="Center"
TextWrapping="Wrap">
<Run x:Uid="CmdPal_FastHeader" FontWeight="SemiBold" /> <LineBreak />
<Run
x:Uid="CmdPal_FastDescription"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
<FontIcon
Grid.Column="2"
HorizontalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Glyph="&#xE790;" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
HorizontalAlignment="Center"
TextAlignment="Center"
TextWrapping="Wrap">
<Run x:Uid="CmdPal_ModernHeader" FontWeight="SemiBold" /> <LineBreak />
<Run
x:Uid="CmdPal_ModernDescription"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</TextBlock>
</Grid>
<StackPanel
Grid.Row="2"
Margin="0,8,0,0"
Orientation="Vertical"
Spacing="{StaticResource SettingsCardSpacing}">
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.IsEnabledGpoConfigured, Mode=OneWay}">
<tkcontrols:SettingsCard
Name="CmdPalEnableCmdPal"
x:Uid="CmdPal_Enable_CmdPal"
HorizontalAlignment="Stretch"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/CmdPal.png}">
<ToggleSwitch IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
</controls:GPOInfoControl>
<controls:SettingsGroup x:Uid="CmdPal_Activation_GroupSettings" IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<tkcontrols:SettingsCard
Name="CmdPalActivationShortcut"
x:Uid="CmdPal_ActivationShortcut"
HeaderIcon="{ui:FontIcon Glyph=&#xEDA7;}">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
HotkeySettings="{x:Bind Path=ViewModel.Hotkey, Mode=OneWay}"
IsEnabled="False" />
<tkcontrols:SettingsCard.Description>
<HyperlinkButton
x:Name="CmdPalSettingsDeeplink"
x:Uid="CmdPal_DeeplinkContent"
Click="CmdPalSettingsDeeplink_Click" />
</tkcontrols:SettingsCard.Description>
</tkcontrols:SettingsCard>
</controls:SettingsGroup>
<tkcontrols:SettingsCard
x:Uid="CmdPal_Launch"
Grid.Row="3"
ActionIcon="{ui:FontIcon Glyph=&#xE8A7;}"
Click="LaunchCard_Click"
Header="Launch Command Palette"
HeaderIcon="{ui:FontIcon Glyph=&#xE945;}"
IsClickEnabled="True"
IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}">
<ItemsControl
AutomationProperties.AccessibilityView="Raw"
IsTabStop="False"
ItemsSource="{x:Bind Path=ViewModel.Hotkey.GetKeysList(), Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:KeyVisual
Padding="8,8,8,8"
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Content="{Binding}"
Style="{StaticResource AccentKeyVisualStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Uid="CmdPal_Settings"
Grid.Row="4"
ActionIcon="{ui:FontIcon Glyph=&#xE8A7;}"
Click="SettingsCard_Click"
HeaderIcon="{ui:FontIcon Glyph=&#xE713;}"
IsClickEnabled="True"
IsEnabled="{x:Bind ViewModel.IsEnabled, Mode=OneWay}" />
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink x:Uid="LearnMore_CmdPal" Link="https://aka.ms/PowerToysOverview_CmdPal" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Grid>
</Grid>
</local:NavigablePage>

View File

@@ -63,12 +63,20 @@ namespace Microsoft.PowerToys.Settings.UI.Views
}
}
private void CmdPalSettingsDeeplink_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
private void SettingsCard_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
// Launch CmdPal settings window as normal user using explorer
string launchPath = "explorer.exe";
string launchArgs = "x-cmdpal://settings";
LaunchApp(launchPath, launchArgs);
}
private void LaunchCard_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
// Launch CmdPal window as normal user using explorer
string launchPath = "explorer.exe";
string launchArgs = "x-cmdpal";
LaunchApp(launchPath, launchArgs);
}
}
}

View File

@@ -659,6 +659,22 @@ Please review the placeholder content that represents the final terms and usage
<data name="AdvancedPaste_Additional_Actions_GroupSettings.Header" xml:space="preserve">
<value>Custom actions</value>
</data>
<data name="AdvancedPaste_CustomModelStoragePath.Header" xml:space="preserve">
<value>Custom model storage path</value>
<comment>Header for the settings card that lets users choose where custom models are stored.</comment>
</data>
<data name="AdvancedPaste_CustomModelStoragePath.Description" xml:space="preserve">
<value>PowerToys looks in this folder when custom actions use locally downloaded models.</value>
</data>
<data name="AdvancedPaste_CustomModelStoragePath_BrowseButton.Content" xml:space="preserve">
<value>Browse</value>
</data>
<data name="AdvancedPasteCustomModelNotFound" xml:space="preserve">
<value>The custom model could not be found. Verify the path and try again.</value>
</data>
<data name="AdvancedPasteCustomModelInferenceError" xml:space="preserve">
<value>PowerToys couldn't generate a response using the selected custom model.</value>
</data>
<data name="AdvancedPaste_FoundryLocal_LegalDescription" xml:space="preserve">
<value>You're running local models directly on your device. Their behavior may vary or be unpredictable.</value>
</data>
@@ -2044,6 +2060,20 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
<data name="AdvancedPasteUI_CustomAction_Prompt.Header" xml:space="preserve">
<value>Prompt</value>
</data>
<data name="AdvancedPasteUI_CustomAction_UseCustomModel.Header" xml:space="preserve">
<value>Use custom model</value>
<comment>Toggle allowing the user to choose a locally stored model for the custom action.</comment>
</data>
<data name="AdvancedPasteUI_CustomAction_ModelPath.Header" xml:space="preserve">
<value>Model path</value>
<comment>Label for the text box showing the selected custom model path.</comment>
</data>
<data name="AdvancedPasteUI_CustomAction_ModelPath.PlaceholderText" xml:space="preserve">
<value>Select a local model file</value>
</data>
<data name="AdvancedPasteUI_CustomAction_SelectModelButton.Content" xml:space="preserve">
<value>Choose model</value>
</data>
<data name="CustomActionDialog.SecondaryButtonText" xml:space="preserve">
<value>Cancel</value>
</data>
@@ -5159,25 +5189,12 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<data name="Shell_TopLevelSystemTools.Content" xml:space="preserve">
<value>System Tools</value>
</data>
<data name="CmdPal.ModuleTitle" xml:space="preserve">
<value>Command Palette</value>
</data>
<data name="CmdPal_ShortDescription" xml:space="preserve">
<value>A better quick launcher</value>
</data>
<data name="CmdPal_ActivationDescription" xml:space="preserve">
<value>Open Command Palette</value>
</data>
<data name="CmdPal_Enable_CmdPal.Header" xml:space="preserve">
<value>Enable Command Palette</value>
<comment>"Command Palette" is the name of the utility.</comment>
</data>
<data name="CmdPal.ModuleDescription" xml:space="preserve">
<value>A fully extensible quick launcher with a richer display and additional capabilities without sacrificing performance.</value>
<comment>Command Palette is a product name, do not loc</comment>
</data>
<data name="LearnMore_CmdPal.Text" xml:space="preserve">
<value>Learn more about Command Palette</value>
<comment>Command Palette is a product name, do not loc</comment>
<value>Learn more</value>
</data>
<data name="Shell_CmdPal.Content" xml:space="preserve">
<value>Command Palette</value>
@@ -5185,11 +5202,11 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
</data>
<data name="Oobe_CmdPal.Description" xml:space="preserve">
<value>A fully extensible quick launcher with a richer display and additional capabilities without sacrificing performance.</value>
<comment>"Command Palette" is a product name</comment>
<comment>Command Palette is a product name, do not loc</comment>
</data>
<data name="Oobe_CmdPal.Title" xml:space="preserve">
<value>Command Palette</value>
<comment>"Command Palette" is a product name</comment>
<comment>Command Palette is a product name, do not loc</comment>
</data>
<data name="Oobe_CmdPal_HowToUse.Text" xml:space="preserve">
<value>and start typing!</value>
@@ -5222,14 +5239,8 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<data name="RetryLabel.Text" xml:space="preserve">
<value>Retry</value>
</data>
<data name="CmdPal_Activation_GroupSettings.Header" xml:space="preserve">
<value>Activation</value>
</data>
<data name="CmdPal_ActivationShortcut.Header" xml:space="preserve">
<value>Activation shortcut</value>
</data>
<data name="CmdPal_DeeplinkContent.Content" xml:space="preserve">
<value>Open Command Palette settings to customize the activation shortcut</value>
<data name="CmdPal_Settings.Header" xml:space="preserve">
<value>Settings</value>
</data>
<data name="Help_chromaCIE" xml:space="preserve">
<value>chroma (CIE LCh)</value>
@@ -5693,14 +5704,14 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<value>Foundry Local model</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_UseCLIToDownloadModels.Text" xml:space="preserve">
<data name="AdvancedPaste_FL_UseCliToDownloadModels.Text" xml:space="preserve">
<value>Use the Foundry Local CLI to download models that run locally on-device. They'll appear here.</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
<data name="AdvancedPaste_FL_RefreshModelList.Text" xml:space="preserve">
<value>Refresh model list</value>
</data>
<data name="AdvancedPaste_FL_FLNotavailableYet.Text" xml:space="preserve">
<data name="AdvancedPaste_FL_FLNotAvailableYet.Text" xml:space="preserve">
<value>Foundry Local is not available on this device yet.</value>
<comment>Do not localize "Foundry Local", it's a product name</comment>
</data>
@@ -5753,4 +5764,51 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
<data name="AdvancedPaste_EnableClipboardPreview.Description" xml:space="preserve">
<value>Display a preview of the current clipboard content</value>
</data>
<data name="AdvancedPaste_FL_LearnMoreFoundryLocal.Content" xml:space="preserve">
<value>Learn more</value>
</data>
<data name="AdvancedPaste_FL_PreviewMessage.Message" xml:space="preserve">
<value>Foundry Local is still in public preview</value>
<comment>Do not loc "Foundry Local"</comment>
</data>
<data name="CmdPal_Settings.Description" xml:space="preserve">
<value>Configure the activation shortcut, extensions, behavior and much more</value>
</data>
<data name="CmdPal_Launch.Header" xml:space="preserve">
<value>Open Command Palette</value>
<comment>Command Palette is a product name, do not loc</comment>
</data>
<data name="CmdPal_ShortDescription" xml:space="preserve">
<value>A better quick launcher</value>
</data>
<data name="CmdPal_Description.Text" xml:space="preserve">
<value>Find files, launch apps, and do so much more with the most extensible quick launcher.</value>
</data>
<data name="CmdPal.ModuleTitle" xml:space="preserve">
<value>Command Palette</value>
<comment>Command Palette is a product name, do not loc</comment>
</data>
<data name="CmdPal_ActivationDescription" xml:space="preserve">
<value>Open Command Palette</value>
<comment>Command Palette is a product name, do not loc</comment>
</data>
<data name="CmdPal_ExtensibleDescription.Text" xml:space="preserve">
<value>Powerful extensions help you do more</value>
</data>
<data name="CmdPal_ExtensibleHeader.Text" xml:space="preserve">
<value>Extensible</value>
</data>
<data name="CmdPal_FastDescription.Text" xml:space="preserve">
<value>Find files and launch apps in an instant</value>
</data>
<data name="CmdPal_FastHeader.Text" xml:space="preserve">
<value>Fast</value>
</data>
<data name="CmdPal_ModernHeader.Text" xml:space="preserve">
<value>Beautiful</value>
</data>
<data name="CmdPal_ModernDescription.Text" xml:space="preserve">
<value>A modern UI built with Fluent Design</value>
<comment>Fluent Design is a product name, do not loc</comment>
</data>
</root>

View File

@@ -8,6 +8,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
using System.Linq;
using System.Runtime.Versioning;
@@ -98,6 +99,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SetupSettingsFileWatcher();
InitializePasteAIProviderState();
EnsureCustomModelStoragePathInitialized();
InitializeEnabledValue();
MigrateLegacyAIEnablement();
@@ -542,6 +544,24 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public string CustomModelStoragePath
{
get => _advancedPasteSettings.Properties.CustomModelStoragePath;
set
{
var normalized = NormalizeDirectoryPath(value);
var current = NormalizeDirectoryPath(_advancedPasteSettings.Properties.CustomModelStoragePath);
if (!string.Equals(current, normalized, StringComparison.OrdinalIgnoreCase))
{
_advancedPasteSettings.Properties.CustomModelStoragePath = normalized;
EnsureDirectoryExists(normalized);
OnPropertyChanged(nameof(CustomModelStoragePath));
SaveAndNotifySettings();
}
}
}
public bool EnableClipboardPreview
{
get => _advancedPasteSettings.Properties.EnableClipboardPreview;
@@ -1213,6 +1233,13 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
OnPropertyChanged(nameof(CloseAfterLosingFocus));
}
if (!string.Equals(NormalizeDirectoryPath(target.CustomModelStoragePath), NormalizeDirectoryPath(source.CustomModelStoragePath), StringComparison.OrdinalIgnoreCase))
{
target.CustomModelStoragePath = NormalizeDirectoryPath(source.CustomModelStoragePath);
EnsureDirectoryExists(target.CustomModelStoragePath);
OnPropertyChanged(nameof(CustomModelStoragePath));
}
if (target.EnableClipboardPreview != source.EnableClipboardPreview)
{
target.EnableClipboardPreview = source.EnableClipboardPreview;
@@ -1447,5 +1474,59 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
customAction.CanMoveDown = index != _customActions.Count - 1;
}
}
private void EnsureCustomModelStoragePathInitialized()
{
var path = NormalizeDirectoryPath(_advancedPasteSettings.Properties.CustomModelStoragePath);
if (string.IsNullOrWhiteSpace(path))
{
path = NormalizeDirectoryPath(AdvancedPasteProperties.GetDefaultCustomModelStoragePath());
_advancedPasteSettings.Properties.CustomModelStoragePath = path;
SaveAndNotifySettings();
}
EnsureDirectoryExists(path);
OnPropertyChanged(nameof(CustomModelStoragePath));
}
private static string NormalizeDirectoryPath(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
return string.Empty;
}
try
{
path = path.Trim();
if (path.Length == 0)
{
return string.Empty;
}
path = Environment.ExpandEnvironmentVariables(path);
return Path.GetFullPath(path);
}
catch (Exception)
{
return path;
}
}
private static void EnsureDirectoryExists(string path)
{
if (string.IsNullOrWhiteSpace(path))
{
return;
}
try
{
Directory.CreateDirectory(path);
}
catch (Exception)
{
}
}
}
}