Compare commits

..

39 Commits

Author SHA1 Message Date
Michael Jolley
42bf5ad885 More refreshing 2025-12-01 10:20:10 -06:00
Michael Jolley
0b10a15a8a More service stuff 2025-11-25 15:15:31 -06:00
Michael Jolley
c755b8585a More service stuff 2025-11-24 22:48:27 -06:00
Michael Jolley
bfc1bcae6d More refreshing 2025-11-20 21:52:02 -06:00
Michael Jolley
c0f6a3f9f4 First commit of refresh 2025-11-20 17:28:05 -06:00
Jiří Polášek
9fbd3de3a2 CmdPal: Add native debugging launch profile to launchSettings.json (#43718)
## Summary of the Pull Request

See title. 

I’m too lazy to open the dialog and then revert the change later.

<!-- 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-20 09:23:42 -06:00
Kai Tao
4a0d9912ae Advanced Paste: No cache for foundry local model list (#43716)
<!-- 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
Cache of the downloaded model will make the newly added model only work
after running of powertoys, this disable the cache, so just downloaded
model will take effect immediately

<!-- 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
Validated locally
2025-11-20 09:57:29 +08:00
Dave Rayment
15c79a0176 [Settings] Fix inconsistent description text for the mouse tools (#43651)
<!-- 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
Change some of the mouse utilities' descriptions from declarative to
imperative, to match best practice and to be consistent with the other
descriptions.

<!-- 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
- Confirmed the changed descriptions were updated in Settings.
2025-11-19 16:50:25 +08:00
Dave Rayment
97d46efec2 [Settings] Fix Dashboard toggle glitches and sorting UI (#43626)
## Summary of the Pull Request
Fixes two UI bugs in the Settings Dashboard: module list glitching when
toggling modules, and incorrect sort menu checkmarks.

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

- [x] Closes: #43624 
- [x] Closes: #43625
- [ ] **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

### User-Facing Fixes

#### 1. Module list glitching when toggling enabled state
When enabling or disabling a module from the "Utilities" list, the
entire list would flicker and redraw, causing other toggles to glitch.
This made it appear as if multiple modules were being affected by a
single change.

**Root cause**
The `AllModules` ObservableCollection was being completely cleared and
re-populated on every change, forcing the UI to destroy and recreate all
list items.

**Fix**
Refactored collection updates to modify items in-place:
- Introduced `_moduleItems` master list, built once during
initialization.
- `RefreshModuleList()` now updates properties without clearing
collections
- `SortModuleList()` uses `ObservableCollection.Move()` instead of
`Clear()`/`Add()`

#### 2. Incorrect sort menu checkmark behaviour
The checkmark in the "Sort by" menu would not update correctly when
changing sort order, sometimes showing the incorrect item checked, or
even both at once.

**Root cause**
The `IsChecked` prop on the `ToggleMenuFlyoutItem` is bound to
`DashboardSortOrder`, but the binding was not updating because the
ViewModel didn't raise a property change notification when the sort
order was changed.

**Fix**
Added `OnPropertyChanged(nameof(DashboardSortOrder))` in
`SortModuleList()`.

### Code quality improvements

1. Renamed `GetShortcutModules()` to `RefreshShortcutModules()`. The
original name implied a getter, but the routine actually affects state
by rebuilding the shortcut and action lists, violating the Command-Query
Separation principle.
2. Added an `_isUpdatingFromUI` flag as a defensive measure against
circular updates when a UI toggle is changed.
3. Separation of concerns for operations on the modules list. Building,
sorting and refreshing it are separated.
4. Added comments and XML doc headers for new methods. Included brief
description of GPO locking behaviour.

<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
- Verified that toggling modules in the list no longer causes the list
to flicker or for other toggles to glitch.
- Confirmed that the sort order checkmarks update correctly and reflect
the current sort order.
- Tested GPO policy settings are still queried as before.
- Checked sort behaviour is unaffected.

## Videos

*Sorting UI*

https://github.com/user-attachments/assets/3484bf63-2946-4460-83a5-361fa7e41c82

*Toggle behaviour*

https://github.com/user-attachments/assets/1fae5429-6fa3-4431-80f3-0907dab4f326

---------

Co-authored-by: Gordon Lam (SH) <yeelam@microsoft.com>
2025-11-19 16:49:40 +08:00
Kai Tao
46242b384e 96 release change log (#43330)
<!-- 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
- [ ] **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

---------

Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
Signed-off-by: Shawn Yuan <shuai.yuan.zju@gmail.com>
Co-authored-by: Jiří Polášek <me@jiripolasek.com>
Co-authored-by: Jaylyn Barbee <51131738+Jaylyn-Barbee@users.noreply.github.com>
Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
Co-authored-by: leileizhang <leilzh@microsoft.com>
Co-authored-by: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: niels9001 <9866362+niels9001@users.noreply.github.com>
Co-authored-by: Niels Laute <niels.laute@live.nl>
Co-authored-by: Dave Rayment <dave.rayment@gmail.com>
Co-authored-by: Gleb Khmyznikov <gleb.khmyznikov@gmail.com>
Co-authored-by: Gordon Lam (SH) <yeelam@microsoft.com>
Co-authored-by: Juju Anselum J <106316316+anselumjuju@users.noreply.github.com>
Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
Co-authored-by: Leon Zandman <leon@wirwar.com>
Co-authored-by: Leon Zandman <lzandman@rdw.nl>
Co-authored-by: moooyo <42196638+moooyo@users.noreply.github.com>
Co-authored-by: Yu Leng <yuleng@microsoft.com>
Co-authored-by: Mike Griese <migrie@microsoft.com>
Co-authored-by: Michael Jolley <mike@baldbeardedbuilder.com>
Co-authored-by: Mario Hewardt <marioh@microsoft.com>
Co-authored-by: Alex Mihaiuc <69110671+foxmsft@users.noreply.github.com>
Co-authored-by: Mike Hall <mikehall@microsoft.com>
Co-authored-by: Trevor <ngo.trev.95@gmail.com>
2025-11-19 16:25:52 +08:00
Niels Laute
84be261581 Logo change for Azure Inference (#43686)
<!-- 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-19 11:19:38 +08:00
Niels Laute
5a8095b704 Loc bug (#43685)
<!-- 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-19 10:32:14 +08:00
Niels Laute
417c1a6b98 Update FoundryLocal.svg (#43682)
<!-- 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-19 08:21:14 +08:00
leileizhang
2593149d22 Fix OOBE Mouse Utilities crash by correcting localization key (#43664)
<!-- 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

- The OOBE Mouse Utilities page crashed when selected because the
TextBlock with x:Uid="Oobe_MouseUtils_MousePointerCrosshairs" tried to
bind a Description property that doesn’t exist.
- Updated Resources.resw so the string entry is named
Oobe_MouseUtils_MousePointerCrosshairs_Description.Text, matching the
markdown description control instead of the TextBlock.
- With the correct resource key, the XAML loader no longer resolves an
invalid property and navigation succeeds.

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

- [x] Closes:  #43663
<!-- - [ ] 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-18 14:22:03 +08:00
Kai Tao
0b50c38fe1 Advanced Paste: Refresh environment if foundry is not present (#43662)
<!-- 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
As title
<!-- 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

[12:55:29.6763496] [Info] FoundryClient.cs::CreateAsync::23
    [FoundryClient] First attempt failed, refreshing PATH and retrying
[12:55:29.6766491] [Info] FoundryClient.cs::RefreshEnvironmentPath::225
    [FoundryClient] Refreshing PATH environment variable from system
[12:55:29.6768710] [Info] FoundryClient.cs::RefreshEnvironmentPath::266
    [FoundryClient] Updating process PATH with latest system values
[12:55:29.6769080] [Info] FoundryClient.cs::TryCreateClientAsync::33
    [FoundryClient] Creating Foundry Local client
[12:55:29.6769312] [Info] FoundryClient.cs::TryCreateClientAsync::45
[FoundryClient] Starting Foundry service using
manager.StartServiceAsync()
[12:55:29.9807668] [Info] FoundryClient.cs::TryCreateClientAsync::48
    [FoundryClient] Foundry service started successfully


Verified, fist launch successfully
2025-11-18 12:59:52 +08:00
Niels Laute
840808b465 [AP] Adding a single scrollviewer and fixing hidden tabstop (#43660)
<!-- 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

- [x] Closes: #43655
<!-- - [ ] 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-18 10:28:40 +08:00
Jiří Polášek
b50df36b70 Setup: Hide apps in PowerToys.SpareApps package from Start Menu (#43650)
<!-- 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 PR updates the Appx manifest for PowerToys.SpareApps to hide the
apps from the Start Menu, as they lack proper visual elements like icons
and text.

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

- [x] Closes: #43647
<!-- - [ ] 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-18 10:00:37 +08:00
Jiří Polášek
b94593ef73 Settings: Add ScrollViewer to Command Palette page in PowerToys Settings (#43649) 2025-11-18 00:55:14 +01:00
Mario Hewardt
7a01d56179 Updates version for standalone release (#43645)
<!-- 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
Updates the version for standalone release

<!-- 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 23:26:42 +08:00
Kai Tao
130e9a0a68 cmdpal: Fix launch by button in settings not work (#43634)
<!-- 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
Shell does not know it's a protocol, so add protocol to it.


<!-- 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
Locally verified
2025-11-17 12:55:22 +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
1884e6abc1 Remove unused properties in AP (#43564)
<!-- 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 pull request removes legacy provider configuration migration logic
and associated data structures from the Advanced Paste AI provider
settings. The changes simplify the codebase by eliminating support for
legacy provider configuration snapshots and related migration methods,
focusing configuration management on the current provider model.

## 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

---------

Signed-off-by: Shawn Yuan (from Dev Box) <shuaiyuan@microsoft.com>
2025-11-14 16:56:23 +08:00
leileizhang
ad4b553bb1 Remove all AdvancedPaste stored keys during uninstall (#43563)
<!-- 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
Remove all AdvancedPaste stored keys during uninstall
<!-- 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-14 16:15:15 +08:00
Dustin L. Howett
193d9aacbe BugReportTool: replace cziplib with tar.exe (#41127)
BugReportTool is the last consumer in the PowerToys repo of cziplib, a
library we use to produce ZIP files.

This pull request replaces cziplib with a simple CreateProcess call that
spawns `tar.exe`, which comes with Windows as of RS4 and can produce ZIP
files!

I've tested this by producing a bug report archive and attempting to
open it with File Explorer. It works fine.

We have taken every precaution to ensure that we do not allow any
attacker-controlled input to tar's command line. We are *not* using
`system()`, and we are not opening up a vector through which a nefarious
caller can perform shell injection.

We do not pass filenames to tar except that of the final archive. We do
not pass directory names to tar; we rely on the current directory
instead.
2025-11-13 15:59:21 -08:00
Niels Laute
483e773299 [CursorWRap] Revert the shortcut removal (#43537)
See title
2025-11-13 22:37:13 +08:00
Niels Laute
dd4c7ba57e [Advanced Paste] Localization (#43536)
More strings to loc, and re-ordering a few settings.
2025-11-13 22:36:35 +08:00
dependabot[bot]
29534601be Build(deps): Bump actions/setup-dotnet from 4 to 5 (#41693)
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet)
from 4 to 5.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/setup-dotnet/releases">actions/setup-dotnet's
releases</a>.</em></p>
<blockquote>
<h2>v5.0.0</h2>
<h2>What's Changed</h2>
<h3>Breaking Changes</h3>
<ul>
<li>Upgrade to Node.js 24 and modernize async usage by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/654">actions/setup-dotnet#654</a></li>
</ul>
<p>Make sure your runner is updated to this version or newer to use this
release. v2.327.1 <a
href="https://github.com/actions/runner/releases/tag/v2.327.1">Release
Notes</a></p>
<h3>Dependency Updates</h3>
<ul>
<li>Upgrade <code>@​action/cache</code> from 4.0.2 to 4.0.3 by <a
href="https://github.com/aparnajyothi-y"><code>@​aparnajyothi-y</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/622">actions/setup-dotnet#622</a></li>
<li>Upgrade husky from 8.0.3 to 9.1.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/591">actions/setup-dotnet#591</a></li>
<li>Upgrade <code>@​actions/glob</code> from 0.4.0 to 0.5.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/594">actions/setup-dotnet#594</a></li>
<li>Upgrade eslint-config-prettier from 9.1.0 to 10.1.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/639">actions/setup-dotnet#639</a></li>
<li>Upgrade undici from 5.28.5 to 5.29.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/641">actions/setup-dotnet#641</a></li>
<li>Upgrade form-data to bring in fix for critical vulnerability by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-dotnet/pull/652">actions/setup-dotnet#652</a></li>
<li>Upgrade actions/checkout from 4 to 5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/662">actions/setup-dotnet#662</a></li>
</ul>
<h3>Bug Fixes</h3>
<ul>
<li>Remove Support for older .NET Versions and Update installers scripts
by <a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a> in
<a
href="https://redirect.github.com/actions/setup-dotnet/pull/647">actions/setup-dotnet#647</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/gowridurgad"><code>@​gowridurgad</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/647">actions/setup-dotnet#647</a></li>
<li><a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/654">actions/setup-dotnet#654</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-dotnet/compare/v4...v5.0.0">https://github.com/actions/setup-dotnet/compare/v4...v5.0.0</a></p>
<h2>v4.3.1</h2>
<h2>What's Changed</h2>
<ul>
<li><code>v4</code> - Remove <code>azureedge.net</code> fallback logic
and update install scripts by <a
href="https://github.com/zaataylor"><code>@​zaataylor</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/572">actions/setup-dotnet#572</a>
As outlined in<a
href="https://devblogs.microsoft.com/dotnet/critical-dotnet-install-links-are-changing/#call-to-action">
Critical .NET Install Links Are Changing</a>, remove the storage account
fallback logic added for v4 in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/566">actions/setup-dotnet#566</a>
and update the install scripts accordingly.
<strong>Related issue</strong>: <a
href="https://redirect.github.com/dotnet/install-scripts/issues/559">dotnet/install-scripts#559</a></li>
<li>upgrade <code>@​actions/cache</code> to 4.0.2 by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/615">actions/setup-dotnet#615</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/setup-dotnet/compare/v4...v4.3.1">https://github.com/actions/setup-dotnet/compare/v4...v4.3.1</a></p>
<h2>v4.3.0</h2>
<h2>What's Changed</h2>
<ul>
<li>README update - add permissions section by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/587">actions/setup-dotnet#587</a></li>
<li>Configure Dependabot settings by <a
href="https://github.com/HarithaVattikuti"><code>@​HarithaVattikuti</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/585">actions/setup-dotnet#585</a></li>
<li>Upgrade <strong>cache</strong> from 3.2.4 to 4.0.0 by <a
href="https://github.com/aparnajyothi-y"><code>@​aparnajyothi-y</code></a>
in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/586">actions/setup-dotnet#586</a></li>
<li>Upgrade <strong>actions/publish-immutable-action</strong> from 0.0.3
to 0.0.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/590">actions/setup-dotnet#590</a></li>
<li>Upgrade <strong><code>@​actions/http-client</code></strong> from
2.2.1 to 2.2.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/592">actions/setup-dotnet#592</a></li>
<li>Upgrade <strong>undici</strong> from 5.28.4 to 5.28.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/596">actions/setup-dotnet#596</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/benwells"><code>@​benwells</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/587">actions/setup-dotnet#587</a></li>
<li><a
href="https://github.com/aparnajyothi-y"><code>@​aparnajyothi-y</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/setup-dotnet/pull/586">actions/setup-dotnet#586</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="d4c94342e5"><code>d4c9434</code></a>
Update to Node.js 24 and modernize async usage (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/654">#654</a>)</li>
<li><a
href="5c125af7da"><code>5c125af</code></a>
Bump actions/checkout from 4 to 5 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/662">#662</a>)</li>
<li><a
href="87c6e11776"><code>87c6e11</code></a>
Bumps form-data (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/652">#652</a>)</li>
<li><a
href="06a5327ecf"><code>06a5327</code></a>
Bump undici from 5.28.5 to 5.29.0 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/641">#641</a>)</li>
<li><a
href="e8e5b8203e"><code>e8e5b82</code></a>
Bump eslint-config-prettier from 9.1.0 to 10.1.5 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/639">#639</a>)</li>
<li><a
href="bf4cd79173"><code>bf4cd79</code></a>
Bump <code>@​actions/glob</code> from 0.4.0 to 0.5.0 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/594">#594</a>)</li>
<li><a
href="4ddad1c881"><code>4ddad1c</code></a>
Bump husky from 8.0.3 to 9.1.7 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/591">#591</a>)</li>
<li><a
href="0f55b457d2"><code>0f55b45</code></a>
removes end-of-line dotnet versions (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/647">#647</a>)</li>
<li><a
href="267870a9c4"><code>267870a</code></a>
upgrade actions/cache to 4.0.3 (<a
href="https://redirect.github.com/actions/setup-dotnet/issues/622">#622</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/setup-dotnet/compare/v4...v5">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-dotnet&package-manager=github_actions&previous-version=4&new-version=5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-13 06:08:12 -06:00
Guilherme
74225b01ce [CmdPal] Enhance ToggleSetting's Label and Description layout (#43472)
<!-- 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 PR changes the positioning of Label and Description from
ToggleSetting, making it more similar to
`CheckBoxWithDescriptionControl` used in Settings.
<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #39283 
- [ ] **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
I initially tried solving this by using a Regex on the card JSON to
replace all `Input.Toggle` elements with the new `ColumnSet` structure.
However, since `ToggleSetting.cs` already serves as a wrapper for
creating an Input.Toggle, I decided it was more effective to update the
declaration inside the `ToDictionary()` method directly.

### This is the result:

<img width="797" height="531" alt="Screenshot 2025-11-11 120426"
src="https://github.com/user-attachments/assets/2ae5d15d-699e-45ef-ab52-afd653d82111"
/>


<!-- Describe how you validated the behavior. Add automated tests
wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed
2025-11-13 05:47:05 -06:00
Kai Tao
2f001e8150 Advanced paste: Tweak Foundry Local Displayed Model and start server if server is turned on when using AP (#43529)
<!-- 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
1. Foundry local model name should not prefixed by fl://
2. If foundry service is shutdown, we should not just fail it, we should
start it then call FL to make availability better.

<!-- 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
Verified locally:
1. Manually disable foundry local service, then run AP with foundry
local, it can return result instead of direct failure.
2. 
<img width="659" height="294" alt="image"
src="https://github.com/user-attachments/assets/113da451-7131-4ce7-ae82-0ccf772ad8aa"
/>
<img width="988" height="192" alt="image"
src="https://github.com/user-attachments/assets/aa3650ba-668a-40c4-ad8a-303e09000dd4"
/>
![Uploading image.png…]()
2025-11-13 17:28:23 +08:00
Shawn Yuan
a983a773f3 Fix advanced paste migration issue (#43524)
<!-- 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 pull request refactors how legacy AI enablement settings are
migrated and simplifies the handling of legacy properties in the
settings UI. The main improvements are in the migration logic and the
removal of legacy extension data handling.


<!-- 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

Signed-off-by: Shawn Yuan <shuai.yuan.zju@gmail.com>
2025-11-13 16:55:09 +08:00
leileizhang
02eb55e3b9 Refine AdvancedPaste Terms UI and add default system prompt for Advanced AI (#43526)
<!-- 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
1. when no terms and Privacy links don't show the infobar
<img width="349" height="127" alt="image"
src="https://github.com/user-attachments/assets/b7eeeabf-365f-45f6-adb4-56335c14e8ad"
/>
<img width="410" height="217" alt="image"
src="https://github.com/user-attachments/assets/15e053c4-738d-4bb4-9544-24bdf8a5a584"
/>


2. add add default system prompt for Advanced AI

<!-- 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
2025-11-13 16:51:57 +08:00
Dave Rayment
afaf904016 [General] Update PR template with multiple issues note (#43442)
Added a comment noting that multiple issues should be placed on separate
lines, as per GitHub recommendations.

(When on the same line, issue references after the first are expanded
from their shortcut form, but are _not_ auto-closed once the PR is
merged.)

<!-- 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
- [ ] **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-13 09:18:31 +01:00
Jiří Polášek
4425e3ad28 CmdPal: Change captitalization of "Last position" item (#43518)
## Summary of the Pull Request

This PR updates the capitalization of the drop-down item from "Last
Position" to "Last position" to align with the guidelines.

<!-- 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
2025-11-13 09:17:41 +01:00
151 changed files with 1716 additions and 1378 deletions

View File

@@ -5,6 +5,7 @@
## 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

View File

@@ -40,7 +40,7 @@ jobs:
echo powerToysInstallerArm64Url=$(jq -n "$powerToysSetup" | jq -r '[.[]|select(.name | contains("arm64"))][0].browser_download_url') >> $GITHUB_OUTPUT
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v4
uses: actions/setup-dotnet@v5
with:
dotnet-version: '9.0.x'

3
.gitmodules vendored
View File

@@ -4,6 +4,3 @@
[submodule "deps/expected-lite"]
path = deps/expected-lite
url = https://github.com/martinmoene/expected-lite.git
[submodule "deps/cziplib"]
path = deps/cziplib
url = https://github.com/kuba--/zip.git

View File

@@ -26,6 +26,7 @@
<PropertyGroup Condition="'$(SkipCppCodeAnalysis)' == ''">
<RunCodeAnalysis>true</RunCodeAnalysis>
<CodeAnalysisRuleSet>$(MsbuildThisFileDirectory)\CppRuleSet.ruleset</CodeAnalysisRuleSet>
<CAExcludePath>$(MSBuildThisFileDirectory)deps;$(MSBuildThisFileDirectory)packages;$(CAExcludePath)</CAExcludePath>
</PropertyGroup>
<!-- C++ source compile-specific things for all configurations -->
@@ -34,7 +35,7 @@
<PreferredToolArchitecture Condition="'$(PROCESSOR_ARCHITECTURE)' == 'ARM64' or '$(PROCESSOR_ARCHITEW6432)' == 'ARM64'">arm64</PreferredToolArchitecture>
<VcpkgEnabled>false</VcpkgEnabled>
<ReplaceWildcardsInProjectItems>true</ReplaceWildcardsInProjectItems>
<ExternalIncludePath>$(MSBuildThisFileFullPath)\..\deps\;$(MSBuildThisFileFullPath)\..\packages\;$(ExternalIncludePath)</ExternalIncludePath>
<ExternalIncludePath>$(MSBuildThisFileDirectory)deps;$(MSBuildThisFileDirectory)packages;$(ExternalIncludePath)</ExternalIncludePath>
<!-- Enable control flow guard for C++ projects that don't consume any C++ files -->
<!-- This covers the case where a .dll exports a .lib, but doesn't have any ClCompile entries. -->
<LinkControlFlowGuard>Guard</LinkControlFlowGuard>

240
README.md
View File

@@ -51,19 +51,20 @@ But to get started quickly, choose one of the installation methods below:
Go to the [PowerToys GitHub releases][github-release-link], click Assets to reveal the downloads, and choose the installer that matches your architecture and install scope. For most devices, that's the x64 per-user installer.
<!-- items that need to be updated release to release -->
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.96%22
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.95%22
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysUserSetup-0.95.1-x64.exe
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysUserSetup-0.95.1-arm64.exe
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysSetup-0.95.1-x64.exe
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.95.1/PowerToysSetup-0.95.1-arm64.exe
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.97%22
[github-current-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.96%22
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.96.0/PowerToysUserSetup-0.96.0-x64.exe
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.96.0/PowerToysUserSetup-0.96.0-arm64.exe
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.96.0/PowerToysSetup-0.96.0-x64.exe
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.96.0/PowerToysSetup-0.96.0-arm64.exe
| Description | Filename |
|----------------|----------|
| Per user - x64 | [PowerToysUserSetup-0.95.1-x64.exe][ptUserX64] |
| Per user - ARM64 | [PowerToysUserSetup-0.95.1-arm64.exe][ptUserArm64] |
| Machine wide - x64 | [PowerToysSetup-0.95.1-x64.exe][ptMachineX64] |
| Machine wide - ARM64 | [PowerToysSetup-0.95.1-arm64.exe][ptMachineArm64] |
| Per user - x64 | [PowerToysUserSetup-0.96.0-x64.exe][ptUserX64] |
| Per user - ARM64 | [PowerToysUserSetup-0.96.0-arm64.exe][ptUserArm64] |
| Machine wide - x64 | [PowerToysSetup-0.96.0-x64.exe][ptMachineX64] |
| Machine wide - ARM64 | [PowerToysSetup-0.96.0-arm64.exe][ptMachineArm64] |
</details>
<details>
@@ -102,156 +103,131 @@ There are [community driven install methods](./doc/unofficialInstallMethods.md)
</details>
## ✨ What's new
**Version 0.95 (October 2025)**
**Version 0.96 (November 2025)**
For an in-depth look at the latest changes, visit the [Windows Command Line blog](https://aka.ms/powertoys-releaseblog).
**✨ Highlights**
- **NEW:** The **Light Switch** utility in PowerToys allows you to automatically switch between light and dark themes in Windows based on the time of day.
- Command Palette delivered major search performance gains (new fuzzy matcher and smarter fallbacks) improving relevance and speed.
- Peek can now be activated using just the Spacebar!
- Find My Mouse added transparent spotlight with independent backdrop opacity, boosting focus and accessibility.
- Settings now lets you delete shortcuts entirely and ignore conflicts.
- Mouse Pointer Crosshairs gained orientation options (vertical / horizontal / both) for customizable accessibility. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
- PowerRename fixed enumeration counter skipping ensuring reliable batch renames. Thanks [@daverayment](https://github.com/daverayment)!
- ZoomIt restored legacy draw and snipping behaviors, and fixed recording issues, improving reliability. Thanks [@chakrik73](https://github.com/chakrik73)!
- Advanced Paste now supports multiple online and on-device AI model providers: Azure OpenAI, OpenAI, Google Gemini, Mistral, Foundry Local and Ollama.
- Command Palette received extensive improvements including file search filters, better clipboard history metadata, context-menu styling, and dozens of bug fixes and enhancements.
- PowerRename can now extract and use photo metadata (EXIF, XMP) in renaming patterns like `%Camera`, `%Lens`, and `%ExposureTime`.
### Advanced Paste
- Advanced Paste now lets you connect to multiple AI providers instead of being limited to a single OpenAI provider. See [Advanced Paste documentation](https://learn.microsoft.com/windows/powertoys/advanced-paste) for usage.
### Awake
- The Awake countdown timer now stays accurate over long periods. Thanks [@daverayment](https://github.com/daverayment)!
- Fixed Awake context menu positioning. The fix removed the conversion of the mouse cursor from screen to client-window coordinates, instead using the raw screen coordinates returned by GetCursorPos; the context menu now appears at the correct screen position. Thanks [@lzandman](https://github.com/lzandman)!
### Command Palette
- Applied conditional margin for icon-only tags to tighten layout. Thanks [@samrueby](https://github.com/samrueby)
- Improved the reliability of accessing Command Palette settings through PowerToys Settings and executing other x-cmdpal:// protocol commands. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Enabled AOT by default for improved performance while simplifying publish configs.
- Replaced service state color dots with play/pause/stop icons for enhanced accessibility. Thanks [@samrueby](https://github.com/samrueby)
- Fixed filter dropdown sync and crash by binding SelectedValue and raising UI-thread notifications. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Ensured long links wrap correctly in details view.
- Removed animation and enforced minimum width on filter dropdown for clarity. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Restored focus to More button after ESC closes context menu, improving keyboard flow. Thanks [@chatasweetie](https://github.com/chatasweetie)
- Marked main and toast windows as tool windows to keep them out of Alt+Tab while preserving style. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Fixed AOT template and theming issues for filter separators. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Introduced grid layouts (small, medium, gallery) for richer page presentation.
- Materialized result lists to avoid rescoring overhead.
- Disabled problematic selection TextToSuggest behind environment flag.
- Major search performance improvements (new fuzzy matcher, smarter fallbacks, fewer exceptions).
- Added context menu "Show Details" command when details pane is hidden.
- Reduced window flicker by avoiding unnecessary cloaking. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Restored EmptyContent rendering for blank states. Thanks [@DevLGuilherme](https://github.com/DevLGuilherme)
- Saved new state even if prior app state file was corrupt (better resilience). Thanks [@jiripolasek](https://github.com/jiripolasek)
- Migrated settings window to WinUI TitleBar control. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Prevented crash on duplicate keybindings and simplified matching. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Hotkeys now always respect the “Ignore shortcut in fullscreen” setting. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Hid search box on content pages, improving focus and accessibility, and added Home title. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Blocked Ctrl+I from inserting stray tabs in search box.
- Logged HRESULT codes in error logs for deeper diagnostics. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Advanced font and emoji icon classification and alignment improvements. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Ensured that fallback command icons are visible on the extension settings page. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Fixed breadcrumb margin misalignment (visual polish). Thanks [@jiripolasek](https://github.com/jiripolasek)
- Truncated overly long command labels with ellipsis to prevent overflow.
- Added a setting to configure the page transition animation.
- Collection of small improvements and nits for Run Commands.
- Improved bookmarks performance and experience. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Added Ctrl+O shortcut in Clipboard History to open links directly.
- Resolved conflict with external software that blocked Command Palette from hiding.
- Updated context menu items to reflect name and icon changes, and ensured application icons are displayed correctly. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Added Alt+Home shortcut to return immediately to the Command Palette home page. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Fixed a crash when displaying code blocks in markdown on detail or content pages. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Fixed an issue where the search bar icon and title were not updated when rapidly switching pages. Thanks [@jiripolasek](https://github.com/jiripolasek)
- Improved the appearance of the search box in the context menu.
- The search field in context menus now matches the look of the Command Palette, with a smoke backdrop and improved padding.
- Fallback items such as math calculations or the Run command now appear in results more quickly. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Ensured the command bar updates correctly after navigating to another page and commands are displayed correctly. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- The Command Palette settings page has been reorganized. Activation-key options are grouped under an expander and extension settings are framed for improved readability.
- When you modify a command, its alias, hotkey, and tags now update in the top-level list, keeping the displayed information in sync. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Press `Ctrl + ,` to open Command Palette settings from anywhere. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- You can use `Page Up` and `Page Down` to navigate the list while focus is in the search box. Thanks [@samrueby](https://github.com/samrueby)!
- Fixed an issue where the search box could disappear when navigating pages. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Ensured search text is selected when *Go home when activated* and *Highlight search on activate* are both enabled. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Fixed an issue where Command Palette window occasionally appeared on the taskbar under certain Windows settings. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Ensured that labels and icons of list items and menu items update when they change. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Fixed visibility of list filters when navigating to a content page. Thanks [@DevLGuilherme](https://github.com/DevLGuilherme)!
- Added search to the extension list and a link to extensions on the Microsoft Store. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added options to open the Command Palette window at its last position or re-center it.
- The Command Palette now remembers its window size after restarting.
- Added a global error handler that logs fatal errors and provides feedback when unexpected failures force Command Palette to close. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Fixed forms and extension settings not showing on some machines due to a missing VC++ runtime.
- Restored ranking of fallback commands for built-in extensions (Sleep, Shutdown, Windows settings, Web search, etc.). Thanks [@jiripolasek](https://github.com/jiripolasek).
- Improved and unified labels and texts across the application!
- Maintainance: Resolved numerous build warnings in Command Palette projects; no user-visible impact. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Maintainance: Fixed a logging issue so exception messages are properly recorded instead of placeholder text, improving troubleshooting. Thanks [@jiripolasek](https://github.com/jiripolasek)!
### Command Palette Extensions
- Replaced localized WebSearch setting keys with stable literals and numeric history count. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Enabled advanced markdown tables and emphasis extensions. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added setting to choose Clipboard History primary action (Paste vs Copy). Thanks [@jiripolasek](https://github.com/jiripolasek)
- Added actionable empty-state hints for File Search (search PC / open indexing settings). Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Ensured all WinGet extension assets copy reliably to output. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Improved Run command line parsing for paths with spaces; sped up related tests.
- Updated WebSearch extension icon set for enhanced clarity and contrast. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added Terminal profile sort order setting including MRU tracking. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added Uninstall Application command (UWP direct, Win32 via Settings). Thanks [@mKpwnz](https://github.com/mKpwnz)!
- Deferred WinGet details loading and added timing logs.
- Removed LINQ from All Apps extension for performance.
- Added standardized key chord system + shortcuts to File Search commands. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added Terminal channel filter & remembered selection option. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Enabled loading local/data/app images in markdown with sizing hints. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added external extension reload via x-cmdpal://reload (configurable). Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Instant WebSearch history updates with in-memory store & events. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Added keep-after-paste option and safe delete with confirmation for Clipboard History. Thanks [@jiripolasek](https://github.com/jiripolasek)!
### Environment Variables
- Replaced custom window chrome with WinUI TitleBar for cleaner, maintainable Environment Variables UI.
### File Locksmith
- Adopted WinUI TitleBar to simplify window chrome while preserving appearance.
- Bookmarks: Added hints about bookmark placeholders to the Add/Edit Bookmark form. — Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Bookmarks: Improved migration of bookmarks from older versions and fixed an issue where aliases or keyboard shortcuts could be lost after restart. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Clipboard history: Items shown in Command Palettes clipboard history now include helpful metadata. For example, image items show dimensions, text files show names and sizes, web links include page titles, and text entries display word counts. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- File search: Added filter buttons to show *all items*, *files only*, or *folders only*. Selecting a filter adds `kind:folders` or `kind:not folders` to narrow results.
- System commands: Replaced the `:red_circle:` placeholder with an actual red-circle emoji so the correct icon appears in the UI. Thanks [@samrueby](https://github.com/samrueby)!
- WinGet: Search performance feels more responsive because typed input is now processed via a task queue rather than complex cancellation tokens!
- Window Walker: UWP apps no longer show a "not responding" label when suspended. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Window Walker: Now displays the actual icon of each window rather than using the process icon, improving recognition of PWAs and Python GUIs. Thanks [@Lee-WonJun](https://github.com/Lee-WonJun)!
- Windows Terminal profiles: Fixed a rare crash in the Windows Terminal extension when the `LOCALAPPDATA` environment variable was missing. The path is now retrieved via a reliable API. Thanks [@jiripolasek](https://github.com/jiripolasek)!
### Find My Mouse
- Added transparent spotlight support with separate backdrop opacity; migrated to Windows App SDK composition APIs.
- Activating Find My Mouse no longer makes the cursor change to the busy (hourglass) icon or steals focus from your active application.
### Hosts File Editor
- Migrated to native WinUI TitleBar for cleaner, maintainable window chrome.
- Added customizable backup settings allowing users to configure backup frequency, location, and auto-deletion policies. Thanks [@davidegiacometti](https://github.com/davidegiacometti)!
### Image Resizer
- Fixed settings consistency during batch resize operations by capturing settings once before processing. Thanks [@daverayment](https://github.com/daverayment)!
### Light Switch
- Introduced as a brand-new PowerToy module.
- Automatically switches between light and dark themes.
- Supports time-based scheduling or location-based sunrise/sunset switching.
- Supports using a keyboard shortcut to force a change.
- Supports filtering changes for Apps and/or System Theme.
- Introduced new UI to allow users to manually enter their latitude and longitude in Sunrise to Sunset mode.
- Refactored service with cleaner state management for stability.
- Removed logs from every tick, only logging key events to largely reduce log size.
### Mouse Pointer Crosshairs
- Added Esc key to cancel active gliding cursor sequence. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
- Added orientation option (vertical / horizontal / both) for crosshairs customization. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
- Enabled switching between Mouse Pointer Crosshairs and Gliding Cursor modes. Thanks [@mikehall-ms](https://github.com/mikehall-ms)!
### Mouse Without Borders
- Continued Common class refactor (part 5/7) by extracting clipboard and init/cleanup logic into focused classes. Thanks [@mikeclayton](https://github.com/mikeclayton)!
- Fix connection failures caused by conflicting MachineId across machines. Thanks [@noraa-junker](https://github.com/noraa-junker) for troubleshooting!
- Added horizontal scrolling support. Thanks [@MasonBergstrom](https://github.com/MasonBergstrom)!
### Peek
- Added the option to activate Peek with just the Spacebar.
- Fixed media files remaining locked after preview window closes. Thanks [@daverayment](https://github.com/daverayment)!
- Added a command-line interface for file previewing. See the [Peek documentation](https://learn.microsoft.com/windows/powertoys/peek) for usage. Thanks [@prochan2](https://github.com/prochan2)!
### PowerRename
- Fixed enumeration counter skipping when regex replacement equals original filename (counters now advance reliably). Thanks [@daverayment](https://github.com/daverayment)!
- PowerRename no longer crashes due to a missing resources file.
- Added photo metadata extraction support using EXIF and XMP for pattern-based renaming with camera info, GPS coordinates, and date taken. See [PowerRename Documentation](https://learn.microsoft.com/en-us/windows/powertoys/powerrename).
### Quick Accent
- Expanded Welsh layout with acute, grave, and dieresis variants for vowels (consistent ordering). Thanks [@PesBandi](https://github.com/PesBandi)!
### PowerToys Run
- Added retry logic with exponential backoff to handle DWM composition errors during theme changes. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Updated OneNote icons to reflect new Microsoft 365 design. Thanks [@trevorNgo](https://github.com/trevorNgo)!
### Registry Preview
- Migrated to native TitleBar and AppWindow APIs for cleaner window chrome.
### Quick Accent
- Added diameter symbol (⌀) for Shift+O in Special Characters mode, thanks to [@anselumjuju](https://github.com/anselumjuju)!
### Screen Ruler
- Fixed ARM64 crash by aligning cursor position structure to 8-byte boundary.
### Zoomit
- Smoothed out zoom-animation in ZoomIt by coalescing mouse-move and timer events, thanks to [@foxmsft](https://github.com/foxmsft)!
- Enabled GIF support for ZoomIt, thanks to [@MarioHewardt](https://github.com/MarioHewardt)!
- Fixed spelling mistakes, and refactored some literal strings to string constants, thanks to [@lzandman](https://github.com/lzandman)!
- Fixed inaccurate "actual size" screenshots in ZoomIt and resolves a GDI handle leak, improving capture fidelity and long-session stability. thanks to [@daverayment](https://github.com/daverayment)!
### Settings
- Added ability to ignore specific hotkey conflicts to reduce noise.
- Stopped creating backup directory during dry-run status checks (cleaner first-run).
- Standardized casing and localization for ZoomIt and modules header.
- Improved search results page accessibility and conditional module grouping.
- Fixed title bar overlapping issue at smaller window sizes.
- Refined shortcut control visual design with improved consistency and spacing.
- Added dashboard utilities sorting by name or status.
- Made update notification InfoBar in flyout clickable for direct navigation to update page.
- Expanded installation instructions by default in README.
- Improved accessibility for shortcut conflict button with static resource-based automation properties.
- Added ScrollViewer to Command Palette page in PowerToys Settings. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Fixed module list glitches and Sort Status checkmark issue. Thanks [@daverayment](https://github.com/daverayment)!
### ZoomIt
- Updated resource file to reflect standalone v9.01 and current copyright year. Thanks [@foxmsft](https://github.com/foxmsft)!
- Restored legacy draw/snipping behaviors and fixed recording race conditions. Thanks [@chakrik73](https://github.com/chakrik73)!
- Added smooth image option for improved zoom quality using GDI+ for static zoom and Magnifier API for live zoom. Thanks [@markrussinovich](https://github.com/markrussinovich)!
### Documentation
- New Microsoft Learn documentation for the Light Switch module.
- New dev docs for the Light Switch module.
### Development (Area-Build & Area-Tests)
- Allowed debug launches to continue when modules fail to load, speeding developer iteration.
- Fixed spell checker dictionary entry (advapi) to eliminate false error.
- Added VS Code development guide and launch configs to streamline cross-editor workflows.
- Upgraded Windows App SDK and related dependencies to 1.8 for newer platform features.
- Rewrote YAML comment to resolve new spell checker forbidden pattern. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Corrected solution structure by returning misplaced Common project, reducing build confusion.
- Modernized build scripts with shared helpers and VS environment autodetection for simpler CLI builds.
- Standardized build scripts and platform detection to improve reliability and reuse.
- Added missing Command Palette version bump to align module release cadence.
- Added EXECUTEDEFAULT term to dictionary to prevent regression build failures. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Introduced nightly pre-warm pipeline and configurable MSBuild cache mode to improve CI performance.
- Resolved CI forbidden pattern spelling complaint to keep pipelines green.
- Added AI contributor instruction set to clarify code area expectations.
- Added accessibility IDs to settings and FancyZones toggles, stabilizing UI tests.
- Added automatic log collection on UI test failures to speed root cause analysis.
- Stabilized Mouse Utils tests by switching to AccessibilityId selectors.
- Added Screen Ruler UI test coverage to validate core measurement workflows.
### Development
- Fixed accessibility by associating controls with labels for screen readers.
- Added accessible name to Shortcut Conflicts button for screen readers.
- Excluded TitleBars from tab navigation across multiple utilities. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Migrated build infrastructure from Windows Server 2019 to Server 2022 with improved failure logging and predictable NuGet package paths.
- Configured build agents to use larger P: drive for release builds to address disk space constraints.
- Enhanced DSC v3 support by organizing resource manifests in a dedicated subfolder with PATH configuration.
- Reduced installer bundle size by 6-7MB through centralized Hybrid CRT configuration across all C++ projects.
- Updated .NET packages to version 9.0.10 for security fixes. Thanks [@snickler](https://github.com/snickler)!
- Fixed spell check dictionary entries for consistency.
- Restored accidentally deleted NuGet configuration file for Command Palette extensions.
- Fixed package identity build by updating AppxManifest entry points to use PowerShell Core.
- Optimized CI pipeline by replacing file copy operations with hard links and moves, reducing build time and disk usage by 10-15GB.
- Updated Copilot guidance and PR prompt workflow.
- Included high-volume bugs in issue template header. Thanks [@daverayment](https://github.com/daverayment)!
- Fixed incorrect HRESULT logging for inner exceptions. Thanks [@jiripolasek](https://github.com/jiripolasek)!
- Introduced shared sparse package identity for PowerToys Win32 components to enable access to Windows platform APIs.
- Consolidated installer builds to produce both machine and user installers simultaneously, reducing build time and complexity.
- Migrated exclusively to WiX v5 installer infrastructure, removing legacy WiX v3 support.
- Temporarily removed PowerToys installer path from PATH environment variable to prevent application crashes.
- Added complete OCR UI test coverage with automated tests for activation, settings, language selection, and text extraction.
- Fixed test input for drive path normalization in bookmark resolver unit tests.
- Fixed Peek UI tests by restoring Ctrl+Space activation shortcut for test scenarios.
- Hided apps in PowerToys.SpareApps package from Start Menu. Thanks [@jiripolasek](https://github.com/jiripolasek)!
## 🛣️ Roadmap
We are planning some nice new features and improvements for the next releases a revamped Keyboard Manager UI, custom endpoint and local model support for Advanced Paste, Command Palette improvements and a brand-new Shortcut Guide experience! Stay tuned for [v0.96][github-next-release-work]!

1
deps/cziplib vendored

Submodule deps/cziplib deleted from 81314fff0a

View File

@@ -64,7 +64,7 @@ public sealed class FoundryLocalModelProvider : ILanguageModelProvider
return new OpenAIClient(
new ApiKeyCredential("none"),
new OpenAIClientOptions { Endpoint = endpointUri, NetworkTimeout = TimeSpan.FromMinutes(5) })
new OpenAIClientOptions { Endpoint = endpointUri })
.GetChatClient(modelId)
.AsIChatClient();
}

View File

@@ -215,6 +215,7 @@ public sealed class AdvancedAIKernelService : KernelServiceBase
return new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(),
Temperature = 0.01,
};
}
}

View File

@@ -146,7 +146,6 @@ public sealed class FoundryLocalPasteProvider : IPasteAIProvider
var options = new ChatOptions
{
ModelId = modelReference,
MaxOutputTokens = 2048,
};
if (!string.IsNullOrWhiteSpace(systemPrompt))

View File

@@ -157,6 +157,8 @@ namespace AdvancedPaste.Services.CustomActions
{
AIServiceType.OpenAI or AIServiceType.AzureOpenAI => new OpenAIPromptExecutionSettings
{
Temperature = 0.01,
MaxTokens = 2000,
FunctionChoiceBehavior = null,
},
_ => new PromptExecutionSettings(),

View File

@@ -121,7 +121,7 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,166,306,50,14
PUSHBUTTON "Cancel",IDCANCEL,223,306,50,14
LTEXT "ZoomIt v9.20",IDC_VERSION,42,7,73,10
LTEXT "ZoomIt v9.21",IDC_VERSION,42,7,73,10
LTEXT "Copyright © 2006-2025 Mark Russinovich",IDC_COPYRIGHT,42,17,231,8
CONTROL "<a HREF=""https://www.sysinternals.com"">Sysinternals - www.sysinternals.com</a>",IDC_LINK,
"SysLink",WS_TABSTOP,42,26,150,9

View File

@@ -350,7 +350,7 @@ namespace Awake.Core
TrayHelper.TimedIcon,
TrayIconAction.Update);
},
() => HandleTimerCompletion("timed"),
_ => HandleTimerCompletion("timed"),
_tokenSource.Token);
}

View File

@@ -1,62 +0,0 @@
// Copyright (c) Microsoft Corporation
// 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;
namespace Microsoft.CmdPal.Core.Common;
public static class CoreLogger
{
public static void InitializeLogger(ILogger implementation)
{
_logger = implementation;
}
private static ILogger? _logger;
public static void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogError(message, ex, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogError(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogWarning(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogInfo(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogDebug(message, memberName, sourceFilePath, sourceLineNumber);
}
public static void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0)
{
_logger?.LogTrace(memberName, sourceFilePath, sourceLineNumber);
}
}
public interface ILogger
{
void LogError(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogError(string message, Exception ex, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogWarning(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogInfo(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogDebug(string message, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
void LogTrace([System.Runtime.CompilerServices.CallerMemberName] string memberName = "", [System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "", [System.Runtime.CompilerServices.CallerLineNumber] int sourceLineNumber = 0);
}

View File

@@ -9,4 +9,8 @@
<PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
</ItemGroup>
</Project>

View File

@@ -2,8 +2,6 @@
// 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.Collections.Generic;
using System.Threading.Tasks;
using Windows.Foundation;
namespace Microsoft.CmdPal.Core.Common.Services;
@@ -26,12 +24,4 @@ public interface IExtensionService
void EnableExtension(string extensionUniqueId);
void DisableExtension(string extensionUniqueId);
///// <summary>
///// Gets a boolean indicating whether the extension was disabled due to the corresponding Windows optional feature
///// being absent from the machine or in an unknown state.
///// </summary>
///// <param name="extension">The out of proc extension object</param>
///// <returns>True only if the extension was disabled. False otherwise.</returns>
// public Task<bool> DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper extension);
}

View File

@@ -23,12 +23,3 @@ public interface IRunHistoryService
/// <param name="item">The run history item to add.</param>
void AddRunHistoryItem(string item);
}
public interface ITelemetryService
{
void LogRunQuery(string query, int resultCount, ulong durationMs);
void LogRunCommand(string command, bool asAdmin, bool success);
void LogOpenUri(string uri, bool isWeb, bool success);
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.Common.Services.Telemetry;
public interface ITelemetryService
{
void WriteEvent(TelemetryEventBase telemetryEvent);
}

View File

@@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.Core.Common.Services.Telemetry;
public abstract class TelemetryEventBase : EventBase, IEvent
{
// Overridden in derived classes
public abstract PartA_PrivTags PartA_PrivTags { get; }
}

View File

@@ -4,9 +4,9 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using Microsoft.CmdPal.Core.Common;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
using Windows.Foundation;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -14,6 +14,7 @@ namespace Microsoft.CmdPal.Core.ViewModels;
public abstract partial class AppExtensionHost : IExtensionHost
{
private static readonly GlobalLogPageContext _globalLogPageContext = new();
private readonly ILogger _logger;
private static ulong _hostingHwnd;
@@ -27,6 +28,11 @@ public abstract partial class AppExtensionHost : IExtensionHost
public static void SetHostHwnd(ulong hostHwnd) => _hostingHwnd = hostHwnd;
public AppExtensionHost(ILogger logger)
{
_logger = logger;
}
public void DebugLog(string message)
{
#if DEBUG
@@ -60,7 +66,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
return Task.CompletedTask.AsAsyncAction();
}
CoreLogger.LogDebug(message.Message);
Log_DebugMessage(message.Message);
_ = Task.Run(() =>
{
@@ -96,7 +102,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
public void ProcessLogMessage(ILogMessage message)
{
var vm = new LogMessageViewModel(message, _globalLogPageContext);
var vm = new LogMessageViewModel(message, _globalLogPageContext, _logger);
vm.SafeInitializePropertiesSynchronous();
Task.Factory.StartNew(
@@ -127,7 +133,7 @@ public abstract partial class AppExtensionHost : IExtensionHost
return;
}
var vm = new StatusMessageViewModel(message, new(_globalLogPageContext));
var vm = new StatusMessageViewModel(message, new(_globalLogPageContext), _logger);
vm.SafeInitializePropertiesSynchronous();
Task.Factory.StartNew(
@@ -158,6 +164,11 @@ public abstract partial class AppExtensionHost : IExtensionHost
}
public abstract string? GetExtensionDisplayName();
public abstract AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost);
[LoggerMessage(Level = LogLevel.Debug, Message = "{Message}")]
partial void Log_DebugMessage(string message);
}
public interface IAppHostService

View File

@@ -6,6 +6,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
using Windows.System;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -13,6 +14,8 @@ namespace Microsoft.CmdPal.Core.ViewModels;
public partial class CommandBarViewModel : ObservableObject,
IRecipient<UpdateCommandBarMessage>
{
private readonly ILogger _logger;
public ICommandBarContext? SelectedItem
{
get => field;
@@ -48,8 +51,9 @@ public partial class CommandBarViewModel : ObservableObject,
[ObservableProperty]
public partial PageViewModel? CurrentPage { get; set; }
public CommandBarViewModel()
public CommandBarViewModel(ILogger logger)
{
_logger = logger;
WeakReferenceMessenger.Default.Register<UpdateCommandBarMessage>(this);
}

View File

@@ -5,12 +5,12 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference<IPageContext> context) : CommandItemViewModel(new(contextItem), context), IContextItemViewModel
public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference<IPageContext> context, ILogger logger) : CommandItemViewModel(new(contextItem), context, logger), IContextItemViewModel
{
private readonly KeyChord nullKeyChord = new(0, 0, 0);

View File

@@ -3,11 +3,11 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics.CodeAnalysis;
using Microsoft.CmdPal.Core.Common;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -86,11 +86,11 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
_errorIcon.InitializeProperties();
}
public CommandItemViewModel(ExtensionObject<ICommandItem> item, WeakReference<IPageContext> errorContext)
: base(errorContext)
public CommandItemViewModel(ExtensionObject<ICommandItem> item, WeakReference<IPageContext> errorContext, ILogger logger)
: base(errorContext, logger)
{
_commandItemModel = item;
Command = new(null, errorContext);
Command = new(null, errorContext, Logger);
}
public void FastInitializeProperties()
@@ -106,7 +106,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
return;
}
Command = new(model.Command, PageContext);
Command = new(model.Command, PageContext, Logger);
Command.FastInitializeProperties();
_itemTitle = model.Title;
@@ -184,7 +184,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
MoreCommands = more
.Select<IContextItem, IContextItemViewModel>(item =>
{
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext) : new SeparatorViewModel();
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext, Logger) : new SeparatorViewModel();
})
.ToList();
}
@@ -201,7 +201,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
if (!string.IsNullOrEmpty(model.Command?.Name))
{
_defaultCommandContextItemViewModel = new CommandContextItemViewModel(new CommandContextItem(model.Command!), PageContext)
_defaultCommandContextItemViewModel = new CommandContextItemViewModel(new CommandContextItem(model.Command!), PageContext, Logger)
{
_itemTitle = Name,
Subtitle = Subtitle,
@@ -231,8 +231,8 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
}
catch (Exception ex)
{
CoreLogger.LogError("error fast initializing CommandItemViewModel", ex);
Command = new(null, PageContext);
Log_ErrorFastInitializingCommandItemViewModel(Logger, ex);
Command = new(null, PageContext, Logger);
_itemTitle = "Error";
Subtitle = "Item failed to load";
MoreCommands = [];
@@ -253,7 +253,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
catch (Exception ex)
{
Initialized |= InitializedState.Error;
CoreLogger.LogError("error slow initializing CommandItemViewModel", ex);
Log_ErrorSlowInitializingCommandItemViewModel(Logger, ex);
}
return false;
@@ -268,8 +268,8 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
}
catch (Exception ex)
{
CoreLogger.LogError("error initializing CommandItemViewModel", ex);
Command = new(null, PageContext);
Log_ErrorSlowInitializingCommandItemViewModel(Logger, ex);
Command = new(null, PageContext, Logger);
_itemTitle = "Error";
Subtitle = "Item failed to load";
MoreCommands = [];
@@ -304,7 +304,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
{
case nameof(Command):
Command.PropertyChanged -= Command_PropertyChanged;
Command = new(model.Command, PageContext);
Command = new(model.Command, PageContext, Logger);
Command.InitializeProperties();
Command.PropertyChanged += Command_PropertyChanged;
@@ -351,7 +351,7 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
var newContextMenu = more
.Select<IContextItem, IContextItemViewModel>(item =>
{
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext) : new SeparatorViewModel();
return item is ICommandContextItem contextItem ? new CommandContextItemViewModel(contextItem, PageContext, Logger) : new SeparatorViewModel();
})
.ToList();
lock (MoreCommands)
@@ -464,6 +464,15 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa
base.SafeCleanup();
Initialized |= InitializedState.CleanedUp;
}
[LoggerMessage(level: LogLevel.Error, message: "error fast initializing CommandItemViewModel")]
static partial void Log_ErrorFastInitializingCommandItemViewModel(ILogger logger, Exception ex);
[LoggerMessage(level: LogLevel.Error, message: "error slow initializing CommandItemViewModel")]
static partial void Log_ErrorSlowInitializingCommandItemViewModel(ILogger logger, Exception ex);
[LoggerMessage(level: LogLevel.Error, message: "error initializing CommandItemViewModel")]
static partial void Log_ErrorInitializingCommandItemViewModel(ILogger logger, Exception ex);
}
[Flags]

View File

@@ -4,6 +4,7 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -38,8 +39,8 @@ public partial class CommandViewModel : ExtensionObjectViewModel
public IReadOnlyDictionary<string, ExtensionObject<object>>? Properties => _properties?.AsReadOnly();
public CommandViewModel(ICommand? command, WeakReference<IPageContext> pageContext)
: base(pageContext)
public CommandViewModel(ICommand? command, WeakReference<IPageContext> pageContext, ILogger logger)
: base(pageContext, logger)
{
Model = new(command);
Icon = new(null);

View File

@@ -4,13 +4,14 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReference<IPageContext> context) :
ExtensionObjectViewModel(context)
public partial class ConfirmResultViewModel(IConfirmationArgs? args, WeakReference<IPageContext> context, ILogger logger)
: ExtensionObjectViewModel(context, logger)
{
public ExtensionObject<IConfirmationArgs> Model { get; } = new(_args);
public ExtensionObject<IConfirmationArgs> Model { get; private set; } = new(args);
// Remember - "observable" properties from the model (via PropChanged)
// cannot be marked [ObservableProperty]
@@ -20,7 +21,7 @@ public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReferen
public bool IsPrimaryCommandCritical { get; private set; }
public CommandViewModel PrimaryCommand { get; private set; } = new(null, context);
public CommandViewModel PrimaryCommand { get; private set; } = new(null, context, logger);
public override void InitializeProperties()
{
@@ -33,7 +34,7 @@ public partial class ConfirmResultViewModel(IConfirmationArgs _args, WeakReferen
Title = model.Title;
Description = model.Description;
IsPrimaryCommandCritical = model.IsPrimaryCommandCritical;
PrimaryCommand = new(model.PrimaryCommand, PageContext);
PrimaryCommand = new(model.PrimaryCommand, PageContext, Logger);
PrimaryCommand.InitializeProperties();
UpdateProperty(nameof(Title));

View File

@@ -11,12 +11,14 @@ using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
{
private readonly ExtensionObject<IContentPage> _model;
private readonly ILogger _logger;
[ObservableProperty]
public partial ObservableCollection<ContentViewModel> Content { get; set; } = [];
@@ -47,10 +49,11 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
// Remember - "observable" properties from the model (via PropChanged)
// cannot be marked [ObservableProperty]
public ContentPageViewModel(IContentPage model, TaskScheduler scheduler, AppExtensionHost host)
: base(model, scheduler, host)
public ContentPageViewModel(IContentPage model, AppExtensionHost host, ILogger logger)
: base(model, host, logger)
{
_model = new(model);
_logger = logger;
}
// TODO: Does this need to hop to a _different_ thread, so that we don't block the extension while we're fetching?
@@ -115,7 +118,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
{
if (item is ICommandContextItem contextItem)
{
return new CommandContextItemViewModel(contextItem, PageContext);
return new CommandContextItemViewModel(contextItem, PageContext, _logger);
}
else
{
@@ -135,7 +138,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
var extensionDetails = model.Details;
if (extensionDetails is not null)
{
Details = new(extensionDetails, PageContext);
Details = new(extensionDetails, PageContext, _logger);
Details.InitializeProperties();
}
@@ -174,7 +177,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
{
if (item is ICommandContextItem contextItem)
{
return new CommandContextItemViewModel(contextItem, PageContext) as IContextItemViewModel;
return new CommandContextItemViewModel(contextItem, PageContext, _logger) as IContextItemViewModel;
}
else
{
@@ -216,7 +219,7 @@ public partial class ContentPageViewModel : PageViewModel, ICommandBarContext
break;
case nameof(Details):
var extensionDetails = model.Details;
Details = extensionDetails is not null ? new(extensionDetails, PageContext) : null;
Details = extensionDetails is not null ? new(extensionDetails, PageContext, _logger) : null;
UpdateDetails();
break;
}

View File

@@ -2,10 +2,12 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public abstract partial class ContentViewModel(WeakReference<IPageContext> context) :
ExtensionObjectViewModel(context)
public abstract partial class ContentViewModel(WeakReference<IPageContext> context, ILogger logger) :
ExtensionObjectViewModel(context, logger)
{
public bool OnlyControlOnPage { get; internal set; }
}

View File

@@ -5,7 +5,6 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.Common;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -138,11 +137,7 @@ public partial class ContextMenuViewModel : ObservableObject,
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
{
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
var added = result.TryAdd(key, cmd);
if (!added)
{
CoreLogger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
}
_ = result.TryAdd(key, cmd);
}
}

View File

@@ -4,19 +4,26 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class DetailsCommandsViewModel(
IDetailsElement _detailsElement,
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
public partial class DetailsCommandsViewModel : DetailsElementViewModel
{
private readonly ILogger _logger;
public List<CommandViewModel> Commands { get; private set; } = [];
public bool HasCommands => Commands.Count > 0;
private readonly ExtensionObject<IDetailsCommands> _dataModel =
new(_detailsElement.Data as IDetailsCommands);
private readonly ExtensionObject<IDetailsCommands> _dataModel;
public DetailsCommandsViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger)
: base(_detailsElement, context, logger)
{
_logger = logger;
_dataModel = new(_detailsElement.Data as IDetailsCommands);
}
public override void InitializeProperties()
{
@@ -31,7 +38,7 @@ public partial class DetailsCommandsViewModel(
.Commands?
.Select(c =>
{
var vm = new CommandViewModel(c, PageContext);
var vm = new CommandViewModel(c, PageContext, _logger);
vm.InitializeProperties();
return vm;
})

View File

@@ -2,11 +2,10 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public abstract partial class DetailsDataViewModel(IPageContext context) : ExtensionObjectViewModel(context)
public abstract partial class DetailsDataViewModel(IPageContext context, ILogger logger) : ExtensionObjectViewModel(context, logger)
{
}

View File

@@ -4,10 +4,11 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public abstract partial class DetailsElementViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
public abstract partial class DetailsElementViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger) : ExtensionObjectViewModel(context, logger)
{
private readonly ExtensionObject<IDetailsElement> _model = new(_detailsElement);

View File

@@ -6,12 +6,12 @@ using CommunityToolkit.Mvvm.Input;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class DetailsLinkViewModel(
IDetailsElement _detailsElement,
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
public partial class DetailsLinkViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger)
: DetailsElementViewModel(_detailsElement, context, logger)
{
private static readonly string[] _initProperties = [
nameof(Text),

View File

@@ -4,12 +4,13 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class DetailsSeparatorViewModel(
IDetailsElement _detailsElement,
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
WeakReference<IPageContext> context, ILogger logger) : DetailsElementViewModel(_detailsElement, context, logger)
{
private readonly ExtensionObject<IDetailsSeparator> _dataModel =
new(_detailsElement.Data as IDetailsSeparator);

View File

@@ -4,19 +4,25 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class DetailsTagsViewModel(
IDetailsElement _detailsElement,
WeakReference<IPageContext> context) : DetailsElementViewModel(_detailsElement, context)
public partial class DetailsTagsViewModel : DetailsElementViewModel
{
public List<TagViewModel> Tags { get; private set; } = [];
public bool HasTags => Tags.Count > 0;
private readonly ExtensionObject<IDetailsTags> _dataModel =
new(_detailsElement.Data as IDetailsTags);
private readonly ExtensionObject<IDetailsTags> _dataModel;
private readonly ILogger _logger;
public DetailsTagsViewModel(IDetailsElement _detailsElement, WeakReference<IPageContext> context, ILogger logger)
: base(_detailsElement, context, logger)
{
_logger = logger;
_dataModel = new(_detailsElement.Data as IDetailsTags);
}
public override void InitializeProperties()
{
@@ -31,7 +37,7 @@ public partial class DetailsTagsViewModel(
.Tags?
.Select(t =>
{
var vm = new TagViewModel(t, PageContext);
var vm = new TagViewModel(t, PageContext, _logger);
vm.InitializeProperties();
return vm;
})

View File

@@ -4,10 +4,11 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class DetailsViewModel(IDetails _details, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
public partial class DetailsViewModel(IDetails _details, WeakReference<IPageContext> context, ILogger logger) : ExtensionObjectViewModel(context, logger)
{
private readonly ExtensionObject<IDetails> _detailsModel = new(_details);
@@ -47,10 +48,10 @@ public partial class DetailsViewModel(IDetails _details, WeakReference<IPageCont
{
DetailsElementViewModel? vm = element.Data switch
{
IDetailsSeparator => new DetailsSeparatorViewModel(element, this.PageContext),
IDetailsLink => new DetailsLinkViewModel(element, this.PageContext),
IDetailsCommands => new DetailsCommandsViewModel(element, this.PageContext),
IDetailsTags => new DetailsTagsViewModel(element, this.PageContext),
IDetailsSeparator => new DetailsSeparatorViewModel(element, this.PageContext, Logger),
IDetailsLink => new DetailsLinkViewModel(element, this.PageContext, Logger),
IDetailsCommands => new DetailsCommandsViewModel(element, this.PageContext, Logger),
IDetailsTags => new DetailsTagsViewModel(element, this.PageContext, Logger),
_ => null,
};
if (vm is not null)

View File

@@ -3,23 +3,29 @@
// See the LICENSE file in the project root for more information.
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.CmdPal.Core.Common;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public abstract partial class ExtensionObjectViewModel : ObservableObject
{
private readonly ILogger _logger;
public ILogger Logger => _logger;
public WeakReference<IPageContext> PageContext { get; set; }
internal ExtensionObjectViewModel(IPageContext? context)
internal ExtensionObjectViewModel(IPageContext? context, ILogger logger)
{
var realContext = context ?? (this is IPageContext c ? c : throw new ArgumentException("You need to pass in an IErrorContext"));
_logger = logger;
PageContext = new(realContext);
}
internal ExtensionObjectViewModel(WeakReference<IPageContext> context)
internal ExtensionObjectViewModel(WeakReference<IPageContext> context, ILogger logger)
{
PageContext = context;
_logger = logger;
}
public async virtual Task InitializePropertiesAsync()
@@ -114,7 +120,10 @@ public abstract partial class ExtensionObjectViewModel : ObservableObject
}
catch (Exception ex)
{
CoreLogger.LogDebug(ex.ToString());
Log_CleanupException(ex);
}
}
[LoggerMessage(Level = LogLevel.Debug)]
partial void Log_CleanupException(Exception exception);
}

View File

@@ -4,6 +4,7 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -23,8 +24,8 @@ public partial class FilterItemViewModel : ExtensionObjectViewModel, IFilterItem
public bool IsInErrorState => Initialized.HasFlag(InitializedState.Error);
public FilterItemViewModel(IFilter filter, WeakReference<IPageContext> context)
: base(context)
public FilterItemViewModel(IFilter filter, WeakReference<IPageContext> context, ILogger logger)
: base(context, logger)
{
_model = new(filter);
}

View File

@@ -2,10 +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.Collections.Generic;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -21,8 +20,8 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
public bool ShouldShowFilters => Filters.Length > 0;
public FiltersViewModel(ExtensionObject<IFilters> filters, WeakReference<IPageContext> context)
: base(context)
public FiltersViewModel(ExtensionObject<IFilters> filters, WeakReference<IPageContext> context, ILogger logger)
: base(context, logger)
{
_filtersModel = filters;
}
@@ -71,7 +70,7 @@ public partial class FiltersViewModel : ExtensionObjectViewModel
{
if (filter is IFilter filterItem)
{
var filterItemViewModel = new FilterItemViewModel(filterItem, PageContext);
var filterItemViewModel = new FilterItemViewModel(filterItem, PageContext, Logger);
filterItemViewModel.InitializeProperties();
if (firstFilterItem is null)

View File

@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.ViewModels.Messages;
namespace Microsoft.CmdPal.Core.ViewModels;
// Represents everything the command bar needs to know about to show command
// buttons at the bottom.
//
// This is implemented by both ListItemViewModel and ContentPageViewModel,
// the two things with sub-commands.
public interface ICommandBarContext : IContextMenuContext
{
public string SecondaryCommandName { get; }
public CommandItemViewModel? PrimaryCommand { get; }
public CommandItemViewModel? SecondaryCommand { get; }
}

View File

@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace Microsoft.CmdPal.Core.ViewModels;
public interface IPageContext
{
void ShowException(Exception ex, string? extensionHint = null);
TaskScheduler Scheduler { get; }
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels;
public interface IPageViewModelFactoryService
{
/// <summary>
/// Creates a new instance of the page view model for the given page type.
/// </summary>
/// <param name="page">The page for which to create the view model.</param>
/// <param name="nested">Indicates whether the page is not the top-level page.</param>
/// <param name="host">The command palette host that will host the page (for status messages)</param>
/// <returns>A new instance of the page view model.</returns>
PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host);
}

View File

@@ -7,13 +7,14 @@ using Microsoft.CmdPal.Core.ViewModels.Commands;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class ListItemViewModel(IListItem model, WeakReference<IPageContext> context)
: CommandItemViewModel(new(model), context)
// Fix for CS9107: Do not capture 'logger' in the primary constructor; use a regular constructor instead.
public partial class ListItemViewModel : CommandItemViewModel
{
public new ExtensionObject<IListItem> Model { get; } = new(model);
public new ExtensionObject<IListItem> Model { get; }
public List<TagViewModel>? Tags { get; set; }
@@ -32,6 +33,15 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
public string AccessibleName { get; private set; } = string.Empty;
private readonly ILogger _logger;
public ListItemViewModel(IListItem model, WeakReference<IPageContext> context, ILogger logger)
: base(new(model), context, logger)
{
Model = new(model);
_logger = logger;
}
public override void InitializeProperties()
{
if (IsInitialized)
@@ -69,7 +79,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
var extensionDetails = model.Details;
if (extensionDetails is not null)
{
Details = new(extensionDetails, PageContext);
Details = new(extensionDetails, PageContext, Logger);
Details.InitializeProperties();
UpdateProperty(nameof(Details));
UpdateProperty(nameof(HasDetails));
@@ -104,7 +114,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
break;
case nameof(Details):
var extensionDetails = model.Details;
Details = extensionDetails is not null ? new(extensionDetails, PageContext) : null;
Details = extensionDetails is not null ? new(extensionDetails, PageContext, Logger) : null;
Details?.InitializeProperties();
UpdateProperty(nameof(Details));
UpdateProperty(nameof(HasDetails));
@@ -146,7 +156,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
// Create the view model for the show details command
var showDetailsCommand = new ShowDetailsCommand(Details);
var showDetailsContextItem = new CommandContextItem(showDetailsCommand);
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext);
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext, _logger);
showDetailsContextItemViewModel.SlowInitializeProperties();
MoreCommands.Add(showDetailsContextItemViewModel);
}
@@ -180,7 +190,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
// Create the view model for the show details command
var showDetailsCommand = new ShowDetailsCommand(Details);
var showDetailsContextItem = new CommandContextItem(showDetailsCommand);
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext);
var showDetailsContextItemViewModel = new CommandContextItemViewModel(showDetailsContextItem, PageContext, _logger);
showDetailsContextItemViewModel.SlowInitializeProperties();
MoreCommands.Add(showDetailsContextItemViewModel);
@@ -193,7 +203,7 @@ public partial class ListItemViewModel(IListItem model, WeakReference<IPageConte
{
var newTags = newTagsFromModel?.Select(t =>
{
var vm = new TagViewModel(t, PageContext);
var vm = new TagViewModel(t, PageContext, Logger);
vm.InitializeProperties();
return vm;
})

View File

@@ -11,6 +11,7 @@ using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
using Windows.Foundation;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -19,6 +20,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
{
// private readonly HashSet<ListItemViewModel> _itemCache = [];
private readonly TaskFactory filterTaskFactory = new(new ConcurrentExclusiveSchedulerPair().ExclusiveScheduler);
private readonly ILogger _logger;
// TODO: Do we want a base "ItemsPageViewModel" for anything that's going to have items?
@@ -90,11 +92,12 @@ public partial class ListViewModel : PageViewModel, IDisposable
}
}
public ListViewModel(IListPage model, TaskScheduler scheduler, AppExtensionHost host)
: base(model, scheduler, host)
public ListViewModel(IListPage model, TaskScheduler scheduler, AppExtensionHost host, ILogger logger)
: base(model, host, logger)
{
_model = new(model);
EmptyContent = new(new(null), PageContext);
EmptyContent = new(new(null), PageContext, logger);
_logger = logger;
}
private void FiltersPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
@@ -232,7 +235,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
return;
}
ListItemViewModel viewModel = new(item, new(this));
ListItemViewModel viewModel = new(item, new(this), _logger);
// If an item fails to load, silently ignore it.
if (viewModel.SafeFastInit())
@@ -594,11 +597,11 @@ public partial class ListViewModel : PageViewModel, IDisposable
UpdateProperty(nameof(SearchText));
UpdateProperty(nameof(InitialSearchText));
EmptyContent = new(new(model.EmptyContent), PageContext);
EmptyContent = new(new(model.EmptyContent), PageContext, _logger);
EmptyContent.SlowInitializeProperties();
Filters?.PropertyChanged -= FiltersPropertyChanged;
Filters = new(new(model.Filters), PageContext);
Filters = new(new(model.Filters), PageContext, _logger);
Filters?.PropertyChanged += FiltersPropertyChanged;
Filters?.InitializeProperties();
@@ -696,12 +699,12 @@ public partial class ListViewModel : PageViewModel, IDisposable
SearchText = model.SearchText;
break;
case nameof(EmptyContent):
EmptyContent = new(new(model.EmptyContent), PageContext);
EmptyContent = new(new(model.EmptyContent), PageContext, _logger);
EmptyContent.SlowInitializeProperties();
break;
case nameof(Filters):
Filters?.PropertyChanged -= FiltersPropertyChanged;
Filters = new(new(model.Filters), PageContext);
Filters = new(new(model.Filters), PageContext, _logger);
Filters?.PropertyChanged += FiltersPropertyChanged;
Filters?.InitializeProperties();
break;
@@ -751,7 +754,7 @@ public partial class ListViewModel : PageViewModel, IDisposable
base.UnsafeCleanup();
EmptyContent?.SafeCleanup();
EmptyContent = new(new(null), PageContext); // necessary?
EmptyContent = new(new(null), PageContext, _logger); // necessary?
_cancellationTokenSource?.Cancel();
filterCancellationTokenSource?.Cancel();

View File

@@ -3,13 +3,14 @@
// See the LICENSE file in the project root for more information.
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class LoadingPageViewModel : PageViewModel
{
public LoadingPageViewModel(IPage? model, TaskScheduler scheduler, AppExtensionHost host)
: base(model, scheduler, host)
public LoadingPageViewModel(IPage? model, AppExtensionHost host, ILogger logger)
: base(model, host, logger)
{
ModelIsLoading = true;
IsInitialized = false;

View File

@@ -4,6 +4,7 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -13,8 +14,8 @@ public partial class LogMessageViewModel : ExtensionObjectViewModel
public string Message { get; private set; } = string.Empty;
public LogMessageViewModel(ILogMessage message, IPageContext context)
: base(context)
public LogMessageViewModel(ILogMessage message, IPageContext context, ILogger logger)
: base(context, logger)
{
_model = new(message);
}

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to perform a list item's secondary command when the user presses ctrl+enter in the search box
/// </summary>
public record ActivateSecondaryCommandMessage
{
}
public record ActivateSecondaryCommandMessage;

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to perform a list item's command when the user presses enter in the search box
/// </summary>
public record ActivateSelectedListItemMessage
{
}
public record ActivateSelectedListItemMessage;

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record ClearSearchMessage()
{
}
public record ClearSearchMessage();

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to announce that a context menu should close
/// </summary>
public record CloseContextMenuMessage
{
}
public record CloseContextMenuMessage;

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record DismissMessage()
{
}
public record DismissMessage();

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record FocusSearchBoxMessage()
{
}
public record FocusSearchBoxMessage();

View File

@@ -4,7 +4,5 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record GoBackMessage(bool WithAnimation = true, bool FocusSearch = true)
{
// TODO! sticking these properties here feels like leaking the UI into the models
}
// TODO! sticking these properties here feels like leaking the UI into the models
public record GoBackMessage(bool WithAnimation = true, bool FocusSearch = true);

View File

@@ -5,6 +5,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
// TODO! sticking these properties here feels like leaking the UI into the models
public record GoHomeMessage(bool WithAnimation = true, bool FocusSearch = true)
{
}
public record GoHomeMessage(bool WithAnimation = true, bool FocusSearch = true);

View File

@@ -7,6 +7,4 @@ using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record HandleCommandResultMessage(ExtensionObject<ICommandResult> Result)
{
}
public record HandleCommandResultMessage(ExtensionObject<ICommandResult> Result);

View File

@@ -2,11 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record HideDetailsMessage()
{
}
public record HideDetailsMessage();

View File

@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation
// 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.ComponentModel;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public interface IContextMenuContext : INotifyPropertyChanged
{
public IEnumerable<IContextItemViewModel> MoreCommands { get; }
public bool HasMoreCommands { get; }
public List<IContextItemViewModel> AllCommands { get; }
/// <summary>
/// Generates a mapping of key -> command item for this particular item's
/// MoreCommands. (This won't include the primary Command, but it will
/// include the secondary one). This map can be used to quickly check if a
/// shortcut key was pressed
/// </summary>
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
/// that have a shortcut key set.</returns>
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
{
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
var menu = MoreCommands;
if (menu is null)
{
return result;
}
foreach (var item in menu)
{
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
{
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
var added = result.TryAdd(key, cmd);
}
}
return result;
}
}

View File

@@ -2,11 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record LaunchUriMessage(Uri Uri)
{
}
public record LaunchUriMessage(Uri Uri);

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record NavigateBackMessage(bool FromBackspace = false)
{
}
public record NavigateBackMessage(bool FromBackspace = false);

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Commands;
/// <summary>
/// Used to navigate to the next command in the page when pressing the Down key in the SearchBox.
/// </summary>
public record NavigateNextCommand
{
}
public record NavigateNextCommand;

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to navigate down one page in the page when pressing the PageDown key in the SearchBox.
/// </summary>
public record NavigatePageDownCommand
{
}
public record NavigatePageDownCommand;

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to navigate up one page in the page when pressing the PageUp key in the SearchBox.
/// </summary>
public record NavigatePageUpCommand
{
}
public record NavigatePageUpCommand;

View File

@@ -7,6 +7,4 @@ namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to navigate to the previous command in the page when pressing the Down key in the SearchBox.
/// </summary>
public record NavigatePreviousCommand
{
}
public record NavigatePreviousCommand;

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record ShowConfirmationMessage(Microsoft.CommandPalette.Extensions.IConfirmationArgs? Args)
{
}
public record ShowConfirmationMessage(Microsoft.CommandPalette.Extensions.IConfirmationArgs? Args);

View File

@@ -2,11 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record ShowDetailsMessage(DetailsViewModel Details)
{
}
public record ShowDetailsMessage(DetailsViewModel Details);

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record ShowToastMessage(string Message)
{
}
public record ShowToastMessage(string Message);

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record ShowWindowMessage(IntPtr Hwnd)
{
}
public record ShowWindowMessage(IntPtr Hwnd);

View File

@@ -2,73 +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.ComponentModel;
using Microsoft.CmdPal.Core.Common;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
/// <summary>
/// Used to update the command bar at the bottom to reflect the commands for a list item
/// </summary>
public record UpdateCommandBarMessage(ICommandBarContext? ViewModel)
{
}
public interface IContextMenuContext : INotifyPropertyChanged
{
public IEnumerable<IContextItemViewModel> MoreCommands { get; }
public bool HasMoreCommands { get; }
public List<IContextItemViewModel> AllCommands { get; }
/// <summary>
/// Generates a mapping of key -> command item for this particular item's
/// MoreCommands. (This won't include the primary Command, but it will
/// include the secondary one). This map can be used to quickly check if a
/// shortcut key was pressed
/// </summary>
/// <returns>a dictionary of KeyChord -> Context commands, for all commands
/// that have a shortcut key set.</returns>
public Dictionary<KeyChord, CommandContextItemViewModel> Keybindings()
{
var result = new Dictionary<KeyChord, CommandContextItemViewModel>();
var menu = MoreCommands;
if (menu is null)
{
return result;
}
foreach (var item in menu)
{
if (item is CommandContextItemViewModel cmd && cmd.HasRequestedShortcut)
{
var key = cmd.RequestedShortcut ?? new KeyChord(0, 0, 0);
var added = result.TryAdd(key, cmd);
if (!added)
{
CoreLogger.LogWarning($"Ignoring duplicate keyboard shortcut {KeyChordHelpers.FormatForDebug(key)} on command '{cmd.Title ?? cmd.Name ?? "(unknown)"}'");
}
}
}
return result;
}
}
// Represents everything the command bar needs to know about to show command
// buttons at the bottom.
//
// This is implemented by both ListItemViewModel and ContentPageViewModel,
// the two things with sub-commands.
public interface ICommandBarContext : IContextMenuContext
{
public string SecondaryCommandName { get; }
public CommandItemViewModel? PrimaryCommand { get; }
public CommandItemViewModel? SecondaryCommand { get; }
}
public record UpdateCommandBarMessage(ICommandBarContext? ViewModel);

View File

@@ -4,6 +4,4 @@
namespace Microsoft.CmdPal.Core.ViewModels.Messages;
public record UpdateSuggestionMessage(string TextToSuggest)
{
}
public record UpdateSuggestionMessage(string TextToSuggest);

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 Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
internal sealed partial class NullPageViewModel(TaskScheduler scheduler, AppExtensionHost extensionHost)
: PageViewModel(null, scheduler, extensionHost);
internal sealed partial class NullPageViewModel(AppExtensionHost extensionHost, ILogger logger)
: PageViewModel(null, extensionHost, logger);

View File

@@ -8,15 +8,16 @@ using CommunityToolkit.Mvvm.Input;
using Microsoft.CmdPal.Core.Common.Helpers;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
{
public TaskScheduler Scheduler { get; private set; }
private readonly ExtensionObject<IPage> _pageModel;
public TaskScheduler Scheduler { get; private set; } = TaskScheduler.FromCurrentSynchronizationContext();
public bool IsLoading => ModelIsLoading || (!IsInitialized);
[ObservableProperty]
@@ -76,11 +77,10 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
public IconInfoViewModel Icon { get; protected set; }
public PageViewModel(IPage? model, TaskScheduler scheduler, AppExtensionHost extensionHost)
: base((IPageContext?)null)
public PageViewModel(IPage? model, AppExtensionHost extensionHost, ILogger logger)
: base((IPageContext?)null, logger)
{
_pageModel = new(model);
Scheduler = scheduler;
PageContext = new(this);
ExtensionHost = extensionHost;
Icon = new(null);
@@ -258,22 +258,3 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext
}
}
}
public interface IPageContext
{
void ShowException(Exception ex, string? extensionHint = null);
TaskScheduler Scheduler { get; }
}
public interface IPageViewModelFactoryService
{
/// <summary>
/// Creates a new instance of the page view model for the given page type.
/// </summary>
/// <param name="page">The page for which to create the view model.</param>
/// <param name="nested">Indicates whether the page is not the top-level page.</param>
/// <param name="host">The command palette host that will host the page (for status messages)</param>
/// <returns>A new instance of the page view model.</returns>
PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host);
}

View File

@@ -4,6 +4,7 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -15,8 +16,8 @@ public partial class ProgressViewModel : ExtensionObjectViewModel
public uint ProgressPercent { get; private set; }
public ProgressViewModel(IProgressState progress, WeakReference<IPageContext> context)
: base(context)
public ProgressViewModel(IProgressState progress, WeakReference<IPageContext> context, ILogger logger)
: base(context, logger)
{
Model = new(progress);
}

View File

@@ -6,10 +6,10 @@ using System.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.CmdPal.Core.Common;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -18,9 +18,10 @@ public partial class ShellViewModel : ObservableObject,
IRecipient<HandleCommandResultMessage>
{
private readonly IRootPageService _rootPageService;
private readonly IAppHostService _appHostService;
private readonly TaskScheduler _scheduler;
private readonly AppExtensionHost _appHost;
private readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
private readonly IPageViewModelFactoryService _pageViewModelFactory;
private readonly ILogger _logger;
private readonly Lock _invokeLock = new();
private Task? _handleInvokeTask;
@@ -60,7 +61,7 @@ public partial class ShellViewModel : ObservableObject,
}
catch (Exception ex)
{
CoreLogger.LogError(ex.ToString());
Log_Exception(ex);
}
}
}
@@ -84,18 +85,18 @@ public partial class ShellViewModel : ObservableObject,
public PageViewModel NullPage { get; private set; }
public ShellViewModel(
TaskScheduler scheduler,
IRootPageService rootPageService,
IPageViewModelFactoryService pageViewModelFactory,
IAppHostService appHostService)
AppExtensionHost appHost,
ILogger<ShellViewModel> logger)
{
_pageViewModelFactory = pageViewModelFactory;
_scheduler = scheduler;
_rootPageService = rootPageService;
_appHostService = appHostService;
_appHost = appHost;
_logger = logger;
NullPage = new NullPageViewModel(_scheduler, appHostService.GetDefaultHost());
_currentPage = new LoadingPageViewModel(null, _scheduler, appHostService.GetDefaultHost());
NullPage = new NullPageViewModel(_appHost, _logger);
_currentPage = new LoadingPageViewModel(null, _appHost, _logger);
// Register to receive messages
WeakReferenceMessenger.Default.Register<PerformCommandMessage>(this);
@@ -162,7 +163,7 @@ public partial class ShellViewModel : ObservableObject,
{
if (viewModel.InitializeCommand.ExecutionTask.Exception is AggregateException ex)
{
CoreLogger.LogError(ex.ToString());
Log_Exception(ex);
}
}
else
@@ -180,7 +181,7 @@ public partial class ShellViewModel : ObservableObject,
}
catch (Exception ex)
{
CoreLogger.LogError(ex.ToString());
Log_Exception(ex);
}
}
@@ -210,7 +211,7 @@ public partial class ShellViewModel : ObservableObject,
}
catch (Exception ex)
{
CoreLogger.LogError(ex.ToString());
Log_Exception(ex);
}
}
@@ -240,7 +241,7 @@ public partial class ShellViewModel : ObservableObject,
}
catch (Exception ex)
{
CoreLogger.LogError(ex.ToString());
Log_Exception(ex);
}
finally
{
@@ -256,7 +257,7 @@ public partial class ShellViewModel : ObservableObject,
return;
}
var host = _appHostService.GetHostForCommand(message.Context, CurrentPage.ExtensionHost);
var host = _appHost.GetHostForCommand(message.Context, CurrentPage.ExtensionHost);
_rootPageService.OnPerformCommand(message.Context, !CurrentPage.IsNested, host);
@@ -264,7 +265,7 @@ public partial class ShellViewModel : ObservableObject,
{
if (command is IPage page)
{
CoreLogger.LogDebug($"Navigating to page");
Log_NavigateToPage();
var isMainPage = command == _rootPage;
_isNested = !isMainPage;
@@ -273,7 +274,7 @@ public partial class ShellViewModel : ObservableObject,
var pageViewModel = _pageViewModelFactory.TryCreatePageViewModel(page, _isNested, host);
if (pageViewModel is null)
{
CoreLogger.LogError($"Failed to create ViewModel for page {page.GetType().Name}");
Log_FailedToCreateViewModel(page.GetType().Name);
throw new NotSupportedException();
}
@@ -303,7 +304,7 @@ public partial class ShellViewModel : ObservableObject,
}
else if (command is IInvokableCommand invokable)
{
CoreLogger.LogDebug($"Invoking command");
Log_InvokingCommand();
WeakReferenceMessenger.Default.Send<BeginInvokeMessage>();
StartInvoke(message, invokable, host);
@@ -369,7 +370,7 @@ public partial class ShellViewModel : ObservableObject,
}
var kind = result.Kind;
CoreLogger.LogDebug($"handling {kind.ToString()}");
Log_HandlingCommandResult(kind.ToString());
WeakReferenceMessenger.Default.Send<CmdPalInvokeResultMessage>(new(kind));
switch (kind)
@@ -460,4 +461,19 @@ public partial class ShellViewModel : ObservableObject,
{
_navigationCts?.Cancel();
}
[LoggerMessage(Level = LogLevel.Error)]
partial void Log_Exception(Exception exception);
[LoggerMessage(Level = LogLevel.Debug, Message = "Navigating to page")]
partial void Log_NavigateToPage();
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to create ViewModel for page {PageTypeName}")]
partial void Log_FailedToCreateViewModel(string pageTypeName);
[LoggerMessage(Level = LogLevel.Debug, Message = "Invoking command")]
partial void Log_InvokingCommand();
[LoggerMessage(Level = LogLevel.Debug, Message = "Handling {CommandResultKind}")]
partial void Log_HandlingCommandResult(string commandResultKind);
}

View File

@@ -4,6 +4,7 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
@@ -19,8 +20,8 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel
public bool HasProgress => Progress is not null;
public StatusMessageViewModel(IStatusMessage message, WeakReference<IPageContext> context)
: base(context)
public StatusMessageViewModel(IStatusMessage message, WeakReference<IPageContext> context, ILogger logger)
: base(context, logger)
{
Model = new(message);
}
@@ -38,7 +39,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel
var modelProgress = model.Progress;
if (modelProgress is not null)
{
Progress = new(modelProgress, this.PageContext);
Progress = new(modelProgress, this.PageContext, Logger);
Progress.InitializeProperties();
UpdateProperty(nameof(HasProgress));
}
@@ -78,7 +79,7 @@ public partial class StatusMessageViewModel : ExtensionObjectViewModel
var modelProgress = model.Progress;
if (modelProgress is not null)
{
Progress = new(modelProgress, this.PageContext);
Progress = new(modelProgress, this.PageContext, Logger);
Progress.InitializeProperties();
}
else

View File

@@ -4,10 +4,11 @@
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.Core.ViewModels;
public partial class TagViewModel(ITag _tag, WeakReference<IPageContext> context) : ExtensionObjectViewModel(context)
public partial class TagViewModel(ITag _tag, WeakReference<IPageContext> context, ILogger logger) : ExtensionObjectViewModel(context, logger)
{
private readonly ExtensionObject<ITag> _tagModel = new(_tag);

View File

@@ -4,23 +4,20 @@
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandPaletteContentPageViewModel : ContentPageViewModel
public partial class CommandPaletteContentPageViewModel(IContentPage model, AppExtensionHost host, ILogger logger)
: ContentPageViewModel(model, host, logger)
{
public CommandPaletteContentPageViewModel(IContentPage model, TaskScheduler scheduler, AppExtensionHost host)
: base(model, scheduler, host)
{
}
public override ContentViewModel? ViewModelFromContent(IContent content, WeakReference<IPageContext> context)
{
ContentViewModel? viewModel = content switch
{
IFormContent form => new ContentFormViewModel(form, context),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
ITreeContent tree => new ContentTreeViewModel(tree, context),
IFormContent form => new ContentFormViewModel(form, context, Logger),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context, Logger),
ITreeContent tree => new ContentTreeViewModel(tree, context, Logger),
_ => null,
};
return viewModel;

View File

@@ -5,29 +5,29 @@
using Microsoft.CmdPal.Core.Common.Services;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
public sealed partial class CommandPaletteHost : AppExtensionHost, IExtensionHost
{
// Static singleton, so that we can access this from anywhere
// Post MVVM - this should probably be like, a dependency injection thing.
public static CommandPaletteHost Instance { get; } = new();
public IExtensionWrapper? Extension { get; }
private readonly ICommandProvider? _builtInProvider;
private CommandPaletteHost()
public CommandPaletteHost(ILogger logger)
: base(logger)
{
}
public CommandPaletteHost(IExtensionWrapper source)
public CommandPaletteHost(IExtensionWrapper source, ILogger logger)
: base(logger)
{
Extension = source;
}
public CommandPaletteHost(ICommandProvider builtInProvider)
public CommandPaletteHost(ICommandProvider builtInProvider, ILogger logger)
: base(logger)
{
_builtInProvider = builtInProvider;
}
@@ -36,4 +36,15 @@ public sealed partial class CommandPaletteHost : AppExtensionHost, IExtensionHos
{
return Extension?.ExtensionDisplayName;
}
public override AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost)
{
AppExtensionHost? topLevelHost = null;
if (context is TopLevelViewModel topLevelViewModel)
{
topLevelHost = topLevelViewModel.ExtensionHost;
}
return topLevelHost ?? currentHost ?? this;
}
}

View File

@@ -4,25 +4,27 @@
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
public class CommandPalettePageViewModelFactory
: IPageViewModelFactoryService
{
private readonly TaskScheduler _scheduler;
private readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();
private readonly ILogger _logger;
public CommandPalettePageViewModelFactory(TaskScheduler scheduler)
public CommandPalettePageViewModelFactory(ILogger logger)
{
_scheduler = scheduler;
_logger = logger;
}
public PageViewModel? TryCreatePageViewModel(IPage page, bool nested, AppExtensionHost host)
{
return page switch
{
IListPage listPage => new ListViewModel(listPage, _scheduler, host) { IsNested = nested },
IContentPage contentPage => new CommandPaletteContentPageViewModel(contentPage, _scheduler, host),
IListPage listPage => new ListViewModel(listPage, _scheduler, host, _logger) { IsNested = nested },
IContentPage contentPage => new CommandPaletteContentPageViewModel(contentPage, host, _logger),
_ => null,
};
}

View File

@@ -2,22 +2,23 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using ManagedCommon;
using Microsoft.CmdPal.Core.Common.Services;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Windows.Foundation;
namespace Microsoft.CmdPal.UI.ViewModels;
public sealed class CommandProviderWrapper
public sealed partial class CommandProviderWrapper
{
public bool IsExtension => Extension is not null;
private readonly bool isValid;
private readonly ILogger _logger;
private readonly AliasManager _aliasManager;
private readonly HotkeyManager _hotKeyManager;
private readonly ExtensionObject<ICommandProvider> _commandProvider;
@@ -51,15 +52,18 @@ public sealed class CommandProviderWrapper
}
}
public CommandProviderWrapper(ICommandProvider provider, TaskScheduler mainThread)
public CommandProviderWrapper(ICommandProvider provider, TaskScheduler mainThread, AliasManager aliasManager, HotkeyManager hotkeyManager, ILogger logger)
{
// This ctor is only used for in-proc builtin commands. So the Unsafe!
// calls are pretty dang safe actually.
_commandProvider = new(provider);
_taskScheduler = mainThread;
_logger = logger;
_aliasManager = aliasManager;
_hotKeyManager = hotkeyManager;
// Hook the extension back into us
ExtensionHost = new CommandPaletteHost(provider);
ExtensionHost = new CommandPaletteHost(provider, logger);
_commandProvider.Unsafe!.InitializeWithHost(ExtensionHost);
_commandProvider.Unsafe!.ItemsChanged += CommandProvider_ItemsChanged;
@@ -72,16 +76,20 @@ public sealed class CommandProviderWrapper
// Note: explicitly not InitializeProperties()ing the settings here. If
// we do that, then we'd regress GH #38321
Settings = new(provider.Settings, this, _taskScheduler);
Settings = new(provider.Settings, this, _taskScheduler, _logger);
Logger.LogDebug($"Initialized command provider {ProviderId}");
Log_CommandProviderInitialized(ProviderId);
}
public CommandProviderWrapper(IExtensionWrapper extension, TaskScheduler mainThread)
public CommandProviderWrapper(IExtensionWrapper extension, TaskScheduler mainThread, AliasManager aliasManager, HotkeyManager hotkeyManager, ILogger logger)
{
_taskScheduler = mainThread;
_logger = logger;
_aliasManager = aliasManager;
_hotKeyManager = hotkeyManager;
Extension = extension;
ExtensionHost = new CommandPaletteHost(extension);
ExtensionHost = new CommandPaletteHost(extension, logger);
if (!Extension.IsRunning())
{
throw new ArgumentException("You forgot to start the extension. This is a CmdPal error - we need to make sure to call StartExtensionAsync");
@@ -106,13 +114,11 @@ public sealed class CommandProviderWrapper
isValid = true;
Logger.LogDebug($"Initialized extension command provider {Extension.PackageFamilyName}:{Extension.ExtensionUniqueId}");
Log_ExtensionInitialized(Extension.PackageFamilyName, Extension.ExtensionUniqueId);
}
catch (Exception e)
{
Logger.LogError("Failed to initialize CommandProvider for extension.");
Logger.LogError($"Extension was {Extension!.PackageFamilyName}");
Logger.LogError(e.ToString());
Log_FailedToInitializeCommandProviderForExtension(Extension!.PackageFamilyName, e);
}
isValid = true;
@@ -123,7 +129,7 @@ public sealed class CommandProviderWrapper
return settings.GetProviderSettings(this);
}
public async Task LoadTopLevelCommands(IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
public async Task LoadTopLevelCommands(SettingsModel settingsModel, WeakReference<IPageContext> pageContext)
{
if (!isValid)
{
@@ -131,9 +137,7 @@ public sealed class CommandProviderWrapper
return;
}
var settings = serviceProvider.GetService<SettingsModel>()!;
IsActive = GetProviderSettings(settings).IsEnabled;
IsActive = GetProviderSettings(settingsModel).IsEnabled;
if (!IsActive)
{
return;
@@ -165,30 +169,27 @@ public sealed class CommandProviderWrapper
// Note: explicitly not InitializeProperties()ing the settings here. If
// we do that, then we'd regress GH #38321
Settings = new(model.Settings, this, _taskScheduler);
Settings = new(model.Settings, this, _taskScheduler, _logger);
// We do need to explicitly initialize commands though
InitializeCommands(commands, fallbacks, serviceProvider, pageContext);
InitializeCommands(commands, fallbacks, settingsModel, pageContext);
Logger.LogDebug($"Loaded commands from {DisplayName} ({ProviderId})");
Log_LoadedCommandsFromExtension(DisplayName, ProviderId);
}
catch (Exception e)
{
Logger.LogError("Failed to load commands from extension");
Logger.LogError($"Extension was {Extension!.PackageFamilyName}");
Logger.LogError(e.ToString());
Log_FailedToLoadCommandsFromProvider(Extension!.PackageFamilyName, e);
}
}
private void InitializeCommands(ICommandItem[] commands, IFallbackCommandItem[] fallbacks, IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
private void InitializeCommands(ICommandItem[] commands, IFallbackCommandItem[] fallbacks, SettingsModel settingsModel, WeakReference<IPageContext> pageContext)
{
var settings = serviceProvider.GetService<SettingsModel>()!;
var providerSettings = GetProviderSettings(settings);
var providerSettings = GetProviderSettings(settingsModel);
Func<ICommandItem?, bool, TopLevelViewModel> makeAndAdd = (ICommandItem? i, bool fallback) =>
{
CommandItemViewModel commandItemViewModel = new(new(i), pageContext);
TopLevelViewModel topLevelViewModel = new(commandItemViewModel, fallback, ExtensionHost, ProviderId, settings, providerSettings, serviceProvider);
CommandItemViewModel commandItemViewModel = new(new(i), pageContext, _logger);
TopLevelViewModel topLevelViewModel = new(commandItemViewModel, fallback, ExtensionHost, ProviderId, settingsModel, providerSettings, _aliasManager, _hotKeyManager);
topLevelViewModel.InitializeProperties();
return topLevelViewModel;
@@ -211,12 +212,13 @@ public sealed class CommandProviderWrapper
private void UnsafePreCacheApiAdditions(ICommandProvider2 provider)
{
var apiExtensions = provider.GetApiExtensionStubs();
Logger.LogDebug($"Provider supports {apiExtensions.Length} extensions");
Log_ProviderCount(apiExtensions.Length);
foreach (var a in apiExtensions)
{
if (a is IExtendedAttributesProvider command2)
{
Logger.LogDebug($"{ProviderId}: Found an IExtendedAttributesProvider");
Log_IExtendedAttributesProviderFound(ProviderId);
}
}
}
@@ -234,4 +236,25 @@ public sealed class CommandProviderWrapper
// In handling this, a call will be made to `LoadTopLevelCommands` to
// retrieve the new items.
this.CommandsChanged?.Invoke(this, args);
[LoggerMessage(Level = LogLevel.Debug, Message = "Initialized CommandProvider '{ProviderId}'")]
partial void Log_CommandProviderInitialized(string providerId);
[LoggerMessage(Level = LogLevel.Debug, Message = "{ProviderId}: Found an IExtendedAttributesProvider")]
partial void Log_IExtendedAttributesProviderFound(string providerId);
[LoggerMessage(Level = LogLevel.Debug, Message = "Provider exposed {Count} API extensions")]
partial void Log_ProviderCount(int count);
[LoggerMessage(Level = LogLevel.Debug, Message = "Initialized CommandProvider from extension '{PackageFamilyName}' ({ExtensionId})")]
partial void Log_ExtensionInitialized(string packageFamilyName, string extensionId);
[LoggerMessage(Level = LogLevel.Debug, Message = "Loaded commands from {DisplayName} ({ProviderId})")]
partial void Log_LoadedCommandsFromExtension(string displayName, string providerId);
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to load commands from extension '{PackageFamilyName}'")]
partial void Log_FailedToLoadCommandsFromProvider(string packageFamilyName, Exception exception);
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to initialize CommandProvider for extension '{PackageFamilyName}'")]
partial void Log_FailedToInitializeCommandProviderForExtension(string packageFamilyName, Exception exception);
}

View File

@@ -2,14 +2,14 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Core.Common;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread)
public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings, CommandProviderWrapper provider, TaskScheduler mainThread, ILogger logger)
{
private readonly ExtensionObject<ICommandSettings> _model = new(_unsafeSettings);
@@ -31,7 +31,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
if (model.SettingsPage is not null)
{
SettingsPage = new CommandPaletteContentPageViewModel(model.SettingsPage, mainThread, provider.ExtensionHost);
SettingsPage = new CommandPaletteContentPageViewModel(model.SettingsPage, provider.ExtensionHost, logger);
SettingsPage.InitializeProperties();
}
}
@@ -44,7 +44,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
}
catch (Exception ex)
{
CoreLogger.LogError($"Failed to load settings page", ex: ex);
Log_FailedToLoadSettingsPage(ex);
}
Initialized = true;
@@ -58,4 +58,7 @@ public partial class CommandSettingsViewModel(ICommandSettings? _unsafeSettings,
TaskCreationOptions.None,
mainThread);
}
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to load settings page")]
partial void Log_FailedToLoadSettingsPage(Exception ex);
}

View File

@@ -38,7 +38,6 @@ public partial class MainListPage : DynamicListPage,
"com.microsoft.cmdpal.builtin.datetime",
];
private readonly IServiceProvider _serviceProvider;
private readonly TopLevelCommandManager _tlcManager;
private List<Scored<IListItem>>? _filteredItems;
private List<Scored<IListItem>>? _filteredApps;
@@ -53,14 +52,13 @@ public partial class MainListPage : DynamicListPage,
private CancellationTokenSource? _cancellationTokenSource;
public MainListPage(IServiceProvider serviceProvider)
public MainListPage(TopLevelCommandManager topLevelCommandManager, SettingsModel settingsModel)
{
Title = Resources.builtin_home_name;
Icon = IconHelpers.FromRelativePath("Assets\\StoreLogo.scale-200.png");
PlaceholderText = Properties.Resources.builtin_main_list_page_searchbar_placeholder;
_serviceProvider = serviceProvider;
_tlcManager = _serviceProvider.GetService<TopLevelCommandManager>()!;
_tlcManager = topLevelCommandManager;
_tlcManager.PropertyChanged += TlcManager_PropertyChanged;
_tlcManager.TopLevelCommands.CollectionChanged += Commands_CollectionChanged;
@@ -78,7 +76,7 @@ public partial class MainListPage : DynamicListPage,
WeakReferenceMessenger.Default.Register<ClearSearchMessage>(this);
WeakReferenceMessenger.Default.Register<UpdateFallbackItemsMessage>(this);
var settings = _serviceProvider.GetService<SettingsModel>()!;
var settings = settingsModel;
settings.SettingsChanged += SettingsChangedHandler;
HotReloadSettings(settings);
_includeApps = _tlcManager.IsProviderActive(AllAppsCommandProvider.WellKnownId);

View File

@@ -7,19 +7,26 @@ using System.Text.Json;
using AdaptiveCards.ObjectModel.WinUI3;
using AdaptiveCards.Templating;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Messages;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
using Windows.Data.Json;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPageContext> context) :
ContentViewModel(context)
public partial class ContentFormViewModel : ContentViewModel
{
private readonly ExtensionObject<IFormContent> _formModel = new(_form);
private readonly ExtensionObject<IFormContent> _formModel;
private readonly ILogger _logger;
public ContentFormViewModel(IFormContent _form, WeakReference<IPageContext> context, ILogger logger)
: base(context, logger)
{
_formModel = new(_form);
_logger = logger;
}
// Remember - "observable" properties from the model (via PropChanged)
// cannot be marked [ObservableProperty]
@@ -38,7 +45,8 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
string templateJson,
string dataJson,
out AdaptiveCardParseResult? card,
out Exception? error)
out Exception? error,
ILogger logger)
{
card = null;
error = null;
@@ -52,7 +60,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
}
catch (Exception ex)
{
Logger.LogError("Error building card from template", ex);
Log_ErrorBuildindCard(logger, ex);
error = ex;
return false;
}
@@ -70,7 +78,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
StateJson = model.StateJson;
DataJson = model.DataJson;
if (TryBuildCard(TemplateJson, DataJson, out var builtCard, out var renderingError))
if (TryBuildCard(TemplateJson, DataJson, out var builtCard, out var renderingError, _logger))
{
Card = builtCard;
UpdateProperty(nameof(Card));
@@ -87,7 +95,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
}
""";
if (TryBuildCard(ErrorCardJson, errorPayload, out var errorCard, out var _))
if (TryBuildCard(ErrorCardJson, errorPayload, out var errorCard, out var _, _logger))
{
Card = errorCard;
UpdateProperty(nameof(Card));
@@ -173,4 +181,7 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference<IPag
]
}
""";
[LoggerMessage(Level = LogLevel.Error, Message = "Error building adaptive card for form.")]
static partial void Log_ErrorBuildindCard(ILogger logger, Exception ex);
}

View File

@@ -5,11 +5,12 @@
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakReference<IPageContext> context) :
ContentViewModel(context)
public partial class ContentMarkdownViewModel(IMarkdownContent _markdown, WeakReference<IPageContext> context, ILogger logger) :
ContentViewModel(context, logger)
{
public ExtensionObject<IMarkdownContent> Model { get; } = new(_markdown);

View File

@@ -7,11 +7,12 @@ using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Core.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPageContext> context) :
ContentViewModel(context)
public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPageContext> context, ILogger logger) :
ContentViewModel(context, logger)
{
public ExtensionObject<ITreeContent> Model { get; } = new(_tree);
@@ -55,9 +56,9 @@ public partial class ContentTreeViewModel(ITreeContent _tree, WeakReference<IPag
{
ContentViewModel? viewModel = content switch
{
IFormContent form => new ContentFormViewModel(form, context),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context),
ITreeContent tree => new ContentTreeViewModel(tree, context),
IFormContent form => new ContentFormViewModel(form, context, Logger),
IMarkdownContent markdown => new ContentMarkdownViewModel(markdown, context, Logger),
ITreeContent tree => new ContentTreeViewModel(tree, context, Logger),
_ => null,
};
return viewModel;

View File

@@ -2,9 +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 ManagedCommon;
using Microsoft.CmdPal.Core.Common.Services;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.Logging;
using Windows.ApplicationModel;
using Windows.ApplicationModel.AppExtensions;
using Windows.Foundation;
@@ -22,6 +22,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
private static readonly Lock _lock = new();
private readonly SemaphoreSlim _getInstalledExtensionsLock = new(1, 1);
private readonly SemaphoreSlim _getInstalledWidgetsLock = new(1, 1);
private readonly ILogger _logger;
// private readonly ILocalSettingsService _localSettingsService;
private bool _disposedValue;
@@ -32,8 +33,9 @@ public partial class ExtensionService : IExtensionService, IDisposable
private static readonly List<IExtensionWrapper> _installedExtensions = [];
private static readonly List<IExtensionWrapper> _enabledExtensions = [];
public ExtensionService()
public ExtensionService(ILogger logger)
{
_logger = logger;
_catalog.PackageInstalling += Catalog_PackageInstalling;
_catalog.PackageUninstalling += Catalog_PackageUninstalling;
_catalog.PackageUpdating += Catalog_PackageUpdating;
@@ -92,14 +94,14 @@ public partial class ExtensionService : IExtensionService, IDisposable
var extension = isCmdPalExtensionResult.Extension;
if (isExtension && extension is not null)
{
CommandPaletteHost.Instance.DebugLog($"Installed new extension app {extension.DisplayName}");
Log_ExtensionInstalled(extension.DisplayName);
Task.Run(async () =>
{
await _getInstalledExtensionsLock.WaitAsync();
try
{
var wrappers = await CreateWrappersForExtension(extension);
var wrappers = await CreateWrappersForExtension(extension, _logger);
UpdateExtensionsListsFromWrappers(wrappers);
@@ -120,7 +122,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
{
if (extension.PackageFullName == package.Id.FullName)
{
CommandPaletteHost.Instance.DebugLog($"Uninstalled extension app {extension.PackageDisplayName}");
Log_ExtensionUninstalled(extension.PackageDisplayName);
removedExtensions.Add(extension);
}
@@ -199,7 +201,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
var extensions = await GetInstalledAppExtensionsAsync();
foreach (var extension in extensions)
{
var wrappers = await CreateWrappersForExtension(extension);
var wrappers = await CreateWrappersForExtension(extension, _logger);
UpdateExtensionsListsFromWrappers(wrappers);
}
}
@@ -233,7 +235,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
}
}
private static async Task<List<ExtensionWrapper>> CreateWrappersForExtension(AppExtension extension)
private static async Task<List<ExtensionWrapper>> CreateWrappersForExtension(AppExtension extension, ILogger logger)
{
var (cmdPalProvider, classIds) = await GetCmdPalExtensionPropertiesAsync(extension);
@@ -245,14 +247,14 @@ public partial class ExtensionService : IExtensionService, IDisposable
List<ExtensionWrapper> wrappers = [];
foreach (var classId in classIds)
{
var extensionWrapper = CreateExtensionWrapper(extension, cmdPalProvider, classId);
var extensionWrapper = CreateExtensionWrapper(extension, cmdPalProvider, classId, logger);
wrappers.Add(extensionWrapper);
}
return wrappers;
}
private static ExtensionWrapper CreateExtensionWrapper(AppExtension extension, IPropertySet cmdPalProvider, string classId)
private static ExtensionWrapper CreateExtensionWrapper(AppExtension extension, IPropertySet cmdPalProvider, string classId, ILogger logger)
{
var extensionWrapper = new ExtensionWrapper(extension, classId);
@@ -269,7 +271,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
else
{
// log warning that extension declared unsupported extension interface
CommandPaletteHost.Instance.DebugLog($"Extension {extension.DisplayName} declared an unsupported interface: {supportedInterface.Key}");
Log_InvalidExtensionInterface(logger, extension.DisplayName, supportedInterface.Key);
}
}
}
@@ -288,7 +290,8 @@ public partial class ExtensionService : IExtensionService, IDisposable
var installedExtensions = await GetInstalledExtensionsAsync();
foreach (var installedExtension in installedExtensions)
{
Logger.LogDebug($"Signaling dispose to {installedExtension.ExtensionUniqueId}");
Log_SignalingDispose(installedExtension.ExtensionUniqueId);
try
{
if (installedExtension.IsRunning())
@@ -298,7 +301,7 @@ public partial class ExtensionService : IExtensionService, IDisposable
}
catch (Exception ex)
{
Logger.LogError($"Failed to send dispose signal to extension {installedExtension.ExtensionUniqueId}", ex);
Log_ErrorSignalingDispose(installedExtension.ExtensionUniqueId, ex);
}
}
}
@@ -400,6 +403,21 @@ public partial class ExtensionService : IExtensionService, IDisposable
_enabledExtensions.Remove(extension.First());
}
[LoggerMessage(Level = LogLevel.Information, Message = "Installed new extension app {ExtensionName}")]
partial void Log_ExtensionInstalled(string extensionName);
[LoggerMessage(Level = LogLevel.Information, Message = "Uninstalled extension app {ExtensionName}")]
partial void Log_ExtensionUninstalled(string extensionName);
[LoggerMessage(Level = LogLevel.Debug, Message = "Signaling dispose to {ExtensionUniqueId}")]
partial void Log_SignalingDispose(string extensionUniqueId);
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to send dispose signal to extension {ExtensionUniqueId}")]
partial void Log_ErrorSignalingDispose(string extensionUniqueId, Exception exception);
[LoggerMessage(Level = LogLevel.Warning, Message = "Extension {ExtensionName} declared unsupported extension interface: {InterfaceName}")]
static partial void Log_InvalidExtensionInterface(ILogger logger, string extensionName, string interfaceName);
/*
///// <inheritdoc cref="IExtensionService.DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper)"/>
//public async Task<bool> DisableExtensionIfWindowsFeatureNotAvailable(IExtensionWrapper extension)

View File

@@ -8,14 +8,13 @@ using System.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using ManagedCommon;
using Microsoft.CmdPal.Core.Common.Helpers;
using Microsoft.CmdPal.Core.Common.Services;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Microsoft.CmdPal.UI.ViewModels;
@@ -24,8 +23,14 @@ public partial class TopLevelCommandManager : ObservableObject,
IPageContext,
IDisposable
{
private readonly IServiceProvider _serviceProvider;
private readonly TaskScheduler _taskScheduler;
private readonly TaskScheduler _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
private readonly ILogger _logger;
private readonly AppExtensionHost _commandPaletteHost;
private readonly IExtensionService _extensionService;
private readonly IEnumerable<ICommandProvider> _builtInProviders;
private readonly SettingsModel _settingsModel;
private readonly AliasManager _aliasManager;
private readonly HotkeyManager _hotkeyManager;
private readonly List<CommandProviderWrapper> _builtInCommands = [];
private readonly List<CommandProviderWrapper> _extensionCommandProviders = [];
@@ -34,10 +39,22 @@ public partial class TopLevelCommandManager : ObservableObject,
TaskScheduler IPageContext.Scheduler => _taskScheduler;
public TopLevelCommandManager(IServiceProvider serviceProvider)
public TopLevelCommandManager(
AppExtensionHost commandPaletteHost,
IExtensionService extensionService,
IEnumerable<ICommandProvider> builtInProviders,
SettingsModel settingsModel,
AliasManager aliasManager,
HotkeyManager hotkeyManager,
ILogger logger)
{
_serviceProvider = serviceProvider;
_taskScheduler = _serviceProvider.GetService<TaskScheduler>()!;
_logger = logger;
_commandPaletteHost = commandPaletteHost;
_extensionService = extensionService;
_builtInProviders = builtInProviders;
_settingsModel = settingsModel;
_aliasManager = aliasManager;
_hotkeyManager = hotkeyManager;
WeakReferenceMessenger.Default.Register<ReloadCommandsMessage>(this);
_reloadCommandsGate = new(ReloadAllCommandsAsyncCore);
}
@@ -70,10 +87,9 @@ public partial class TopLevelCommandManager : ObservableObject,
// Load built-In commands first. These are all in-proc, and
// owned by our ServiceProvider.
var builtInCommands = _serviceProvider.GetServices<ICommandProvider>();
foreach (var provider in builtInCommands)
foreach (var provider in _builtInProviders)
{
CommandProviderWrapper wrapper = new(provider, _taskScheduler);
CommandProviderWrapper wrapper = new(provider, _taskScheduler, _aliasManager, _hotkeyManager, _logger);
lock (_commandProvidersLock)
{
_builtInCommands.Add(wrapper);
@@ -91,7 +107,7 @@ public partial class TopLevelCommandManager : ObservableObject,
s.Stop();
Logger.LogDebug($"Loading built-ins took {s.ElapsedMilliseconds}ms");
Log_BuiltInsLoaded(s.ElapsedMilliseconds);
return true;
}
@@ -101,7 +117,7 @@ public partial class TopLevelCommandManager : ObservableObject,
{
WeakReference<IPageContext> weakSelf = new(this);
await commandProvider.LoadTopLevelCommands(_serviceProvider, weakSelf);
await commandProvider.LoadTopLevelCommands(_settingsModel, weakSelf);
var commands = await Task.Factory.StartNew(
() =>
@@ -149,7 +165,7 @@ public partial class TopLevelCommandManager : ObservableObject,
private async Task UpdateCommandsForProvider(CommandProviderWrapper sender, IItemsChangedEventArgs args)
{
WeakReference<IPageContext> weakSelf = new(this);
await sender.LoadTopLevelCommands(_serviceProvider, weakSelf);
await sender.LoadTopLevelCommands(_settingsModel, weakSelf);
List<TopLevelViewModel> newItems = [.. sender.TopLevelItems];
foreach (var i in sender.FallbackItems)
@@ -216,8 +232,7 @@ public partial class TopLevelCommandManager : ObservableObject,
private async Task ReloadAllCommandsAsyncCore(CancellationToken cancellationToken)
{
IsLoading = true;
var extensionService = _serviceProvider.GetService<IExtensionService>()!;
await extensionService.SignalStopExtensionsAsync();
await _extensionService.SignalStopExtensionsAsync();
lock (TopLevelCommands)
{
@@ -238,12 +253,10 @@ public partial class TopLevelCommandManager : ObservableObject,
[RelayCommand]
public async Task<bool> LoadExtensionsAsync()
{
var extensionService = _serviceProvider.GetService<IExtensionService>()!;
_extensionService.OnExtensionAdded -= ExtensionService_OnExtensionAdded;
_extensionService.OnExtensionRemoved -= ExtensionService_OnExtensionRemoved;
extensionService.OnExtensionAdded -= ExtensionService_OnExtensionAdded;
extensionService.OnExtensionRemoved -= ExtensionService_OnExtensionRemoved;
var extensions = (await extensionService.GetInstalledExtensionsAsync()).ToImmutableList();
var extensions = (await _extensionService.GetInstalledExtensionsAsync()).ToImmutableList();
lock (_commandProvidersLock)
{
_extensionCommandProviders.Clear();
@@ -254,8 +267,8 @@ public partial class TopLevelCommandManager : ObservableObject,
await StartExtensionsAndGetCommands(extensions);
}
extensionService.OnExtensionAdded += ExtensionService_OnExtensionAdded;
extensionService.OnExtensionRemoved += ExtensionService_OnExtensionRemoved;
_extensionService.OnExtensionAdded += ExtensionService_OnExtensionAdded;
_extensionService.OnExtensionRemoved += ExtensionService_OnExtensionRemoved;
IsLoading = false;
@@ -310,20 +323,20 @@ public partial class TopLevelCommandManager : ObservableObject,
}
timer.Stop();
Logger.LogDebug($"Loading extensions took {timer.ElapsedMilliseconds} ms");
Log_ExtensionsLoaded(timer.ElapsedMilliseconds);
}
private async Task<CommandProviderWrapper?> StartExtensionWithTimeoutAsync(IExtensionWrapper extension)
{
Logger.LogDebug($"Starting {extension.PackageFullName}");
Log_StartingExtension(extension.PackageFullName);
try
{
await extension.StartExtensionAsync().WaitAsync(TimeSpan.FromSeconds(10));
return new CommandProviderWrapper(extension, _taskScheduler);
return new CommandProviderWrapper(extension, _taskScheduler, _aliasManager, _hotkeyManager, _logger);
}
catch (Exception ex)
{
Logger.LogError($"Failed to start extension {extension.PackageFullName}: {ex}");
Log_FailedToStartExtension(extension.PackageFullName, ex);
return null; // Return null for failed extensions
}
}
@@ -336,11 +349,11 @@ public partial class TopLevelCommandManager : ObservableObject,
}
catch (TimeoutException)
{
Logger.LogError($"Loading commands from {wrapper!.ExtensionHost?.Extension?.PackageFullName} timed out");
Log_LoadingCommandsTimedOut(wrapper!.ExtensionHost?.Extension?.PackageFullName);
}
catch (Exception ex)
{
Logger.LogError($"Failed to load commands for extension {wrapper!.ExtensionHost?.Extension?.PackageFullName}: {ex}");
Log_FailedToLoadCommandsForExtension(wrapper!.ExtensionHost?.Extension?.PackageFullName, ex);
}
return null;
@@ -414,7 +427,7 @@ public partial class TopLevelCommandManager : ObservableObject,
void IPageContext.ShowException(Exception ex, string? extensionHint)
{
var message = DiagnosticsHelper.BuildExceptionMessage(ex, extensionHint ?? "TopLevelCommandManager");
CommandPaletteHost.Instance.Log(message);
_commandPaletteHost.Log(message);
}
internal bool IsProviderActive(string id)
@@ -431,4 +444,22 @@ public partial class TopLevelCommandManager : ObservableObject,
_reloadCommandsGate.Dispose();
GC.SuppressFinalize(this);
}
[LoggerMessage(Level = LogLevel.Debug, Message = "Loading built-ins took {ElapsedMilliseconds}ms")]
partial void Log_BuiltInsLoaded(long elapsedMilliseconds);
[LoggerMessage(Level = LogLevel.Debug, Message = "Loading extensions took {ElapsedMilliseconds}ms")]
partial void Log_ExtensionsLoaded(long elapsedMilliseconds);
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to load commands for extension {ExtensionName}")]
partial void Log_FailedToLoadCommandsForExtension(string? extensionName, Exception exception);
[LoggerMessage(Level = LogLevel.Warning, Message = "Loading commands for extension {ExtensionName} timed out")]
partial void Log_LoadingCommandsTimedOut(string? extensionName);
[LoggerMessage(Level = LogLevel.Error, Message = "Failed to start extension {ExtensionName}")]
partial void Log_FailedToStartExtension(string extensionName, Exception exception);
[LoggerMessage(Level = LogLevel.Debug, Message = "Starting extension {ExtensionName}")]
partial void Log_StartingExtension(string extensionName);
}

View File

@@ -12,7 +12,6 @@ using Microsoft.CmdPal.UI.ViewModels.Messages;
using Microsoft.CmdPal.UI.ViewModels.Settings;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Extensions.DependencyInjection;
using Windows.Foundation;
using WyHash;
@@ -22,7 +21,8 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
{
private readonly SettingsModel _settings;
private readonly ProviderSettings _providerSettings;
private readonly IServiceProvider _serviceProvider;
private readonly HotkeyManager _hotKeyManager;
private readonly AliasManager _aliasManager;
private readonly CommandItemViewModel _commandItemViewModel;
private readonly string _commandProviderId;
@@ -99,7 +99,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
get => _hotkey;
set
{
_serviceProvider.GetService<HotkeyManager>()!.UpdateHotkey(Id, value);
_hotKeyManager.UpdateHotkey(Id, value);
UpdateHotkey();
UpdateTags();
Save();
@@ -177,9 +177,11 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
string commandProviderId,
SettingsModel settings,
ProviderSettings providerSettings,
IServiceProvider serviceProvider)
AliasManager aliasManager,
HotkeyManager hotkeyManager)
{
_serviceProvider = serviceProvider;
_hotKeyManager = hotkeyManager;
_aliasManager = aliasManager;
_settings = settings;
_providerSettings = providerSettings;
_commandProviderId = commandProviderId;
@@ -268,16 +270,15 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
? null
: new CommandAlias(Alias.Alias, Alias.CommandId, Alias.IsDirect);
_serviceProvider.GetService<AliasManager>()!.UpdateAlias(Id, commandAlias);
_aliasManager.UpdateAlias(Id, commandAlias);
UpdateTags();
}
private void FetchAliasFromAliasManager()
{
var am = _serviceProvider.GetService<AliasManager>();
if (am is not null)
if (_aliasManager is not null)
{
var commandAlias = am.AliasFromId(Id);
var commandAlias = _aliasManager.AliasFromId(Id);
if (commandAlias is not null)
{
// Decouple from the alias manager alias object

View File

@@ -2,33 +2,6 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using ManagedCommon;
using Microsoft.CmdPal.Core.Common;
using Microsoft.CmdPal.Core.Common.Helpers;
using Microsoft.CmdPal.Core.Common.Services;
using Microsoft.CmdPal.Core.ViewModels;
using Microsoft.CmdPal.Ext.Apps;
using Microsoft.CmdPal.Ext.Bookmarks;
using Microsoft.CmdPal.Ext.Calc;
using Microsoft.CmdPal.Ext.ClipboardHistory;
using Microsoft.CmdPal.Ext.Indexer;
using Microsoft.CmdPal.Ext.Registry;
using Microsoft.CmdPal.Ext.Shell;
using Microsoft.CmdPal.Ext.System;
using Microsoft.CmdPal.Ext.TimeDate;
using Microsoft.CmdPal.Ext.WebSearch;
using Microsoft.CmdPal.Ext.WindowsServices;
using Microsoft.CmdPal.Ext.WindowsSettings;
using Microsoft.CmdPal.Ext.WindowsTerminal;
using Microsoft.CmdPal.Ext.WindowWalker;
using Microsoft.CmdPal.Ext.WinGet;
using Microsoft.CmdPal.UI.Helpers;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
using Microsoft.CmdPal.UI.ViewModels.Models;
using Microsoft.CommandPalette.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml;
// To learn more about WinUI, the WinUI project structure,
@@ -40,8 +13,6 @@ namespace Microsoft.CmdPal.UI;
/// </summary>
public partial class App : Application
{
private readonly GlobalErrorHandler _globalErrorHandler = new();
/// <summary>
/// Gets the current <see cref="App"/> instance in use.
/// </summary>
@@ -49,43 +20,16 @@ public partial class App : Application
public Window? AppWindow { get; private set; }
public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
/// <summary>
/// Gets the <see cref="IServiceProvider"/> instance to resolve application services.
/// </summary>
public IServiceProvider Services { get; }
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
public App(MainWindow mainWindow)
{
#if !CMDPAL_DISABLE_GLOBAL_ERROR_HANDLER
_globalErrorHandler.Register(this);
#endif
Services = ConfigureServices();
AppWindow = mainWindow;
this.InitializeComponent();
// Ensure types used in XAML are preserved for AOT compilation
TypePreservation.PreserveTypes();
NativeEventWaiter.WaitForEventLoop(
"Local\\PowerToysCmdPal-ExitEvent-eb73f6be-3f22-4b36-aee3-62924ba40bfd", () =>
{
EtwTrace?.Dispose();
AppWindow?.Close();
Environment.Exit(0);
});
// Connect the PT logging to the core project's logging.
// This way, log statements from the core project will be captured by the PT logs
var logWrapper = new LogWrapper();
CoreLogger.InitializeLogger(logWrapper);
}
/// <summary>
@@ -94,84 +38,7 @@ public partial class App : Application
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
AppWindow = new MainWindow();
var activatedEventArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
((MainWindow)AppWindow).HandleLaunchNonUI(activatedEventArgs);
}
/// <summary>
/// Configures the services for the application
/// </summary>
private static ServiceProvider ConfigureServices()
{
// TODO: It's in the Labs feed, but we can use Sergio's AOT-friendly source generator for this: https://github.com/CommunityToolkit/Labs-Windows/discussions/463
ServiceCollection services = new();
// Root services
services.AddSingleton(TaskScheduler.FromCurrentSynchronizationContext());
// Built-in Commands. Order matters - this is the order they'll be presented by default.
var allApps = new AllAppsCommandProvider();
var files = new IndexerCommandsProvider();
files.SuppressFallbackWhen(ShellCommandsProvider.SuppressFileFallbackIf);
services.AddSingleton<ICommandProvider>(allApps);
services.AddSingleton<ICommandProvider, ShellCommandsProvider>();
services.AddSingleton<ICommandProvider, CalculatorCommandProvider>();
services.AddSingleton<ICommandProvider>(files);
services.AddSingleton<ICommandProvider, BookmarksCommandProvider>(_ => BookmarksCommandProvider.CreateWithDefaultStore());
services.AddSingleton<ICommandProvider, WindowWalkerCommandsProvider>();
services.AddSingleton<ICommandProvider, WebSearchCommandsProvider>();
services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>();
// GH #38440: Users might not have WinGet installed! Or they might have
// a ridiculously old version. Or might be running as admin.
// We shouldn't explode in the App ctor if we fail to instantiate an
// instance of PackageManager, which will happen in the static ctor
// for WinGetStatics
try
{
var winget = new WinGetExtensionCommandsProvider();
var callback = allApps.LookupApp;
winget.SetAllLookup(callback);
services.AddSingleton<ICommandProvider>(winget);
}
catch (Exception ex)
{
Logger.LogError("Couldn't load winget");
Logger.LogError(ex.ToString());
}
services.AddSingleton<ICommandProvider, WindowsTerminalCommandsProvider>();
services.AddSingleton<ICommandProvider, WindowsSettingsCommandsProvider>();
services.AddSingleton<ICommandProvider, RegistryCommandsProvider>();
services.AddSingleton<ICommandProvider, WindowsServicesCommandsProvider>();
services.AddSingleton<ICommandProvider, BuiltInsCommandProvider>();
services.AddSingleton<ICommandProvider, TimeDateCommandsProvider>();
services.AddSingleton<ICommandProvider, SystemCommandExtensionProvider>();
// Models
services.AddSingleton<TopLevelCommandManager>();
services.AddSingleton<AliasManager>();
services.AddSingleton<HotkeyManager>();
var sm = SettingsModel.LoadSettings();
services.AddSingleton(sm);
var state = AppStateModel.LoadState();
services.AddSingleton(state);
services.AddSingleton<IExtensionService, ExtensionService>();
services.AddSingleton<TrayIconService>();
services.AddSingleton<IRunHistoryService, RunHistoryService>();
services.AddSingleton<IRootPageService, PowerToysRootPageService>();
services.AddSingleton<IAppHostService, PowerToysAppHostService>();
services.AddSingleton<ITelemetryService, TelemetryForwarder>();
// ViewModels
services.AddSingleton<ShellViewModel>();
services.AddSingleton<IPageViewModelFactoryService, CommandPalettePageViewModelFactory>();
return services.BuildServiceProvider();
((MainWindow)AppWindow!).HandleLaunchNonUI(activatedEventArgs);
}
}

View File

@@ -20,7 +20,7 @@ public sealed partial class CommandBar : UserControl,
IRecipient<TryCommandKeybindingMessage>,
ICurrentPageAware
{
public CommandBarViewModel ViewModel { get; } = new();
public CommandBarViewModel ViewModel { get; set; }
public PageViewModel? CurrentPageViewModel
{
@@ -32,9 +32,10 @@ public sealed partial class CommandBar : UserControl,
public static readonly DependencyProperty CurrentPageViewModelProperty =
DependencyProperty.Register(nameof(CurrentPageViewModel), typeof(PageViewModel), typeof(CommandBar), new PropertyMetadata(null));
public CommandBar()
public CommandBar(CommandBarViewModel commandBarViewModel)
{
this.InitializeComponent();
ViewModel = commandBarViewModel;
// RegisterAll isn't AOT compatible
WeakReferenceMessenger.Default.Register<OpenContextMenuMessage>(this);

View File

@@ -21,6 +21,7 @@ public sealed partial class ContextMenu : UserControl,
IRecipient<UpdateCommandBarMessage>,
IRecipient<TryCommandKeybindingMessage>
{
// Fix for CS8618: Mark ViewModel property as required to ensure it is initialized by the constructor.
public ContextMenuViewModel ViewModel { get; } = new();
public ContextMenu()

View File

@@ -4,18 +4,18 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class BeginInvoke : EventBase, IEvent
public class BeginInvokeEvent : TelemetryEventBase
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public BeginInvoke()
public BeginInvokeEvent()
{
EventName = "CmdPal_BeginInvoke";
}

View File

@@ -1,18 +0,0 @@
// Copyright (c) Microsoft Corporation
// 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.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class CmdPalDismissedOnLostFocus : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}

View File

@@ -1,18 +0,0 @@
// Copyright (c) Microsoft Corporation
// 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.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class CmdPalProcessStarted : EventBase, IEvent
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}

View File

@@ -4,18 +4,18 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class ColdLaunch : EventBase, IEvent
public class ColdLaunchEvent : TelemetryEventBase
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public ColdLaunch()
public ColdLaunchEvent()
{
EventName = "CmdPal_ColdLaunch";
}

View File

@@ -4,15 +4,19 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class CmdPalDismissedOnEsc : EventBase, IEvent
public class DismissedOnEscEvent : TelemetryEventBase
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public DismissedOnEscEvent()
{
EventName = "CmdPal_DismissedOnEsc";
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation
// 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.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class DismissedOnLostFocusEvent : TelemetryEventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public DismissedOnLostFocusEvent()
{
EventName = "CmdPal_DismissedOnLostFocus";
}
}

View File

@@ -4,22 +4,22 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class CmdPalHotkeySummoned : EventBase, IEvent
public class HotkeySummonedEvent : TelemetryEventBase
{
public bool Global { get; set; }
public CmdPalHotkeySummoned(bool global)
public HotkeySummonedEvent(bool global)
{
Global = global;
EventName = "CmdPal_HotkeySummoned";
}
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}

View File

@@ -4,22 +4,23 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.CommandPalette.Extensions;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class CmdPalInvokeResult : EventBase, IEvent
public class InvokeResultEvent : TelemetryEventBase
{
public string ResultKind { get; set; }
public CmdPalInvokeResult(CommandResultKind resultKind)
public InvokeResultEvent(CommandResultKind resultKind)
{
EventName = "CmdPal_InvokeResult";
ResultKind = resultKind.ToString();
}
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}

View File

@@ -4,20 +4,20 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class OpenPage : EventBase, IEvent
public class OpenPageEvent : TelemetryEventBase
{
public int PageDepth { get; set; }
public string Id { get; set; }
public OpenPage(int pageDepth, string id)
public OpenPageEvent(int pageDepth, string id)
{
PageDepth = pageDepth;
Id = id;
@@ -25,5 +25,5 @@ public class OpenPage : EventBase, IEvent
EventName = "CmdPal_OpenPage";
}
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation
// 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.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class OpenUriEvent : TelemetryEventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public string Uri { get; set; }
public bool IsWeb { get; set; }
public bool Success { get; set; }
public OpenUriEvent(string uri, bool isWeb, bool success)
{
EventName = "CmdPal_OpenUri";
Uri = uri;
IsWeb = isWeb;
Success = success;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation
// 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.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class ProcessStartedEvent : TelemetryEventBase
{
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public ProcessStartedEvent()
{
EventName = "CmdPal_ProcessStarted";
}
}

View File

@@ -4,18 +4,18 @@
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using Microsoft.CmdPal.Core.Common.Services.Telemetry;
using Microsoft.PowerToys.Telemetry;
using Microsoft.PowerToys.Telemetry.Events;
namespace Microsoft.CmdPal.UI.Events;
[EventData]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)]
public class ReactivateInstance : EventBase, IEvent
public class ReactivateInstanceEvent : TelemetryEventBase
{
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public override PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
public ReactivateInstance()
public ReactivateInstanceEvent()
{
EventName = "CmdPal_ReactivateInstance";
}

Some files were not shown because too many files have changed in this diff Show More