From e2b37445f67638bdbe012b51fb2289e6533aabb0 Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Fri, 31 Jan 2025 15:30:57 +0000 Subject: [PATCH 01/18] =?UTF-8?q?Deploying=20to=20main=20from=20@=20ChrisT?= =?UTF-8?q?itusTech/winutil@c2fb98b0dc5a941f3eaa3058dd849746da7c98b0=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a7aa826..840187a8 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win These are the sponsors that help keep this project alive with monthly contributions. -User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Sandman616User avatar: Phillip WatersUser avatar: User avatar: toranaga +User avatar: TriHyderaUser avatar: User avatar: TommyUser avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Sandman616User avatar: Phillip WatersUser avatar: User avatar: auditor ## 🏅 Thanks to all Contributors Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. From bfb83ced791e6d05fd513acd24c55ee96501400f Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Sat, 1 Feb 2025 15:31:03 +0000 Subject: [PATCH 02/18] =?UTF-8?q?Deploying=20to=20main=20from=20@=20ChrisT?= =?UTF-8?q?itusTech/winutil@e2b37445f67638bdbe012b51fb2289e6533aabb0=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 840187a8..749584ba 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win These are the sponsors that help keep this project alive with monthly contributions. -User avatar: TriHyderaUser avatar: User avatar: TommyUser avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Sandman616User avatar: Phillip WatersUser avatar: User avatar: auditor +User avatar: TriHyderaUser avatar: User avatar: TommyUser avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: auditor ## 🏅 Thanks to all Contributors Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. From 048f580a56c4541a5af0ffda0f5a6693c54c8186 Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Wed, 5 Feb 2025 15:33:03 +0000 Subject: [PATCH 03/18] =?UTF-8?q?Deploying=20to=20main=20from=20@=20ChrisT?= =?UTF-8?q?itusTech/winutil@bfb83ced791e6d05fd513acd24c55ee96501400f=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 749584ba..5ea38f85 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win These are the sponsors that help keep this project alive with monthly contributions. -User avatar: TriHyderaUser avatar: User avatar: TommyUser avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: auditor +User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: auditor ## 🏅 Thanks to all Contributors Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. From dccda61ab491d5d9b899e3ba2cd36dddeb273692 Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Thu, 6 Feb 2025 15:32:52 +0000 Subject: [PATCH 04/18] =?UTF-8?q?Deploying=20to=20main=20from=20@=20ChrisT?= =?UTF-8?q?itusTech/winutil@048f580a56c4541a5af0ffda0f5a6693c54c8186=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ea38f85..bb6424bf 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win These are the sponsors that help keep this project alive with monthly contributions. -User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: auditor +User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: ## 🏅 Thanks to all Contributors Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. From a051e64a917b2ecdbe3a60bf40f706b8af0705a9 Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Thu, 20 Feb 2025 15:33:18 +0000 Subject: [PATCH 05/18] =?UTF-8?q?Deploying=20to=20main=20from=20@=20ChrisT?= =?UTF-8?q?itusTech/winutil@dccda61ab491d5d9b899e3ba2cd36dddeb273692=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb6424bf..1f6e9f4f 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win These are the sponsors that help keep this project alive with monthly contributions. -User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: +User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: ## 🏅 Thanks to all Contributors Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. From 364076c25e3b8744b2fe2da24e83b8ce93d834f0 Mon Sep 17 00:00:00 2001 From: MyDrift Date: Tue, 25 Feb 2025 18:29:18 +0100 Subject: [PATCH 06/18] [GHTemplates] Use new preview of Issue templates (#3202) * use new issue preview - convert existing issue templates to new template style - move issue validation to start - add important section at start - improve checkbox UX - improve wording a bit - add config to link discord & remove blank issues * remove description --- .github/ISSUE_TEMPLATE/bug_report.md | 30 ---------- .github/ISSUE_TEMPLATE/bug_report.yaml | 62 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 ++ .github/ISSUE_TEMPLATE/feature_request.md | 24 -------- .github/ISSUE_TEMPLATE/feature_request.yaml | 57 +++++++++++++++++++ 5 files changed, 124 insertions(+), 54 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 063c005f..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: 'bug' -assignees: '' ---- - -## Describe the bug - - -## Steps to reproduce -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See the error. - -## Expected behavior - - -## Screenshots - - -## Additional context - - -## Issue validation -- [ ] I checked for duplicate issues. -- [ ] I checked for already existing discussions. -- [ ] I checked for an already existing pull request addressing the issue. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 00000000..a17a517e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,62 @@ +name: "Bug report" +description: "Report a bug to help us identify and fix issues in the project." +labels: ["bug"] + +body: + - type: markdown + attributes: + value: | + # 🐞 **Issue Report** + Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently. + + ## ⚠️ **IMPORTANT** + - 🛠️ **Supported environments only:** We only support Windows 11. Custom ISOs that are not made using Microwin are not supported. + - 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ). + + - type: checkboxes + attributes: + label: ⚙️ Issue Checklist + options: + - label: I have read the guidelines. + - label: I checked for duplicate issues. + - label: I searched for existing discussions. + - label: I checked for an existing pull request that addresses this issue. + validations: + required: true + + - type: input + id: affected_part + attributes: + label: 📜 What part of Winutil are you having issues with? + placeholder: "e.g., Microwin, Tweaks, etc." + validations: + required: true + + - type: textarea + id: issue_description + attributes: + label: 📝 Provide a clear and concise description of the issue. + validations: + required: true + + - type: textarea + id: steps_to_reproduce + attributes: + label: 🔄 Steps to reproduce the issue. + placeholder: "e.g., Step 1: ..., Step 2: ..." + validations: + required: true + + - type: textarea + id: error_output + attributes: + label: ❌ Paste the full error output (if available). + placeholder: "Include any relevant logs or error messages." + + - type: textarea + id: additional_context + attributes: + label: 🖼️ Additional context. + placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information." + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..024473d8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: 💻 Community Discord + url: https://discord.gg/RUbZUZyByQ + about: Join our Community Discord server to chat with other users in the Winutil community. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index f9874142..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: 'enhancement' -assignees: '' ---- - -## Is your feature request related to a problem? Please describe - - -## Describe the solution you'd like - - -## Describe alternatives you've considered - - -## Additional context - - -## Issue validation -- [ ] I checked for duplicate issues. -- [ ] I checked for already existing discussions. -- [ ] I checked for an already existing pull request addressing the issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 00000000..d32fae1e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,57 @@ +name: "Feature request" +description: "Suggest a new feature or improvement for the project." +labels: ["enhancement"] + +body: + - type: markdown + attributes: + value: | + # ✨ **Feature request** + Thank you for taking the time to suggest a feature! Please provide as much detail as possible to help us understand and evaluate your request. + + ## ⚠️ **IMPORTANT** + - 🛠️ **Supported environments only:** We only support Windows 11. + - 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ). + + - type: checkboxes + attributes: + label: ⚙️ Issue Checklist + options: + - label: I have read the guidelines. + - label: I checked for duplicate issues. + - label: I searched for existing discussions. + - label: I checked for an existing pull request that addresses this request. + validations: + required: true + + - type: textarea + id: problem_statement + attributes: + label: ❓ Is your feature request related to a problem? + placeholder: "Provide a clear and concise description of the issue you're facing. Example: 'I'm always frustrated when [...]'" + validations: + required: false + + - type: textarea + id: proposed_solution + attributes: + label: 💡 Describe the solution you'd like + placeholder: "Provide a clear and concise description of what you want to happen." + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: 🔄 Describe alternatives you've considered + placeholder: "Provide details on any alternative solutions or features you've thought about." + validations: + required: false + + - type: textarea + id: additional_context + attributes: + label: 🖼️ Additional context + placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information." + validations: + required: false \ No newline at end of file From f6e5d0e0534f844374d884c9887f505fbbacada0 Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Thu, 27 Feb 2025 15:33:22 +0000 Subject: [PATCH 07/18] =?UTF-8?q?Deploying=20to=20main=20from=20@=20ChrisT?= =?UTF-8?q?itusTech/winutil@364076c25e3b8744b2fe2da24e83b8ce93d834f0=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f6e9f4f..48f848d2 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win These are the sponsors that help keep this project alive with monthly contributions. -User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: +User avatar: TriHyderaUser avatar: User avatar: User avatar: Mark AmosUser avatar: User avatar: Martin StockzellUser avatar: Jason A. DiegmuellerUser avatar: User avatar: RMSUser avatar: StefanUser avatar: PaulUser avatar: Dave JonesUser avatar: Anthony MendezUser avatar: ClaudemodsUser avatar: User avatar: MaxUser avatar: DursleyGuyUser avatar: Phillip WatersUser avatar: User avatar: User avatar: Kiera Meredith ## 🏅 Thanks to all Contributors Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻. From 329a3de9a6fc1828072e153479565db9b99d3ed4 Mon Sep 17 00:00:00 2001 From: Kurt217432975 <49043315+Kurt217432975@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:55:19 -0500 Subject: [PATCH 08/18] Fix winget command and update FxSound description (#3207) --- config/applications.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/applications.json b/config/applications.json index 800e1d73..15272027 100644 --- a/config/applications.json +++ b/config/applications.json @@ -683,9 +683,9 @@ "category": "Multimedia Tools", "choco": "fxsound", "content": "FxSound", - "description": "FxSound is a cutting-edge audio enhancement software that elevates your listening experience across all media.", + "description": "FxSound is free open-source software to boost sound quality, volume, and bass. Including an equalizer, effects, and presets for customized audio.", "link": "https://www.fxsound.com/", - "winget": "FxSoundLLC.FxSound" + "winget": "FxSound.FxSound" }, "fzf": { "category": "Utilities", From 6038556e64f81b4575485bc150032b3cfce1d7f8 Mon Sep 17 00:00:00 2001 From: matthewkasiski Date: Fri, 28 Feb 2025 08:56:45 -0800 Subject: [PATCH 09/18] Feature/disable wpbt execution (#3188) * add IDE * add tweak --- .gitignore | 1 + config/tweaks.json | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/.gitignore b/.gitignore index 08184875..e8ae34a6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # Configuration folder .vscode/ +.idea/ ### Visual Studio ### diff --git a/config/tweaks.json b/config/tweaks.json index 36f80567..045f6f69 100644 --- a/config/tweaks.json +++ b/config/tweaks.json @@ -2667,6 +2667,22 @@ ], "link": "https://christitustech.github.io/winutil/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableLMS1" }, + "WPFTweaksDisableWpbtExecution": { + "Content": "Disable Windows Platform Binary Table (WPBT)", + "Description": "If enabled then allows your computer vendor to execute a program each time it boots. It enables computer vendors to force install anti-theft software, software drivers, or a software program conveniently. This could also be a security risk.", + "category": "z__Advanced Tweaks - CAUTION", + "panel": "1", + "Order": "a027_", + "registry": [ + { + "Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager", + "Name": "DisableWpbtExecution", + "Value": "1", + "OriginalValue": "", + "Type": "DWord" + } + ] + }, "WPFTweaksRemoveOnedrive": { "Content": "Remove OneDrive", "Description": "Moves OneDrive files to Default Home Folders and Uninstalls it.", From 1ae16f6f386b3e6b94473ea8958465847352b0c6 Mon Sep 17 00:00:00 2001 From: bess <1159066+bessx@users.noreply.github.com> Date: Fri, 28 Feb 2025 08:59:42 -0800 Subject: [PATCH 10/18] Update dev docs table of contents links (#3181) --- docs/devdocs.md | 164 ++++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 82 deletions(-) diff --git a/docs/devdocs.md b/docs/devdocs.md index 2b9b0a30..28e3ad37 100644 --- a/docs/devdocs.md +++ b/docs/devdocs.md @@ -5,104 +5,104 @@ ### Essential-Tweaks -- [Change Windows Terminal default: PowerShell 5 -> PowerShell 7](../docs/dev/tweaks/Essential-Tweaks/Powershell7.md) -- [Create Restore Point](../docs/dev/tweaks/Essential-Tweaks/RestorePoint.md) -- [Debloat Edge](../docs/dev/tweaks/Essential-Tweaks/EdgeDebloat.md) -- [Delete Temporary Files](../docs/dev/tweaks/Essential-Tweaks/DeleteTempFiles.md) -- [Disable Activity History](../docs/dev/tweaks/Essential-Tweaks/AH.md) -- [Disable ConsumerFeatures](../docs/dev/tweaks/Essential-Tweaks/ConsumerFeatures.md) -- [Disable GameDVR](../docs/dev/tweaks/Essential-Tweaks/DVR.md) -- [Disable Hibernation](../docs/dev/tweaks/Essential-Tweaks/Hiber.md) -- [Disable Homegroup](../docs/dev/tweaks/Essential-Tweaks/Home.md) -- [Disable Location Tracking](../docs/dev/tweaks/Essential-Tweaks/Loc.md) -- [Disable Powershell 7 Telemetry](../docs/dev/tweaks/Essential-Tweaks/Powershell7Tele.md) -- [Disable Storage Sense](../docs/dev/tweaks/Essential-Tweaks/Storage.md) -- [Disable Telemetry](../docs/dev/tweaks/Essential-Tweaks/Tele.md) -- [Disable Wifi-Sense](../docs/dev/tweaks/Essential-Tweaks/Wifi.md) -- [Enable End Task With Right Click](../docs/dev/tweaks/Essential-Tweaks/EndTaskOnTaskbar.md) -- [Prefer IPv4 over IPv6](../docs/dev/tweaks/Essential-Tweaks/IPv46.md) -- [Run Disk Cleanup](../docs/dev/tweaks/Essential-Tweaks/DiskCleanup.md) -- [Set Hibernation as default (good for laptops)](../docs/dev/tweaks/Essential-Tweaks/LaptopHibernation.md) -- [Set Services to Manual](../docs/dev/tweaks/Essential-Tweaks/Services.md) +- [Change Windows Terminal default: PowerShell 5 -> PowerShell 7](../dev/tweaks/Essential-Tweaks/Powershell7/) +- [Create Restore Point](../dev/tweaks/Essential-Tweaks/RestorePoint/) +- [Debloat Edge](../dev/tweaks/Essential-Tweaks/EdgeDebloat/) +- [Delete Temporary Files](../dev/tweaks/Essential-Tweaks/DeleteTempFiles/) +- [Disable Activity History](../dev/tweaks/Essential-Tweaks/AH/) +- [Disable ConsumerFeatures](../dev/tweaks/Essential-Tweaks/ConsumerFeatures/) +- [Disable GameDVR](../dev/tweaks/Essential-Tweaks/DVR/) +- [Disable Hibernation](../dev/tweaks/Essential-Tweaks/Hiber/) +- [Disable Homegroup](../dev/tweaks/Essential-Tweaks/Home/) +- [Disable Location Tracking](../dev/tweaks/Essential-Tweaks/Loc/) +- [Disable Powershell 7 Telemetry](../dev/tweaks/Essential-Tweaks/Powershell7Tele/) +- [Disable Storage Sense](../dev/tweaks/Essential-Tweaks/Storage/) +- [Disable Telemetry](../dev/tweaks/Essential-Tweaks/Tele/) +- [Disable Wifi-Sense](../dev/tweaks/Essential-Tweaks/Wifi/) +- [Enable End Task With Right Click](../dev/tweaks/Essential-Tweaks/EndTaskOnTaskbar/) +- [Prefer IPv4 over IPv6](../dev/tweaks/Essential-Tweaks/IPv46/) +- [Run Disk Cleanup](../dev/tweaks/Essential-Tweaks/DiskCleanup/) +- [Set Hibernation as default (good for laptops)](../dev/tweaks/Essential-Tweaks/LaptopHibernation/) +- [Set Services to Manual](../dev/tweaks/Essential-Tweaks/Services/) ### Shortcuts -- [Create WinUtil Shortcut](../docs/dev/tweaks/Shortcuts/Shortcut.md) +- [Create WinUtil Shortcut](../dev/tweaks/Shortcuts/Shortcut/) ### z--Advanced-Tweaks---CAUTION -- [Adobe Debloat](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DebloatAdobe.md) -- [Adobe Network Block](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/BlockAdobeNet.md) -- [Disable Background Apps](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableBGapps.md) -- [Disable Fullscreen Optimizations](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableFSO.md) -- [Disable Intel MM (vPro LMS)](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableLMS1.md) -- [Disable IPv6](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/Disableipsix.md) -- [Disable Microsoft Copilot](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveCopilot.md) -- [Disable Notification Tray/Calendar](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableNotifications.md) -- [Disable Teredo](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/Teredo.md) -- [DNS](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/changedns.md) -- [Remove ALL MS Store Apps - NOT RECOMMENDED](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DeBloat.md) -- [Remove Home and Gallery from explorer](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveHomeGallery.md) -- [Remove Microsoft Edge](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveEdge.md) -- [Remove OneDrive](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveOnedrive.md) -- [Run OO Shutup 10](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/OOSUbutton.md) -- [Set Classic Right-Click Menu ](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RightClickMenu.md) -- [Set Display for Performance](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/Display.md) -- [Set Time to UTC (Dual Boot)](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/UTC.md) +- [Adobe Debloat](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DebloatAdobe/) +- [Adobe Network Block](../dev/tweaks/z--Advanced-Tweaks---CAUTION/BlockAdobeNet/) +- [Disable Background Apps](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableBGapps/) +- [Disable Fullscreen Optimizations](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableFSO/) +- [Disable Intel MM (vPro LMS)](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableLMS1/) +- [Disable IPv6](../dev/tweaks/z--Advanced-Tweaks---CAUTION/Disableipsix/) +- [Disable Microsoft Copilot](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveCopilot/) +- [Disable Notification Tray/Calendar](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableNotifications/) +- [Disable Teredo](../dev/tweaks/z--Advanced-Tweaks---CAUTION/Teredo/) +- [DNS](../dev/tweaks/z--Advanced-Tweaks---CAUTION/changedns/) +- [Remove ALL MS Store Apps - NOT RECOMMENDED](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DeBloat/) +- [Remove Home and Gallery from explorer](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveHomeGallery/) +- [Remove Microsoft Edge](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveEdge/) +- [Remove OneDrive](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveOnedrive/) +- [Run OO Shutup 10](../dev/tweaks/z--Advanced-Tweaks---CAUTION/OOSUbutton/) +- [Set Classic Right-Click Menu ](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RightClickMenu/) +- [Set Display for Performance](../dev/tweaks/z--Advanced-Tweaks---CAUTION/Display/) +- [Set Time to UTC (Dual Boot)](../dev/tweaks/z--Advanced-Tweaks---CAUTION/UTC/) ### Customize-Preferences -- [Bing Search in Start Menu](../docs/dev/tweaks/Customize-Preferences/BingSearch.md) -- [Center Taskbar Items](../docs/dev/tweaks/Customize-Preferences/TaskbarAlignment.md) -- [Dark Theme for Windows](../docs/dev/tweaks/Customize-Preferences/DarkMode.md) -- [Detailed BSoD](../docs/dev/tweaks/Customize-Preferences/DetailedBSoD.md) -- [Mouse Acceleration](../docs/dev/tweaks/Customize-Preferences/MouseAcceleration.md) -- [NumLock on Startup](../docs/dev/tweaks/Customize-Preferences/NumLock.md) -- [Search Button in Taskbar](../docs/dev/tweaks/Customize-Preferences/TaskbarSearch.md) -- [Show File Extensions](../docs/dev/tweaks/Customize-Preferences/ShowExt.md) -- [Show Hidden Files](../docs/dev/tweaks/Customize-Preferences/HiddenFiles.md) -- [Snap Assist Flyout](../docs/dev/tweaks/Customize-Preferences/SnapFlyout.md) -- [Snap Assist Suggestion](../docs/dev/tweaks/Customize-Preferences/SnapSuggestion.md) -- [Snap Window](../docs/dev/tweaks/Customize-Preferences/SnapWindow.md) -- [Sticky Keys](../docs/dev/tweaks/Customize-Preferences/StickyKeys.md) -- [Task View Button in Taskbar](../docs/dev/tweaks/Customize-Preferences/TaskView.md) -- [Verbose Messages During Logon](../docs/dev/tweaks/Customize-Preferences/VerboseLogon.md) -- [Widgets Button in Taskbar](../docs/dev/tweaks/Customize-Preferences/TaskbarWidgets.md) +- [Bing Search in Start Menu](../dev/tweaks/Customize-Preferences/BingSearch/) +- [Center Taskbar Items](../dev/tweaks/Customize-Preferences/TaskbarAlignment/) +- [Dark Theme for Windows](../dev/tweaks/Customize-Preferences/DarkMode/) +- [Detailed BSoD](../dev/tweaks/Customize-Preferences/DetailedBSoD/) +- [Mouse Acceleration](../dev/tweaks/Customize-Preferences/MouseAcceleration/) +- [NumLock on Startup](../dev/tweaks/Customize-Preferences/NumLock/) +- [Search Button in Taskbar](../dev/tweaks/Customize-Preferences/TaskbarSearch/) +- [Show File Extensions](../dev/tweaks/Customize-Preferences/ShowExt/) +- [Show Hidden Files](../dev/tweaks/Customize-Preferences/HiddenFiles/) +- [Snap Assist Flyout](../dev/tweaks/Customize-Preferences/SnapFlyout/) +- [Snap Assist Suggestion](../dev/tweaks/Customize-Preferences/SnapSuggestion/) +- [Snap Window](../dev/tweaks/Customize-Preferences/SnapWindow/) +- [Sticky Keys](../dev/tweaks/Customize-Preferences/StickyKeys/) +- [Task View Button in Taskbar](../dev/tweaks/Customize-Preferences/TaskView/) +- [Verbose Messages During Logon](../dev/tweaks/Customize-Preferences/VerboseLogon/) +- [Widgets Button in Taskbar](../dev/tweaks/Customize-Preferences/TaskbarWidgets/) ### Performance-Plans -- [Add and Activate Ultimate Performance Profile](../docs/dev/tweaks/Performance-Plans/AddUltPerf.md) -- [Remove Ultimate Performance Profile](../docs/dev/tweaks/Performance-Plans/RemoveUltPerf.md) +- [Add and Activate Ultimate Performance Profile](../dev/tweaks/Performance-Plans/AddUltPerf/) +- [Remove Ultimate Performance Profile](../dev/tweaks/Performance-Plans/RemoveUltPerf/) ## Features ### Fixes -- [Remove Adobe Creative Cloud](../docs/dev/features/Fixes/RunAdobeCCCleanerTool.md) -- [Reset Network](../docs/dev/features/Fixes/Network.md) -- [Reset Windows Update](../docs/dev/features/Fixes/Update.md) -- [Set Up Autologin](../docs/dev/features/Fixes/Autologin.md) -- [System Corruption Scan](../docs/dev/features/Fixes/DISM.md) -- [WinGet Reinstall](../docs/dev/features/Fixes/Winget.md) +- [Remove Adobe Creative Cloud](../dev/features/Fixes/RunAdobeCCCleanerTool/) +- [Reset Network](../dev/features/Fixes/Network/) +- [Reset Windows Update](../dev/features/Fixes/Update/) +- [Set Up Autologin](../dev/features/Fixes/Autologin/) +- [System Corruption Scan](../dev/features/Fixes/DISM/) +- [WinGet Reinstall](../dev/features/Fixes/Winget/) ### Legacy-Windows-Panels -- [Control Panel](../docs/dev/features/Legacy-Windows-Panels/control.md) -- [Network Connections](../docs/dev/features/Legacy-Windows-Panels/network.md) -- [Power Panel](../docs/dev/features/Legacy-Windows-Panels/power.md) -- [Printer Settings](../docs/dev/features/Legacy-Windows-Panels/printer.md) -- [Region](../docs/dev/features/Legacy-Windows-Panels/region.md) -- [Sound Settings](../docs/dev/features/Legacy-Windows-Panels/sound.md) -- [System Properties](../docs/dev/features/Legacy-Windows-Panels/system.md) -- [User Accounts](../docs/dev/features/Legacy-Windows-Panels/user.md) +- [Control Panel](../dev/features/Legacy-Windows-Panels/control/) +- [Network Connections](../dev/features/Legacy-Windows-Panels/network/) +- [Power Panel](../dev/features/Legacy-Windows-Panels/power/) +- [Printer Settings](../dev/features/Legacy-Windows-Panels/printer/) +- [Region](../dev/features/Legacy-Windows-Panels/region/) +- [Sound Settings](../dev/features/Legacy-Windows-Panels/sound/) +- [System Properties](../dev/features/Legacy-Windows-Panels/system/) +- [User Accounts](../dev/features/Legacy-Windows-Panels/user/) ### Features -- [All .Net Framework (2,3,4)](../docs/dev/features/Features/dotnet.md) -- [Disable Legacy F8 Boot Recovery](../docs/dev/features/Features/DisableLegacyRecovery.md) -- [Disable Search Box Web Suggestions in Registry(explorer restart)](../docs/dev/features/Features/DisableSearchSuggestions.md) -- [Enable Daily Registry Backup Task 12.30am](../docs/dev/features/Features/RegBackup.md) -- [Enable Legacy F8 Boot Recovery](../docs/dev/features/Features/EnableLegacyRecovery.md) -- [Enable Search Box Web Suggestions in Registry(explorer restart)](../docs/dev/features/Features/EnableSearchSuggestions.md) -- [HyperV Virtualization](../docs/dev/features/Features/hyperv.md) -- [Install Features](../docs/dev/features/Features/Install.md) -- [Legacy Media (WMP, DirectPlay)](../docs/dev/features/Features/legacymedia.md) -- [NFS - Network File System](../docs/dev/features/Features/nfs.md) -- [Windows Sandbox](../docs/dev/features/Features/Sandbox.md) -- [Windows Subsystem for Linux](../docs/dev/features/Features/wsl.md) +- [All .Net Framework (2,3,4)](../dev/features/Features/dotnet/) +- [Disable Legacy F8 Boot Recovery](../dev/features/Features/DisableLegacyRecovery/) +- [Disable Search Box Web Suggestions in Registry(explorer restart)](../dev/features/Features/DisableSearchSuggestions/) +- [Enable Daily Registry Backup Task 12.30am](../dev/features/Features/RegBackup/) +- [Enable Legacy F8 Boot Recovery](../dev/features/Features/EnableLegacyRecovery/) +- [Enable Search Box Web Suggestions in Registry(explorer restart)](../dev/features/Features/EnableSearchSuggestions/) +- [HyperV Virtualization](../dev/features/Features/hyperv/) +- [Install Features](../dev/features/Features/Install/) +- [Legacy Media (WMP, DirectPlay)](../dev/features/Features/legacymedia/) +- [NFS - Network File System](../dev/features/Features/nfs/) +- [Windows Sandbox](../dev/features/Features/Sandbox/) +- [Windows Subsystem for Linux](../dev/features/Features/wsl/) From 8a0e0c77157c9a665e2af11a9407cc32c0a72276 Mon Sep 17 00:00:00 2001 From: MyDrift Date: Sat, 1 Mar 2025 20:50:12 +0100 Subject: [PATCH 11/18] [UI/UX] Refractor Install Tab (#2859) * initial visual implementation - remove idiotic border logic from Invoke-WPFUIElements - add "application" type & style - add "radiobutton" type & style - remove prefer choco checkbox (did not modify logic outside of xaml, so i currently get errors due to that) * add image support via choco db - add image support via choco db - backup image should be taken from unigetui db - backup backup image is some random package one rn * add compatibility for every app * performance improvements - move get logo to runspace (not working rn) - readd choco checkbox to mute errors * add border name * fix scrollviewer & reimplement logo logic into ui elements * noimage fix * add notes * cleanup & remove nav from search effects * add button action * rename buttons * add sort by options * move scrollviewer & app buttons into uielements logic * format logic for app action buttons * fix app action button logic & move get & clear to sidepanel * change category of new buttons * add virtualisation & layouting fixes - commented out prefer choco logic - add virtualisation - layouting improvements * fix radiobuttons * LETS GOOO (#12) * Add Selected Apps Label, Reshuffel the nesting of the checkbox and the label to be able to reference the name from the actual checkbox * Add visual selection and allow click on the whole app section * Fix Theme definition to work with theme change * Fix Highlight on if label or icon is clicked * change applications.json to powershell object list and refactor UI Creation logic * Optimization and Add Collapsable Categories * Add Button functionality for install, uninstall, info, install selected, uninstall selected, clear and implement search * Rest application.json to Main * Reset Compile to main * Pretty much revamp_apps but without changes to applications.json * Small fixes * Add Get-Installed Loading Indicator + small fixes * Re-Add Choco Preference * Remove Logic from Invoke-WPFUIElements that is Moved to Invoke-WPFUIApps * Remove Alphabetical List, Sort Apps inside Category Alphabetically * Small fixes to the Get-Installed function and formatting stuff * Style for Hidden Checkbox but visible Content * Hotfix for Category Expansion during search * Replace Category Label with ToggleButton, Fix Search Bugs * First Try at implementing a Compact Mode for the App page * Fix Whitespace when using Search * Keep the search status when switching between compact and full view * Fix weird buggy behaviour in regards to switching the Display Mode and using Show-SelectedOnly * Improve Togglebutton - add initial implementation of togglebutton style - add togglebuttons to appnavigation.json - refractor UI element creation for Togglebutton - commit preprocessing changes * Togglebutton fixes - move dot to the right in style - cleanup code - fix arrangement of content * Add logic to the new ToggleButtons in the sidebar of the install tab and remove old buttons * reorder buttons & fix Togglebutton toggling if action not possible - reorder getinstalled and clearselection - set togglebutton back if no app is selected * Slight modificatoin to togglebutton style & fix sidebar width * Add hover effect for the app tiles * ToggleButtonStyle animation - add hover animation to white dot - remove IsPressed trigger - improve some comments * disable show selected filter on clear selection * Add a Popup Dropdown for Selected Apps with the ability to deselect them * Split up the functions to seperate files like the rest of the repo * Fix Bug where Scrollviewer dosnt work * disable autofallback checkbox * run preprocessing * remove installation scope - remove all 3 radiobuttons from appnavigation.json * remove scrollviewer from WPFUIElements * toggle showselected on GetInstalled * remove unused autofallback --------- Co-authored-by: Martin Wiethan <47688561+Marterich@users.noreply.github.com> Co-authored-by: Chris Titus --- config/appnavigation.json | 48 ++++ config/themes.json | 6 + .../private/Add-SelectedAppsMenuItem.ps1 | 50 ++++ .../private/Find-AppsByNameOrDescription.ps1 | 35 +++ .../private/Initalize-InstallAppEntry.ps1 | 197 +++++++++++++++ .../private/Initialize-InstallAppArea.ps1 | 36 +++ .../Initialize-InstallAppsMainElement.ps1 | 28 +++ .../Initialize-InstallCategoryAppList.ps1 | 72 ++++++ .../private/Initialize-InstallHeader.ps1 | 89 +++++++ functions/private/Set-CategoryVisibility.ps1 | 44 ++++ functions/private/Show-OnlyCheckedApps.ps1 | 54 +++++ functions/public/Invoke-WPFButton.ps1 | 3 +- functions/public/Invoke-WPFGetInstalled.ps1 | 41 ++-- functions/public/Invoke-WPFInstall.ps1 | 8 +- functions/public/Invoke-WPFInstallUpgrade.ps1 | 2 +- .../public/Invoke-WPFSelectedAppsUpdate.ps1 | 43 ++++ functions/public/Invoke-WPFTab.ps1 | 1 + functions/public/Invoke-WPFUIApps.ps1 | 22 ++ functions/public/Invoke-WPFUIElements.ps1 | 229 +++++++++--------- functions/public/Invoke-WPFUnInstall.ps1 | 23 +- scripts/main.ps1 | 116 +++++---- scripts/start.ps1 | 8 + xaml/inputXML.xaml | 179 ++++++++++++-- 23 files changed, 1105 insertions(+), 229 deletions(-) create mode 100644 config/appnavigation.json create mode 100644 functions/private/Add-SelectedAppsMenuItem.ps1 create mode 100644 functions/private/Find-AppsByNameOrDescription.ps1 create mode 100644 functions/private/Initalize-InstallAppEntry.ps1 create mode 100644 functions/private/Initialize-InstallAppArea.ps1 create mode 100644 functions/private/Initialize-InstallAppsMainElement.ps1 create mode 100644 functions/private/Initialize-InstallCategoryAppList.ps1 create mode 100644 functions/private/Initialize-InstallHeader.ps1 create mode 100644 functions/private/Set-CategoryVisibility.ps1 create mode 100644 functions/private/Show-OnlyCheckedApps.ps1 create mode 100644 functions/public/Invoke-WPFSelectedAppsUpdate.ps1 create mode 100644 functions/public/Invoke-WPFUIApps.ps1 diff --git a/config/appnavigation.json b/config/appnavigation.json new file mode 100644 index 00000000..c0a408a9 --- /dev/null +++ b/config/appnavigation.json @@ -0,0 +1,48 @@ +{ + "WPFToggleView": { + "Content": ["Expanded View", "Compact View"], + "Category": "____Actions", + "Type": "ToggleButton", + "Order": "1", + "Description": "Toggle between a list and a compact grid like view" + }, + "WPFSelectedFilter": { + "Content": [ "Show All", "Show Selected"], + "Category": "____Actions", + "Type": "ToggleButton", + "Order": "2", + "Description": "Toggle between showing all or only the selected applications" + }, + "WPFClearInstallSelection": { + "Content": "Clear Selection", + "Category": "____Actions", + "Type": "Button", + "Order": "3", + "Description": "Clear the selection of applications" + }, + "WPFGetInstalled": { + "Content": "Get Installed", + "Category": "____Actions", + "Type": "Button", + "Order": "4", + "Description": "Show installed applications" + }, + "WingetRadioButton": { + "Content": "Winget", + "Category": "__Package Manager", + "Type": "RadioButton", + "GroupName": "PackageManagerGroup", + "Checked": true, + "Order": "1", + "Description": "Use Winget for package management" + }, + "ChocoRadioButton": { + "Content": "Chocolatey", + "Category": "__Package Manager", + "Type": "RadioButton", + "GroupName": "PackageManagerGroup", + "Checked": false, + "Order": "2", + "Description": "Use Chocolatey for package management" + } +} diff --git a/config/themes.json b/config/themes.json index dd2fb93a..4869120f 100644 --- a/config/themes.json +++ b/config/themes.json @@ -38,6 +38,9 @@ "ButtonCornerRadius": "2" }, "Light": { + "AppInstallUnselectedColor": "#F0F0F0", + "AppInstallHighlightedColor": "#CFCFCF", + "AppInstallSelectedColor": "#C2C2C2", "ComboBoxForegroundColor": "#232629", "ComboBoxBackgroundColor": "#F7F7F7", "LabelboxForegroundColor": "#232629", @@ -73,6 +76,9 @@ }, "Dark": { + "AppInstallUnselectedColor": "#232629", + "AppInstallHighlightedColor": "#3C3C3C", + "AppInstallSelectedColor": "#4C4C4C", "ComboBoxForegroundColor": "#F7F7F7", "ComboBoxBackgroundColor": "#1E3747", "LabelboxForegroundColor": "#0567ff", diff --git a/functions/private/Add-SelectedAppsMenuItem.ps1 b/functions/private/Add-SelectedAppsMenuItem.ps1 new file mode 100644 index 00000000..29789c20 --- /dev/null +++ b/functions/private/Add-SelectedAppsMenuItem.ps1 @@ -0,0 +1,50 @@ + function Add-SelectedAppsMenuItem { + <# + .SYNOPSIS + This is a helper function that generates and adds the Menu Items to the Selected Apps Popup. + + .Parameter name + The actual Name of an App like "Chrome" or "Brave" + This name is contained in the "Content" property inside the applications.json + .PARAMETER key + The key which identifies an app object in applications.json + For Chrome this would be "WPFInstallchrome" because "WPFInstall" is prepended automatically for each key in applications.json + #> + + param ([string]$name, [string]$key) + + $selectedAppGrid = New-Object Windows.Controls.Grid + + $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "*"})) + $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "30"})) + + # Sets the name to the Content as well as the Tooltip, because the parent Popup Border has a fixed width and text could "overflow". + # With the tooltip, you can still read the whole entry on hover + $selectedAppLabel = New-Object Windows.Controls.Label + $selectedAppLabel.Content = $name + $selectedAppLabel.ToolTip = $name + $selectedAppLabel.HorizontalAlignment = "Left" + $selectedAppLabel.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + [System.Windows.Controls.Grid]::SetColumn($selectedAppLabel, 0) + $selectedAppGrid.Children.Add($selectedAppLabel) + + $selectedAppRemoveButton = New-Object Windows.Controls.Button + $selectedAppRemoveButton.FontFamily = "Segoe MDL2 Assets" + $selectedAppRemoveButton.Content = [string]([char]0xE711) + $selectedAppRemoveButton.HorizontalAlignment = "Center" + $selectedAppRemoveButton.Tag = $key + $selectedAppRemoveButton.ToolTip = "Remove the App from Selection" + $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "HoverButtonStyle") + + # Highlight the Remove icon on Hover + $selectedAppRemoveButton.Add_MouseEnter({ $this.Foreground = "Red" }) + $selectedAppRemoveButton.Add_MouseLeave({ $this.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") }) + $selectedAppRemoveButton.Add_Click({ + $sync.($this.Tag).isChecked = $false # On click of the remove button, we only have to uncheck the corresponding checkbox. This will kick of all neccessary changes to update the UI + }) + [System.Windows.Controls.Grid]::SetColumn($selectedAppRemoveButton, 1) + $selectedAppGrid.Children.Add($selectedAppRemoveButton) + # Add new Element to Popup + $sync.selectedAppsstackPanel.Children.Add($selectedAppGrid) + } diff --git a/functions/private/Find-AppsByNameOrDescription.ps1 b/functions/private/Find-AppsByNameOrDescription.ps1 new file mode 100644 index 00000000..4271835f --- /dev/null +++ b/functions/private/Find-AppsByNameOrDescription.ps1 @@ -0,0 +1,35 @@ +function Find-AppsByNameOrDescription { + <# + .SYNOPSIS + Searches through the Apps on the Install Tab and hides all entries that do not match the string + + .PARAMETER SearchString + The string to be searched for + #> + param( + [Parameter(Mandatory=$false)] + [string]$SearchString = "" + ) + # Reset the visibility if the search string is empty or the search is cleared + if ([string]::IsNullOrWhiteSpace($SearchString)) { + Set-CategoryVisibility -Category "*" + return + } + $sync.ItemsControl.Items | ForEach-Object { + # Hide all CategoryWrapPanel and ToggleButton + $_.Visibility = [Windows.Visibility]::Collapsed + if ($_.Tag -like "CategoryWrapPanel_*") { + # Search for Apps that match the search string + $_.Children | Foreach-Object { + if ($sync.configs.applicationsHashtable.$($_.Tag).Content -like "*$SearchString*") { + # Show the App and the parent CategoryWrapPanel if the string is found + $_.Visibility = [Windows.Visibility]::Visible + $_.parent.Visibility = [Windows.Visibility]::Visible + } + else { + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } + } +} diff --git a/functions/private/Initalize-InstallAppEntry.ps1 b/functions/private/Initalize-InstallAppEntry.ps1 new file mode 100644 index 00000000..47268a18 --- /dev/null +++ b/functions/private/Initalize-InstallAppEntry.ps1 @@ -0,0 +1,197 @@ +function Initialize-InstallAppEntry { + <# + .SYNOPSIS + Creates the app entry to be placed on the isntall tab for a given app + Used to as part of the Install Tab UI generation + .PARAMETER TargetElement + The Element into which the Apps should be placed + .PARAMETER AppKey + The Key of the app inside the $sync.configs.applicationsHashtable + #> + param( + [Windows.Controls.WrapPanel]$TargetElement, + $AppKey + ) + $App = $sync.configs.applicationsHashtable.$AppKey + # Create the outer Border for the application type + $border = New-Object Windows.Controls.Border + $border.BorderBrush = [Windows.Media.Brushes]::Gray + $border.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "AppTileBorderThickness") + $border.CornerRadius = 5 + $border.SetResourceReference([Windows.Controls.Control]::PaddingProperty, "AppTileMargins") + $border.SetResourceReference([Windows.Controls.Control]::WidthProperty, "AppTileWidth") + $border.VerticalAlignment = "Top" + $border.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $border.Cursor = [System.Windows.Input.Cursors]::Hand + $border.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") + $border.Tag = $Appkey + $border.ToolTip = $App.description + $border.Add_MouseUp({ + $childCheckbox = ($this.Child.Children | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0] + $childCheckBox.isChecked = -not $childCheckbox.IsChecked + }) + $border.Add_MouseEnter({ + if (($sync.$($this.Tag).IsChecked) -eq $false) { + $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallHighlightedColor") + } + }) + $border.Add_MouseLeave({ + if (($sync.$($this.Tag).IsChecked) -eq $false) { + $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") + } + }) + # Create a DockPanel inside the Border + $dockPanel = New-Object Windows.Controls.DockPanel + $dockPanel.LastChildFill = $true + $border.Child = $dockPanel + + # Create the CheckBox, vertically centered + $checkBox = New-Object Windows.Controls.CheckBox + $checkBox.Name = $AppKey + $checkBox.Background = "Transparent" + $checkBox.HorizontalAlignment = "Left" + $checkBox.VerticalAlignment = "Center" + $checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $checkBox.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CollapsedCheckBoxStyle") + $checkbox.Add_Checked({ + Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this + $borderElement = $this.Parent.Parent + $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor") + }) + + $checkbox.Add_Unchecked({ + Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this + $borderElement = $this.Parent.Parent + $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor") + }) + $sync.$($checkBox.Name) = $checkBox + # Create a StackPanel for the image and name + $imageAndNamePanel = New-Object Windows.Controls.StackPanel + $imageAndNamePanel.Orientation = "Horizontal" + $imageAndNamePanel.VerticalAlignment = "Center" + + # Create the Image and set a placeholder + $image = New-Object Windows.Controls.Image + # $image.Name = "wpfapplogo" + $App.Name + $image.Width = 40 + $image.Height = 40 + $image.Margin = New-Object Windows.Thickness(0, 0, 10, 0) + $image.Source = $noimage # Ensure $noimage is defined in your script + + # Clip the image corners + $image.Clip = New-Object Windows.Media.RectangleGeometry + $image.Clip.Rect = New-Object Windows.Rect(0, 0, $image.Width, $image.Height) + $image.Clip.RadiusX = 5 + $image.Clip.RadiusY = 5 + $image.SetResourceReference([Windows.Controls.Control]::VisibilityProperty, "AppTileCompactVisibility") + + $imageAndNamePanel.Children.Add($image) | Out-Null + + # Create the TextBlock for the application name + $appName = New-Object Windows.Controls.TextBlock + $appName.Text = $App.Content + $appName.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "AppTileFontSize") + $appName.FontWeight = [Windows.FontWeights]::Bold + $appName.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $appName.VerticalAlignment = "Center" + $appName.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $appName.Background = "Transparent" + $imageAndNamePanel.Children.Add($appName) | Out-Null + + # Add the image and name panel to the Checkbox + $checkBox.Content = $imageAndNamePanel + + # Add the checkbox to the DockPanel + [Windows.Controls.DockPanel]::SetDock($checkBox, [Windows.Controls.Dock]::Left) + $dockPanel.Children.Add($checkBox) | Out-Null + + # Create the StackPanel for the buttons and dock it to the right + $buttonPanel = New-Object Windows.Controls.StackPanel + $buttonPanel.Orientation = "Horizontal" + $buttonPanel.HorizontalAlignment = "Right" + $buttonPanel.VerticalAlignment = "Center" + $buttonPanel.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins") + $buttonPanel.SetResourceReference([Windows.Controls.Control]::VisibilityProperty, "AppTileCompactVisibility") + [Windows.Controls.DockPanel]::SetDock($buttonPanel, [Windows.Controls.Dock]::Right) + + # Create the "Install" button + $installButton = New-Object Windows.Controls.Button + $installButton.Width = 45 + $installButton.Height = 35 + $installButton.Margin = New-Object Windows.Thickness(0, 0, 10, 0) + + $installIcon = New-Object Windows.Controls.TextBlock + $installIcon.Text = [char]0xE118 # Install Icon + $installIcon.FontFamily = "Segoe MDL2 Assets" + $installIcon.FontSize = 20 + $installIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $installIcon.Background = "Transparent" + $installIcon.HorizontalAlignment = "Center" + $installIcon.VerticalAlignment = "Center" + + $installButton.Content = $installIcon + $installButton.ToolTip = "Install or Upgrade the application" + $buttonPanel.Children.Add($installButton) | Out-Null + + # Add Click event for the "Install" button + $installButton.Add_Click({ + $appKey = $this.Parent.Parent.Parent.Tag + $appObject = $sync.configs.applicationsHashtable.$appKey + Invoke-WPFInstall -PackagesToInstall $appObject + }) + + # Create the "Uninstall" button + $uninstallButton = New-Object Windows.Controls.Button + $uninstallButton.Width = 45 + $uninstallButton.Height = 35 + + $uninstallIcon = New-Object Windows.Controls.TextBlock + $uninstallIcon.Text = [char]0xE74D # Uninstall Icon + $uninstallIcon.FontFamily = "Segoe MDL2 Assets" + $uninstallIcon.FontSize = 20 + $uninstallIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $uninstallIcon.Background = "Transparent" + $uninstallIcon.HorizontalAlignment = "Center" + $uninstallIcon.VerticalAlignment = "Center" + + $uninstallButton.Content = $uninstallIcon + $buttonPanel.Children.Add($uninstallButton) | Out-Null + + $uninstallButton.ToolTip = "Uninstall the application" + $uninstallButton.Add_Click({ + $appKey = $this.Parent.Parent.Parent.Tag + $appObject = $sync.configs.applicationsHashtable.$appKey + Invoke-WPFUnInstall -PackagesToUninstall $appObject + }) + + # Create the "Info" button + $infoButton = New-Object Windows.Controls.Button + $infoButton.Width = 45 + $infoButton.Height = 35 + $infoButton.Margin = New-Object Windows.Thickness(10, 0, 0, 0) + + $infoIcon = New-Object Windows.Controls.TextBlock + $infoIcon.Text = [char]0xE946 # Info Icon + $infoIcon.FontFamily = "Segoe MDL2 Assets" + $infoIcon.FontSize = 20 + $infoIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $infoIcon.Background = "Transparent" + $infoIcon.HorizontalAlignment = "Center" + $infoIcon.VerticalAlignment = "Center" + + $infoButton.Content = $infoIcon + $infoButton.ToolTip = "Open the application's website in your default browser" + $buttonPanel.Children.Add($infoButton) | Out-Null + + $infoButton.Add_Click({ + $appKey = $this.Parent.Parent.Parent.Tag + $appObject = $sync.configs.applicationsHashtable.$appKey + Start-Process $appObject.link + }) + + # Add the button panel to the DockPanel + $dockPanel.Children.Add($buttonPanel) | Out-Null + + # Add the border to the corresponding Category + $TargetElement.Children.Add($border) | Out-Null + } diff --git a/functions/private/Initialize-InstallAppArea.ps1 b/functions/private/Initialize-InstallAppArea.ps1 new file mode 100644 index 00000000..3e79d56d --- /dev/null +++ b/functions/private/Initialize-InstallAppArea.ps1 @@ -0,0 +1,36 @@ + function Initialize-InstallAppArea { + <# + .SYNOPSIS + Creates a [Windows.Controls.ScrollViewer] containing a [Windows.Controls.ItemsControl] which is setup to use Virtualization to only load the visible elements for performance reasons. + This is used as the parent object for all category and app entries on the install tab + Used to as part of the Install Tab UI generation + + .PARAMETER TargetElement + The element to which the AppArea shoud be added + + #> + param($TargetElement) + $scrollViewer = New-Object Windows.Controls.ScrollViewer + $scrollViewer.VerticalScrollBarVisibility = 'Auto' + $scrollViewer.HorizontalAlignment = 'Stretch' + $scrollViewer.VerticalAlignment = 'Stretch' + $scrollViewer.CanContentScroll = $true + + $itemsControl = New-Object Windows.Controls.ItemsControl + $itemsControl.HorizontalAlignment = 'Stretch' + $itemsControl.VerticalAlignment = 'Stretch' + + $itemsPanelTemplate = New-Object Windows.Controls.ItemsPanelTemplate + $factory = New-Object Windows.FrameworkElementFactory ([Windows.Controls.VirtualizingStackPanel]) + $itemsPanelTemplate.VisualTree = $factory + $itemsControl.ItemsPanel = $itemsPanelTemplate + + $itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::IsVirtualizingProperty, $true) + $itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::VirtualizationModeProperty, [Windows.Controls.VirtualizationMode]::Recycling) + + $scrollViewer.Content = $itemsControl + + [Windows.Controls.DockPanel]::SetDock($scrollViewer, [Windows.Controls.Dock]::Bottom) + $null = $TargetElement.Children.Add($scrollViewer) + return $itemsControl + } diff --git a/functions/private/Initialize-InstallAppsMainElement.ps1 b/functions/private/Initialize-InstallAppsMainElement.ps1 new file mode 100644 index 00000000..818a6343 --- /dev/null +++ b/functions/private/Initialize-InstallAppsMainElement.ps1 @@ -0,0 +1,28 @@ +function Initialize-InstallAppsMainElement { + <# + .SYNOPSIS + Clears the given WPF Grid and creates a [Windows.Controls.Border] containing a [Windows.Controls.StackPanel] + Used to as part of the Install Tab UI generation + .PARAMETER TargetGridName + The WPF Grid name + .OUTPUTS + Returns the created [Windows.Controls.StackPanel] element + #> + param( + [Parameter(Mandatory)] + [string]$TargetGridName + ) + $targetGrid = $sync.Form.FindName($TargetGridName) + $null = $targetGrid.Children.Clear() + + $Border = New-Object Windows.Controls.Border + $Border.VerticalAlignment = "Stretch" + $Border.SetResourceReference([Windows.Controls.Control]::StyleProperty, "BorderStyle") + + $dockPanel = New-Object Windows.Controls.DockPanel + $Border.Child = $dockPanel + + $null = $targetGrid.Children.Add($Border) + + return $dockPanel +} diff --git a/functions/private/Initialize-InstallCategoryAppList.ps1 b/functions/private/Initialize-InstallCategoryAppList.ps1 new file mode 100644 index 00000000..aa5151e0 --- /dev/null +++ b/functions/private/Initialize-InstallCategoryAppList.ps1 @@ -0,0 +1,72 @@ +function Initialize-InstallCategoryAppList { + <# + .SYNOPSIS + Clears the Target Element and sets up a "Loading" message. This is done, because loading of all apps can take a bit of time in some scenarios + Iterates through all Categories and Apps and adds them to the UI + Used to as part of the Install Tab UI generation + .PARAMETER TargetElement + The Element into which the Categories and Apps should be placed + .PARAMETER Apps + The Hashtable of Apps to be added to the UI + The Categories are also extracted from the Apps Hashtable + + #> + param( + $TargetElement, + $Apps + ) + function Add-Category { + param( + [string]$Category, + [Windows.Controls.ItemsControl]$TargetElement + ) + + $toggleButton = New-Object Windows.Controls.Primitives.ToggleButton + $toggleButton.Content = "$Category" + $toggleButton.Tag = "CategoryToggleButton" + $toggleButton.Cursor = [System.Windows.Input.Cursors]::Hand + $toggleButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CategoryToggleButtonStyle") + $sync.Buttons.Add($toggleButton) + $toggleButton.Add_Checked({ + # Clear the search bar when a category is clicked + $sync.SearchBar.Text = "" + Set-CategoryVisibility -Category $this.Content -overrideState Expand + }) + $toggleButton.Add_Unchecked({ + Set-CategoryVisibility -Category $this.Content -overrideState Collapse + }) + $null = $TargetElement.Items.Add($toggleButton) + } + + $loadingLabel = New-Object Windows.Controls.Label + $loadingLabel.Content = "Loading, please wait..." + $loadingLabel.HorizontalAlignment = "Center" + $loadingLabel.VerticalAlignment = "Center" + $loadingLabel.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") + $loadingLabel.FontWeight = [Windows.FontWeights]::Bold + $loadingLabel.Foreground = [Windows.Media.Brushes]::Gray + $sync.LoadingLabel = $loadingLabel + + $TargetElement.Items.Clear() + $null = $TargetElement.Items.Add($sync.LoadingLabel) + # Use the Dispatcher to make sure the Loading message is shown before the logic loading the apps starts, and only is removed when the loading is complete and the apps are added to the UI + $TargetElement.Dispatcher.Invoke([System.Windows.Threading.DispatcherPriority]::Background, [action]{ + + $TargetElement.Items.Clear() # Remove the loading message + $categories = $Apps.Values | Select-Object -ExpandProperty category -Unique | Sort-Object + foreach ($category in $categories) { + Add-Category -Category $category -TargetElement $TargetElement + $wrapPanel = New-Object Windows.Controls.WrapPanel + $wrapPanel.Orientation = "Horizontal" + $wrapPanel.HorizontalAlignment = "Stretch" + $wrapPanel.VerticalAlignment = "Center" + $wrapPanel.Margin = New-Object Windows.Thickness(0, 0, 0, 20) + $wrapPanel.Visibility = [Windows.Visibility]::Collapsed + $wrapPanel.Tag = "CategoryWrapPanel_$category" + $null = $TargetElement.Items.Add($wrapPanel) + $Apps.Keys | Where-Object { $Apps.$_.Category -eq $category } | Sort-Object | ForEach-Object { + Initialize-InstallAppEntry -TargetElement $wrapPanel -AppKey $_ + } + } + }) + } diff --git a/functions/private/Initialize-InstallHeader.ps1 b/functions/private/Initialize-InstallHeader.ps1 new file mode 100644 index 00000000..2e70533d --- /dev/null +++ b/functions/private/Initialize-InstallHeader.ps1 @@ -0,0 +1,89 @@ +function Initialize-InstallHeader { + <# + .SYNOPSIS + Creates the Multi Selection Header Elements on the Install Tab + Used to as part of the Install Tab UI generation + .PARAMETER TargetElement + The Parent Element into which the Header should be placed + #> + param($TargetElement) + function New-WPFButton { + param ( + [string]$Name, + [string]$Content + ) + $button = New-Object Windows.Controls.Button + $button.Name = $Name + $button.Content = $Content + $button.Margin = New-Object Windows.Thickness(2) + $button.HorizontalAlignment = "Stretch" + return $button + } + + $wrapPanelTop = New-Object Windows.Controls.WrapPanel + $wrapPanelTop.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") + $wrapPanelTop.HorizontalAlignment = "Left" + $wrapPanelTop.VerticalAlignment = "Top" + $wrapPanelTop.Orientation = "Horizontal" + $wrapPanelTop.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin") + $buttonConfigs = @( + @{Name="WPFInstall"; Content="Install/Upgrade Selected"}, + @{Name="WPFInstallUpgrade"; Content="Upgrade All"}, + @{Name="WPFUninstall"; Content="Uninstall Selected"} + ) + + foreach ($config in $buttonConfigs) { + $button = New-WPFButton -Name $config.Name -Content $config.Content + $null = $wrapPanelTop.Children.Add($button) + $sync[$config.Name] = $button + } + + $selectedAppsButton = New-Object Windows.Controls.Button + $selectedAppsButton.Name = "WPFselectedAppsButton" + $selectedAppsButton.Content = "Selected Apps: 0" + $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") + $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin") + $selectedAppsButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") + $selectedAppsButton.HorizontalAlignment = "Center" + $selectedAppsButton.VerticalAlignment = "Center" + + $selectedAppsPopup = New-Object Windows.Controls.Primitives.Popup + $selectedAppsPopup.IsOpen = $false + $selectedAppsPopup.PlacementTarget = $selectedAppsButton + $selectedAppsPopup.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Bottom + $selectedAppsPopup.AllowsTransparency = $true + + $selectedAppsBorder = New-Object Windows.Controls.Border + $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor") + $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderBrushProperty, "MainForegroundColor") + $selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "ButtonBorderThickness") + $selectedAppsBorder.Width = 200 + $selectedAppsBorder.Padding = 5 + $selectedAppsPopup.Child = $selectedAppsBorder + $sync.selectedAppsPopup = $selectedAppsPopup + + $sync.selectedAppsstackPanel = New-Object Windows.Controls.StackPanel + $selectedAppsBorder.Child = $sync.selectedAppsstackPanel + + # Toggle selectedAppsPopup open/close with button + $selectedAppsButton.Add_Click({ + $sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen + }) + # Close selectedAppsPopup when mouse leaves both button and selectedAppsPopup + $selectedAppsButton.Add_MouseLeave({ + if (-not $sync.selectedAppsPopup.IsMouseOver) { + $sync.selectedAppsPopup.IsOpen = $false + } + }) + $selectedAppsPopup.Add_MouseLeave({ + if (-not $selectedAppsButton.IsMouseOver) { + $sync.selectedAppsPopup.IsOpen = $false + } + }) + + $null = $wrapPanelTop.Children.Add($selectedAppsButton) + $sync.$($selectedAppsButton.Name) = $selectedAppsButton + + [Windows.Controls.DockPanel]::SetDock($wrapPanelTop, [Windows.Controls.Dock]::Top) + $null = $TargetElement.Children.Add($wrapPanelTop) +} diff --git a/functions/private/Set-CategoryVisibility.ps1 b/functions/private/Set-CategoryVisibility.ps1 new file mode 100644 index 00000000..4d2c48d0 --- /dev/null +++ b/functions/private/Set-CategoryVisibility.ps1 @@ -0,0 +1,44 @@ +function Set-CategoryVisibility { + <# + .SYNOPSIS + Used to expand or collapse categories and corresponding apps on the install tab + + .PARAMETER Category + Can eigther be a specific category name like "Browsers" OR "*" to affect all categories at once + + .PARAMETER overrideState + "Expand" => expands the corresponding elements + "Collapse" => collapses the corresponding elements + N/A => if compactView is active expand, otherwise collapse elements + #> + param( + [Parameter(Mandatory=$true)] + [string]$Category, + [ValidateSet("Expand", "Collapse")] + [string]$overrideState + ) + + switch ($overrideState) { + "Expand" {$state = $true} + "Collapse" {$state = $false} + default {$state = $sync.CompactView} + } + + # If all the Categories are affected, update the Checked state of the ToggleButtons. + # Otherwise, the state is not synced when toggling between the display modes + if ($category -eq "*") { + $items = $sync.ItemsControl.Items | Where-Object {($_.Tag -like "CategoryWrapPanel_*")} + $sync.ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryToggleButton")} | Foreach-Object { $_.Visibility = [Windows.Visibility]::Visible; $_.IsChecked = $state } + + } else { + $items = $sync.ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryWrapPanel_$Category")} + } + + $elementVisibility = if ($state -eq $true) {[Windows.Visibility]::Visible} else {[Windows.Visibility]::Collapsed} + $items | ForEach-Object { + $_.Visibility = $elementVisibility + } + $items.Children | ForEach-Object { + $_.Visibility = $elementVisibility + } +} diff --git a/functions/private/Show-OnlyCheckedApps.ps1 b/functions/private/Show-OnlyCheckedApps.ps1 new file mode 100644 index 00000000..fc581cb0 --- /dev/null +++ b/functions/private/Show-OnlyCheckedApps.ps1 @@ -0,0 +1,54 @@ +function Show-OnlyCheckedApps { + <# + .SYNOPSIS + Toggle between showing only the actively selected apps on the Install Tab and hiding everything else and displaying every app. + If no apps are selected, dont do anything + .PARAMETER appKeys + Expects a List of appKeys that are selected at the moment + If not provided, or empty, the function exits without any visual change to the ui + .EXAMPLE + Show-OnlyCheckedApps -appKeys $sync.SelectedApps + Show-OnlyCheckedApps -appKeys ("WPFInstallChrome", "WPFInstall7zip") + #> + param ( + [Parameter(Mandatory=$false)] + [String[]]$appKeys + ) + # If no apps are selected, do not allow switching to show only selected + if (($false -eq $sync.ShowOnlySelected) -and ($appKeys.Length -eq 0)) { + Write-Host "No apps selected" + $sync.wpfselectedfilter.IsChecked = $false + return + } + $sync.ShowOnlySelected = -not $sync.ShowOnlySelected + if ($sync.ShowOnlySelected) { + $sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { + $_.Content = "Show All" + } + + $sync.ItemsControl.Items | Foreach-Object { + # Search for App Container and set them to visible + if ($_.Tag -like "CategoryWrapPanel_*") { + $_.Visibility = [Windows.Visibility]::Visible + # Iterate through all the apps in the container and set them to visible if they are in the appKeys array + $_.Children | ForEach-Object { + if ($appKeys -contains $_.Tag) { + $_.Visibility = [Windows.Visibility]::Visible + } + else { + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } + else { + # Set all other items to collapsed + $_.Visibility = [Windows.Visibility]::Collapsed + } + } + } else { + $sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object { + $_.Content = "Show Selected" + } + Set-CategoryVisibility -Category "*" + } +} diff --git a/functions/public/Invoke-WPFButton.ps1 b/functions/public/Invoke-WPFButton.ps1 index 68cdfa28..0b79e553 100644 --- a/functions/public/Invoke-WPFButton.ps1 +++ b/functions/public/Invoke-WPFButton.ps1 @@ -26,7 +26,8 @@ function Invoke-WPFButton { "WPFStandard" {Invoke-WPFPresets "Standard" -checkboxfilterpattern "WPFTweak*"} "WPFMinimal" {Invoke-WPFPresets "Minimal" -checkboxfilterpattern "WPFTweak*"} "WPFClearTweaksSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFTweak*"} - "WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"} + "WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"; Show-OnlyCheckedApps; $sync.wpfselectedfilter.IsChecked = $false} + "WPFSelectedFilter" {Show-OnlyCheckedApps -appKeys $sync.SelectedApps} "WPFtweaksbutton" {Invoke-WPFtweaksbutton} "WPFOOSUbutton" {Invoke-WPFOOSU} "WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"} diff --git a/functions/public/Invoke-WPFGetInstalled.ps1 b/functions/public/Invoke-WPFGetInstalled.ps1 index c27fd13c..f33ea479 100644 --- a/functions/public/Invoke-WPFGetInstalled.ps1 +++ b/functions/public/Invoke-WPFGetInstalled.ps1 @@ -9,42 +9,49 @@ function Invoke-WPFGetInstalled { #> param($checkbox) - - if($sync.ProcessRunning) { + if ($sync.ProcessRunning) { $msg = "[Invoke-WPFGetInstalled] Install process is currently running." [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } - if(($sync.WPFpreferChocolatey.IsChecked -eq $false) -and ((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") { + if (($sync.ChocoRadioButton.IsChecked -eq $false) -and ((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") { return } - $preferChoco = $sync.WPFpreferChocolatey.IsChecked - Invoke-WPFRunspace -ArgumentList $checkbox, $preferChoco -DebugPreference $DebugPreference -ScriptBlock { - param($checkbox, $preferChoco, $DebugPreference) - + $preferChoco = $sync.ChocoRadioButton.IsChecked + $sync.ItemsControl.Dispatcher.Invoke([action] { + $sync.ItemsControl.Items | ForEach-Object { $_.Visibility = [Windows.Visibility]::Collapsed } + $null = $sync.itemsControl.Items.Add($sync.LoadingLabel) + }) + Invoke-WPFRunspace -ParameterList @(("preferChoco", $preferChoco),("checkbox", $checkbox),("ShowOnlyCheckedApps", ${function:Show-OnlyCheckedApps})) -DebugPreference $DebugPreference -ScriptBlock { + param ( + [string]$checkbox, + [boolean]$preferChoco, + [scriptblock]$ShowOnlyCheckedApps + ) $sync.ProcessRunning = $true - $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" }) + $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Indeterminate" }) - if($checkbox -eq "winget") { + if ($checkbox -eq "winget") { Write-Host "Getting Installed Programs..." + if ($preferChoco) { $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox "choco" } + else { $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox } } - if($checkbox -eq "tweaks") { + elseif ($checkbox -eq "tweaks") { Write-Host "Getting Installed Tweaks..." - } - if ($preferChoco -and $checkbox -eq "winget") { - $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox "choco" - } - else{ $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox } $sync.form.Dispatcher.invoke({ - foreach($checkbox in $Checkboxes) { + foreach ($checkbox in $Checkboxes) { $sync.$checkbox.ischecked = $True } }) - + $sync.ItemsControl.Dispatcher.Invoke([action] { + $ShowOnlyCheckedApps.Invoke($sync.SelectedApps) + $sync["WPFSelectedFilter"].IsChecked = $true + $sync.ItemsControl.Items.Remove($sync.LoadingLabel) + }) Write-Host "Done..." $sync.ProcessRunning = $false $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" }) diff --git a/functions/public/Invoke-WPFInstall.ps1 b/functions/public/Invoke-WPFInstall.ps1 index ef03af36..97069662 100644 --- a/functions/public/Invoke-WPFInstall.ps1 +++ b/functions/public/Invoke-WPFInstall.ps1 @@ -1,4 +1,8 @@ function Invoke-WPFInstall { + param ( + [Parameter(Mandatory=$false)] + [PSObject[]]$PackagesToInstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ }) + ) <# .SYNOPSIS @@ -12,14 +16,12 @@ function Invoke-WPFInstall { return } - $PackagesToInstall = (Get-WinUtilCheckBoxes)["Install"] - Write-Host $PackagesToInstall if ($PackagesToInstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to install or upgrade" [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return } - $ChocoPreference = $($sync.WPFpreferChocolatey.IsChecked) + $ChocoPreference = $($sync.ChocoRadioButton.IsChecked) $installHandle = Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ChocoPreference", $ChocoPreference)) -DebugPreference $DebugPreference -ScriptBlock { param($PackagesToInstall, $ChocoPreference, $DebugPreference) if ($PackagesToInstall.count -eq 1) { diff --git a/functions/public/Invoke-WPFInstallUpgrade.ps1 b/functions/public/Invoke-WPFInstallUpgrade.ps1 index c86ee123..c914d023 100644 --- a/functions/public/Invoke-WPFInstallUpgrade.ps1 +++ b/functions/public/Invoke-WPFInstallUpgrade.ps1 @@ -5,7 +5,7 @@ function Invoke-WPFInstallUpgrade { Invokes the function that upgrades all installed programs #> - if ($sync.WPFpreferChocolatey.IsChecked) { + if ($sync.ChocoRadioButton.IsChecked) { Install-WinUtilChoco $chocoUpgradeStatus = (Start-Process "choco" -ArgumentList "upgrade all -y" -Wait -PassThru -NoNewWindow).ExitCode if ($chocoUpgradeStatus -eq 0) { diff --git a/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 b/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 new file mode 100644 index 00000000..19e39a4a --- /dev/null +++ b/functions/public/Invoke-WPFSelectedAppsUpdate.ps1 @@ -0,0 +1,43 @@ +function Invoke-WPFSelectedAppsUpdate { + <# + .SYNOPSIS + This is a helper function that is called by the Checked and Unchecked events of the Checkboxes on the install tab. + It Updates the "Selected Apps" selectedAppLabel on the Install Tab to represent the current collection + .PARAMETER type + Eigther: Add | Remove + .PARAMETER checkbox + should contain the current instance of the checkbox that triggered the Event. + Most of the time will be the automatic variable $this + .EXAMPLE + $checkbox.Add_Unchecked({Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this}) + OR + Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $specificCheckbox + #> + param ( + $type, + $checkbox + ) + + $selectedAppsButton = $sync.WPFselectedAppsButton + # Get the actual Name from the selectedAppLabel inside the Checkbox + $appKey = $checkbox.Parent.Parent.Tag + if ($type -eq "Add") { + $sync.selectedApps.Add($appKey) + # The List type needs to be specified again, because otherwise Sort-Object will convert the list to a string if there is only a single entry + [System.Collections.Generic.List[pscustomobject]]$sync.selectedApps = $sync.SelectedApps | Sort-Object + + } + elseif ($type -eq "Remove") { + $sync.SelectedApps.Remove($appKey) + } + else{ + Write-Error "Type: $type not implemented" + } + + $count = $sync.SelectedApps.Count + $selectedAppsButton.Content = "Selected Apps: $count" + # On every change, remove all entries inside the Popup Menu. This is done, so we can keep the alphabetical order even if elements are selected in a random way + $sync.selectedAppsstackPanel.Children.Clear() + $sync.SelectedApps | Foreach-Object { Add-SelectedAppsMenuItem -name $($sync.configs.applicationsHashtable.$_.Content) -key $_ } + +} diff --git a/functions/public/Invoke-WPFTab.ps1 b/functions/public/Invoke-WPFTab.ps1 index 15d64bbd..9975574f 100644 --- a/functions/public/Invoke-WPFTab.ps1 +++ b/functions/public/Invoke-WPFTab.ps1 @@ -28,4 +28,5 @@ function Invoke-WPFTab { $sync.$tabNav.Items[$tabNumber].IsSelected = $true } } + $sync.currentTab = $sync.$tabNav.Items[$tabNumber].Header } diff --git a/functions/public/Invoke-WPFUIApps.ps1 b/functions/public/Invoke-WPFUIApps.ps1 new file mode 100644 index 00000000..e339277f --- /dev/null +++ b/functions/public/Invoke-WPFUIApps.ps1 @@ -0,0 +1,22 @@ +function Invoke-WPFUIApps { + [OutputType([void])] + param( + [Parameter(Mandatory, Position = 0)] + [PSCustomObject[]]$Apps, + [Parameter(Mandatory, Position = 1)] + [string]$TargetGridName + ) + + switch ($TargetGridName) { + "appspanel" { + $dockPanel = Initialize-InstallAppsMainElement -TargetGridName $TargetGridName + $null = Initialize-InstallHeader -TargetElement $dockPanel + $sync.ItemsControl = Initialize-InstallAppArea -TargetElement $dockPanel + Initialize-InstallCategoryAppList -TargetElement $sync.ItemsControl -Apps $Apps + } + default { + Write-Output "$TargetGridName not yet implemented" + } + } +} + diff --git a/functions/public/Invoke-WPFUIElements.ps1 b/functions/public/Invoke-WPFUIElements.ps1 index 7b55b843..f609b0d3 100644 --- a/functions/public/Invoke-WPFUIElements.ps1 +++ b/functions/public/Invoke-WPFUIElements.ps1 @@ -11,26 +11,26 @@ function Invoke-WPFUIElements { .EXAMPLE Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "install" -columncount 5 .NOTES - Future me/contributer: If possible please wrap this into a runspace to make it load all panels at the same time. + Future me/contributor: If possible, please wrap this into a runspace to make it load all panels at the same time. #> param( - [Parameter(Mandatory, position=0)] + [Parameter(Mandatory, Position = 0)] [PSCustomObject]$configVariable, - [Parameter(Mandatory, position=1)] + [Parameter(Mandatory, Position = 1)] [string]$targetGridName, - [Parameter(Mandatory, position=2)] + [Parameter(Mandatory, Position = 2)] [int]$columncount ) - $window = $sync["Form"] + $window = $sync.form - $theme = $sync.Form.Resources $borderstyle = $window.FindResource("BorderStyle") $HoverTextBlockStyle = $window.FindResource("HoverTextBlockStyle") $ColorfulToggleSwitchStyle = $window.FindResource("ColorfulToggleSwitchStyle") + $ToggleButtonStyle = $window.FindResource("ToggleButtonStyle") if (!$borderstyle -or !$HoverTextBlockStyle -or !$ColorfulToggleSwitchStyle) { throw "Failed to retrieve Styles using 'FindResource' from main window element." @@ -59,6 +59,8 @@ function Invoke-WPFUIElements { $configHashtable[$_] = $configVariable.$_ } + $radioButtonGroups = @{} + $organizedData = @{} # Iterate through JSON data and organize by panel and category foreach ($entry in $configHashtable.Keys) { @@ -66,19 +68,18 @@ function Invoke-WPFUIElements { # Create an object for the application $entryObject = [PSCustomObject]@{ - Name = $entry - Order = $entryInfo.order - Category = $entryInfo.Category - Content = $entryInfo.Content - Choco = $entryInfo.choco - Winget = $entryInfo.winget - Panel = if ($entryInfo.Panel) { $entryInfo.Panel } else { "0" } - Link = $entryInfo.link + Name = $entry + Order = $entryInfo.order + Category = $entryInfo.Category + Content = $entryInfo.Content + Panel = if ($entryInfo.Panel) { $entryInfo.Panel } else { "0" } + Link = $entryInfo.link Description = $entryInfo.description - Type = $entryInfo.type - ComboItems = $entryInfo.ComboItems - Checked = $entryInfo.Checked + Type = $entryInfo.type + ComboItems = $entryInfo.ComboItems + Checked = $entryInfo.Checked ButtonWidth = $entryInfo.ButtonWidth + GroupName = $entryInfo.GroupName # Added for RadioButton groupings } if (-not $organizedData.ContainsKey($entryObject.Panel)) { @@ -96,11 +97,13 @@ function Invoke-WPFUIElements { if ($targetGridName -eq "appspanel") { $panelcount = 0 $entrycount = $configHashtable.Keys.Count + $organizedData["0"].Keys.Count - $maxcount = [Math]::Round($entrycount / $columncount + 0.5) } } + # Initialize panel count + $panelcount = 0 + # Iterate through 'organizedData' by panel, category, and application $count = 0 foreach ($panelKey in ($organizedData.Keys | Sort-Object)) { @@ -111,78 +114,46 @@ function Invoke-WPFUIElements { $border.style = $borderstyle $targetGrid.Children.Add($border) | Out-Null - # Create a StackPanel inside the Border - $stackPanel = New-Object Windows.Controls.StackPanel - $stackPanel.Background = [Windows.Media.Brushes]::Transparent - $stackPanel.SnapsToDevicePixels = $true - $stackPanel.VerticalAlignment = "Stretch" - $border.Child = $stackPanel + # Use a DockPanel to contain the content + $dockPanelContainer = New-Object Windows.Controls.DockPanel + $border.Child = $dockPanelContainer + + # Create an ItemsControl for application content + $itemsControl = New-Object Windows.Controls.ItemsControl + $itemsControl.HorizontalAlignment = 'Stretch' + $itemsControl.VerticalAlignment = 'Stretch' + + # Set the ItemsPanel to a VirtualizingStackPanel + $itemsPanelTemplate = New-Object Windows.Controls.ItemsPanelTemplate + $factory = New-Object Windows.FrameworkElementFactory ([Windows.Controls.VirtualizingStackPanel]) + $itemsPanelTemplate.VisualTree = $factory + $itemsControl.ItemsPanel = $itemsPanelTemplate + + # Set virtualization properties + $itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::IsVirtualizingProperty, $true) + $itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::VirtualizationModeProperty, [Windows.Controls.VirtualizationMode]::Recycling) + + # Add the ItemsControl directly to the DockPanel + [Windows.Controls.DockPanel]::SetDock($itemsControl, [Windows.Controls.Dock]::Bottom) + $dockPanelContainer.Children.Add($itemsControl) | Out-Null $panelcount++ - # Add Windows Version label if this is the updates panel - if ($targetGridName -eq "updatespanel") { - $windowsVersion = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ProductName - $versionLabel = New-Object Windows.Controls.Label - $versionLabel.Content = "Windows Version: $windowsVersion" - $versionLabel.FontSize = $theme.FontSize - $versionLabel.HorizontalAlignment = "Left" - $stackPanel.Children.Add($versionLabel) | Out-Null - } - + # Now proceed with adding category labels and entries to $itemsControl foreach ($category in ($organizedData[$panelKey].Keys | Sort-Object)) { $count++ - if ($targetGridName -eq "appspanel" -and $columncount -gt 0) { - $panelcount2 = [Int](($count) / $maxcount - 0.5) - if ($panelcount -eq $panelcount2) { - # Create a new Border for the new column - $border = New-Object Windows.Controls.Border - $border.VerticalAlignment = "Stretch" - [System.Windows.Controls.Grid]::SetColumn($border, $panelcount) - $border.style = $borderstyle - $targetGrid.Children.Add($border) | Out-Null - - # Create a new StackPanel inside the Border - $stackPanel = New-Object Windows.Controls.StackPanel - $stackPanel.Background = [Windows.Media.Brushes]::Transparent - $stackPanel.SnapsToDevicePixels = $true - $stackPanel.VerticalAlignment = "Stretch" - $border.Child = $stackPanel - $panelcount++ - } - } $label = New-Object Windows.Controls.Label $label.Content = $category -replace ".*__", "" - $label.FontSize = $theme.HeadingFontSize - $label.FontFamily = $theme.HeaderFontFamily - $stackPanel.Children.Add($label) | Out-Null - + $label.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading") + $label.SetResourceReference([Windows.Controls.Control]::FontFamilyProperty, "HeaderFontFamily") + $itemsControl.Items.Add($label) | Out-Null $sync[$category] = $label - # Sort entries by Order and then by Name, but only display Name + # Sort entries by Order and then by Name $entries = $organizedData[$panelKey][$category] | Sort-Object Order, Name foreach ($entryInfo in $entries) { $count++ - if ($targetGridName -eq "appspanel" -and $columncount -gt 0) { - $panelcount2 = [Int](($count) / $maxcount - 0.5) - if ($panelcount -eq $panelcount2) { - # Create a new Border for the new column - $border = New-Object Windows.Controls.Border - $border.VerticalAlignment = "Stretch" - [System.Windows.Controls.Grid]::SetColumn($border, $panelcount) - $border.style = $borderstyle - $targetGrid.Children.Add($border) | Out-Null - - # Create a new StackPanel inside the Border - $stackPanel = New-Object Windows.Controls.StackPanel - $stackPanel.Background = [Windows.Media.Brushes]::Transparent - $stackPanel.SnapsToDevicePixels = $true - $stackPanel.VerticalAlignment = "Stretch" - $border.Child = $stackPanel - $panelcount++ - } - } - + # Create the UI elements based on the entry type switch ($entryInfo.Type) { "Toggle" { $dockPanel = New-Object Windows.Controls.DockPanel @@ -196,10 +167,10 @@ function Invoke-WPFUIElements { $label.Content = $entryInfo.Content $label.ToolTip = $entryInfo.Description $label.HorizontalAlignment = "Left" - $label.FontSize = $theme.FontSize + $label.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSize") $label.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") $dockPanel.Children.Add($label) | Out-Null - $stackPanel.Children.Add($dockPanel) | Out-Null + $itemsControl.Items.Add($dockPanel) | Out-Null $sync[$entryInfo.Name] = $checkBox @@ -217,35 +188,29 @@ function Invoke-WPFUIElements { } "ToggleButton" { - $toggleButton = New-Object Windows.Controls.ToggleButton + $toggleButton = New-Object Windows.Controls.Primitives.ToggleButton $toggleButton.Name = $entryInfo.Name - $toggleButton.Name = "WPFTab" + ($stackPanel.Children.Count + 1) + "BT" + $toggleButton.Content = $entryInfo.Content[1] + $toggleButton.ToolTip = $entryInfo.Description $toggleButton.HorizontalAlignment = "Left" - $toggleButton.Height = $theme.TabButtonHeight - $toggleButton.Width = $theme.TabButtonWidth - $toggleButton.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "ButtonInstallBackgroundColor") - $toggleButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") - $toggleButton.FontWeight = [Windows.FontWeights]::Bold + $toggleButton.Style = $ToggleButtonStyle - $textBlock = New-Object Windows.Controls.TextBlock - $textBlock.FontSize = $theme.TabButtonFontSize - $textBlock.Background = [Windows.Media.Brushes]::Transparent - $textBlock.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "ButtonInstallForegroundColor") + $toggleButton.Tag = @{ + contentOn = if ($entryInfo.Content.Count -ge 1) { $entryInfo.Content[0] } else { "" } + contentOff = if ($entryInfo.Content.Count -ge 2) { $entryInfo.Content[1] } else { $contentOn } + } - $underline = New-Object Windows.Documents.Underline - $underline.Inlines.Add($entryInfo.name -replace "(.).*", "`$1") - - $run = New-Object Windows.Documents.Run - $run.Text = $entryInfo.name -replace "^.", "" - - $textBlock.Inlines.Add($underline) - $textBlock.Inlines.Add($run) - - $toggleButton.Content = $textBlock - - $stackPanel.Children.Add($toggleButton) | Out-Null + $itemsControl.Items.Add($toggleButton) | Out-Null $sync[$entryInfo.Name] = $toggleButton + + $sync[$entryInfo.Name].Add_Checked({ + $this.Content = $this.Tag.contentOn + }) + + $sync[$entryInfo.Name].Add_Unchecked({ + $this.Content = $this.Tag.contentOff + }) } "Combobox" { @@ -257,26 +222,26 @@ function Invoke-WPFUIElements { $label.Content = $entryInfo.Content $label.HorizontalAlignment = "Left" $label.VerticalAlignment = "Center" - $label.FontSize = $theme.ButtonFontSize + $label.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize") $horizontalStackPanel.Children.Add($label) | Out-Null $comboBox = New-Object Windows.Controls.ComboBox $comboBox.Name = $entryInfo.Name - $comboBox.Height = $theme.ButtonHeight - $comboBox.Width = $theme.ButtonWidth + $comboBox.SetResourceReference([Windows.Controls.Control]::HeightProperty, "ButtonHeight") + $comboBox.SetResourceReference([Windows.Controls.Control]::WidthProperty, "ButtonWidth") $comboBox.HorizontalAlignment = "Left" $comboBox.VerticalAlignment = "Center" - $comboBox.Margin = $theme.ButtonMargin + $comboBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "ButtonMargin") foreach ($comboitem in ($entryInfo.ComboItems -split " ")) { $comboBoxItem = New-Object Windows.Controls.ComboBoxItem $comboBoxItem.Content = $comboitem - $comboBoxItem.FontSize = $theme.ButtonFontSize + $comboBoxItem.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize") $comboBox.Items.Add($comboBoxItem) | Out-Null } $horizontalStackPanel.Children.Add($comboBox) | Out-Null - $stackPanel.Children.Add($horizontalStackPanel) | Out-Null + $itemsControl.Items.Add($horizontalStackPanel) | Out-Null $comboBox.SelectedIndex = 0 @@ -288,16 +253,50 @@ function Invoke-WPFUIElements { $button.Name = $entryInfo.Name $button.Content = $entryInfo.Content $button.HorizontalAlignment = "Left" - $button.Margin = $theme.ButtonMargin - $button.FontSize = $theme.ButtonFontSize + $button.SetResourceReference([Windows.Controls.Control]::MarginProperty, "ButtonMargin") + $button.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize") if ($entryInfo.ButtonWidth) { $button.Width = $entryInfo.ButtonWidth } - $stackPanel.Children.Add($button) | Out-Null + $itemsControl.Items.Add($button) | Out-Null $sync[$entryInfo.Name] = $button } + "RadioButton" { + # Check if a container for this GroupName already exists + if (-not $radioButtonGroups.ContainsKey($entryInfo.GroupName)) { + # Create a StackPanel for this group + $groupStackPanel = New-Object Windows.Controls.StackPanel + $groupStackPanel.Orientation = "Vertical" + + # Add the group container to the ItemsControl + $itemsControl.Items.Add($groupStackPanel) | Out-Null + } + else { + # Retrieve the existing group container + $groupStackPanel = $radioButtonGroups[$entryInfo.GroupName] + } + + # Create the RadioButton + $radioButton = New-Object Windows.Controls.RadioButton + $radioButton.Name = $entryInfo.Name + $radioButton.GroupName = $entryInfo.GroupName + $radioButton.Content = $entryInfo.Content + $radioButton.HorizontalAlignment = "Left" + $radioButton.SetResourceReference([Windows.Controls.Control]::MarginProperty, "CheckBoxMargin") + $radioButton.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize") + $radioButton.ToolTip = $entryInfo.Description + + if ($entryInfo.Checked -eq $true) { + $radioButton.IsChecked = $true + } + + # Add the RadioButton to the group container + $groupStackPanel.Children.Add($radioButton) | Out-Null + $sync[$entryInfo.Name] = $radioButton + } + default { $horizontalStackPanel = New-Object Windows.Controls.StackPanel $horizontalStackPanel.Orientation = "Horizontal" @@ -305,9 +304,9 @@ function Invoke-WPFUIElements { $checkBox = New-Object Windows.Controls.CheckBox $checkBox.Name = $entryInfo.Name $checkBox.Content = $entryInfo.Content - $checkBox.FontSize = $theme.FontSize + $checkBox.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSize") $checkBox.ToolTip = $entryInfo.Description - $checkBox.Margin = $theme.CheckBoxMargin + $checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "CheckBoxMargin") if ($entryInfo.Checked -eq $true) { $checkBox.IsChecked = $entryInfo.Checked } @@ -325,7 +324,7 @@ function Invoke-WPFUIElements { $sync[$textBlock.Name] = $textBlock } - $stackPanel.Children.Add($horizontalStackPanel) | Out-Null + $itemsControl.Items.Add($horizontalStackPanel) | Out-Null $sync[$entryInfo.Name] = $checkBox } } diff --git a/functions/public/Invoke-WPFUnInstall.ps1 b/functions/public/Invoke-WPFUnInstall.ps1 index 7180ecf2..d3d4cfb4 100644 --- a/functions/public/Invoke-WPFUnInstall.ps1 +++ b/functions/public/Invoke-WPFUnInstall.ps1 @@ -1,9 +1,12 @@ function Invoke-WPFUnInstall { + param( + [Parameter(Mandatory=$false)] + [PSObject[]]$PackagesToUninstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ }) + ) <# .SYNOPSIS Uninstalls the selected programs - #> if($sync.ProcessRunning) { @@ -12,9 +15,7 @@ function Invoke-WPFUnInstall { return } - $PackagesToInstall = (Get-WinUtilCheckBoxes)["Install"] - - if ($PackagesToInstall.Count -eq 0) { + if ($PackagesToUninstall.Count -eq 0) { $WarningMsg = "Please select the program(s) to uninstall" [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning) return @@ -22,17 +23,17 @@ function Invoke-WPFUnInstall { $ButtonType = [System.Windows.MessageBoxButton]::YesNo $MessageboxTitle = "Are you sure?" - $Messageboxbody = ("This will uninstall the following applications: `n $($PackagesToInstall | Format-Table | Out-String)") + $Messageboxbody = ("This will uninstall the following applications: `n $($PackagesToUninstall | Select-Object Name, Description| Out-String)") $MessageIcon = [System.Windows.MessageBoxImage]::Information $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon) if($confirm -eq "No") {return} - $ChocoPreference = $($sync.WPFpreferChocolatey.IsChecked) + $ChocoPreference = $($sync.ChocoRadioButton.IsChecked) - Invoke-WPFRunspace -ArgumentList @(("PackagesToInstall", $PackagesToInstall),("ChocoPreference", $ChocoPreference)) -DebugPreference $DebugPreference -ScriptBlock { - param($PackagesToInstall, $ChocoPreference, $DebugPreference) - if ($PackagesToInstall.count -eq 1) { + Invoke-WPFRunspace -ArgumentList @(("PackagesToUninstall", $PackagesToUninstall),("ChocoPreference", $ChocoPreference)) -DebugPreference $DebugPreference -ScriptBlock { + param($PackagesToUninstall, $ChocoPreference, $DebugPreference) + if ($PackagesToUninstall.count -eq 1) { $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" }) } else { $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" }) @@ -41,7 +42,7 @@ function Invoke-WPFUnInstall { $packagesWinget = [System.Collections.ArrayList]::new() $packagesChoco = [System.Collections.ArrayList]::new() - foreach ($package in $PackagesToInstall) { + foreach ($package in $PackagesToUninstall) { if ($ChocoPreference) { if ($package.choco -eq "na") { $packagesWinget.add($package.winget) @@ -62,7 +63,7 @@ function Invoke-WPFUnInstall { } } return $packagesWinget, $packagesChoco - }.Invoke($PackagesToInstall) + }.Invoke($PackagesToUninstall) try { $sync.ProcessRunning = $true diff --git a/scripts/main.ps1 b/scripts/main.ps1 index 785f55e7..fe12165a 100644 --- a/scripts/main.ps1 +++ b/scripts/main.ps1 @@ -108,8 +108,27 @@ $sync.Form.Add_Loaded({ Invoke-WinutilThemeChange -init $true # Load the configuration files -#Invoke-WPFUIElements -configVariable $sync.configs.nav -targetGridName "WPFMainGrid" -Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "appspanel" -columncount 5 + +$noimage = "https://images.emojiterra.com/google/noto-emoji/unicode-15/color/512px/1f4e6.png" +$noimage = [Windows.Media.Imaging.BitmapImage]::new([Uri]::new($noimage)) + +$sync.configs.applicationsHashtable = @{} +$sync.configs.applications.PSObject.Properties | ForEach-Object { + $sync.configs.applicationsHashtable[$_.Name] = $_.Value +} + +# Now call the function with the final merged config +Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1 +# Add logic to handle click to the ToggleView Button on the Install Tab +$sync.WPFToggleView.Add_Click({ + $sync.CompactView = -not $sync.CompactView + Update-AppTileProperties + if ($sync.SearchBar.Text -eq "") { + Set-CategoryVisibility -Category "*" + } +}) +Invoke-WPFUIApps -Apps $sync.configs.applicationsHashtable -targetGridName "appspanel" + Invoke-WPFUIElements -configVariable $sync.configs.tweaks -targetGridName "tweakspanel" -columncount 2 Invoke-WPFUIElements -configVariable $sync.configs.feature -targetGridName "featurespanel" -columncount 2 # Future implementation: Add Windows Version to updates panel @@ -123,10 +142,10 @@ $xaml.SelectNodes("//*[@Name]") | ForEach-Object {$sync["$("$($psitem.Name)")"] #Persist the Chocolatey preference across winutil restarts $ChocoPreferencePath = "$env:LOCALAPPDATA\winutil\preferChocolatey.ini" -$sync.WPFpreferChocolatey.Add_Checked({New-Item -Path $ChocoPreferencePath -Force }) -$sync.WPFpreferChocolatey.Add_Unchecked({Remove-Item $ChocoPreferencePath -Force}) +$sync.ChocoRadioButton.Add_Checked({New-Item -Path $ChocoPreferencePath -Force }) +$sync.ChocoRadioButton.Add_Unchecked({Remove-Item $ChocoPreferencePath -Force}) if (Test-Path $ChocoPreferencePath) { - $sync.WPFpreferChocolatey.IsChecked = $true + $sync.ChocoRadioButton.IsChecked = $true } $sync.keys | ForEach-Object { @@ -183,6 +202,32 @@ Invoke-WPFRunspace -ScriptBlock { # Print the logo Invoke-WPFFormVariables +$sync.CompactView = $false +$sync.Form.Resources.AppTileWidth = [double]::NaN +$sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Visible +$sync.Form.Resources.AppTileFontSize = [double]16 +$sync.Form.Resources.AppTileMargins = [Windows.Thickness]5 +$sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]0 +function Update-AppTileProperties { + if ($sync.CompactView -eq $true) { + $sync.Form.Resources.AppTileWidth = [double]::NaN + $sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Collapsed + $sync.Form.Resources.AppTileFontSize = [double]12 + $sync.Form.Resources.AppTileMargins = [Windows.Thickness]2 + $sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]0 + } + else { + $sync.Form.Resources.AppTileWidth = $sync.ItemsControl.ActualWidth -20 + $sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Visible + $sync.Form.Resources.AppTileFontSize = [double]16 + $sync.Form.Resources.AppTileMargins = [Windows.Thickness]5 + $sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]1 + } +} +# We need to update the app tile properties when the form is resized because to fill a WrapPanel update the width of the elemenmt manually (afaik) +$sync.Form.Add_SizeChanged({ + Update-AppTileProperties +}) # Progress bar in taskbaritem > Set-WinUtilProgressbar $sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo @@ -414,73 +459,22 @@ if ($sync["ISOLanguage"].Items.Count -eq 1) { } $sync["ISOLanguage"].SelectedIndex = 0 - -# Load Checkboxes and Labels outside of the Filter function only once on startup for performance reasons -$filter = Get-WinUtilVariables -Type CheckBox -$CheckBoxes = ($sync.GetEnumerator()).where{ $psitem.Key -in $filter } - -$filter = Get-WinUtilVariables -Type Label -$labels = @{} -($sync.GetEnumerator()).where{$PSItem.Key -in $filter} | ForEach-Object {$labels[$_.Key] = $_.Value} - -$allCategories = $checkBoxes.Name | ForEach-Object {$sync.configs.applications.$_} | Select-Object -Unique -ExpandProperty category - $sync["SearchBar"].Add_TextChanged({ if ($sync.SearchBar.Text -ne "") { $sync.SearchBarClearButton.Visibility = "Visible" } else { $sync.SearchBarClearButton.Visibility = "Collapsed" } - - $activeApplications = @() - - $textToSearch = $sync.SearchBar.Text.ToLower() - - foreach ($CheckBox in $CheckBoxes) { - # Skip if the checkbox is null, it doesn't have content or it is the prefer Choco checkbox - if ($CheckBox -eq $null -or $CheckBox.Value -eq $null -or $CheckBox.Value.Content -eq $null -or $CheckBox.Name -eq "WPFpreferChocolatey") { - continue + switch ($sync.currentTab) { + "Install" { + Find-AppsByNameOrDescription -SearchString $sync.SearchBar.Text } - - $checkBoxName = $CheckBox.Key - $textBlockName = $checkBoxName + "Link" - - # Retrieve the corresponding text block based on the generated name - $textBlock = $sync[$textBlockName] - - if ($CheckBox.Value.Content.ToString().ToLower().Contains($textToSearch)) { - $CheckBox.Value.Visibility = "Visible" - $activeApplications += $sync.configs.applications.$checkboxName - # Set the corresponding text block visibility - if ($textBlock -ne $null -and $textBlock -is [System.Windows.Controls.TextBlock]) { - $textBlock.Visibility = "Visible" - } - } else { - $CheckBox.Value.Visibility = "Collapsed" - # Set the corresponding text block visibility - if ($textBlock -ne $null -and $textBlock -is [System.Windows.Controls.TextBlock]) { - $textBlock.Visibility = "Collapsed" - } - } - } - - $activeCategories = $activeApplications | Select-Object -ExpandProperty category -Unique - - foreach ($category in $activeCategories) { - $sync[$category].Visibility = "Visible" - } - if ($activeCategories) { - $inactiveCategories = Compare-Object -ReferenceObject $allCategories -DifferenceObject $activeCategories -PassThru - } else { - $inactiveCategories = $allCategories - } - foreach ($category in $inactiveCategories) { - $sync[$category].Visibility = "Collapsed" } }) $sync["Form"].Add_Loaded({ param($e) + $sync.Form.MinWidth = "1000" $sync["Form"].MaxWidth = [Double]::PositiveInfinity $sync["Form"].MaxHeight = [Double]::PositiveInfinity }) @@ -585,5 +579,7 @@ $sync["SponsorMenuItem"].Add_Click({ Show-CustomDialog -Title "Sponsors" -Message $authorInfo -EnableScroll $true }) + + $sync["Form"].ShowDialog() | out-null Stop-Transcript diff --git a/scripts/start.ps1 b/scripts/start.ps1 index c289709c..2e55646b 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -37,7 +37,15 @@ $sync = [Hashtable]::Synchronized(@{}) $sync.PSScriptRoot = $PSScriptRoot $sync.version = "#{replaceme}" $sync.configs = @{} +$sync.Buttons = [System.Collections.Generic.List[PSObject]]::new() $sync.ProcessRunning = $false +$sync.selectedApps = [System.Collections.Generic.List[string]]::new() +$sync.ShowOnlySeleced = $false +$sync.currentTab = "Install" +$sync.ShowOnlySelected = $false +$sync.selectedAppsStackPanel +$sync.selectedAppsPopup + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { Write-Output "Winutil needs to be run as Administrator. Attempting to relaunch." diff --git a/xaml/inputXML.xaml b/xaml/inputXML.xaml index 39610760..63a41af5 100644 --- a/xaml/inputXML.xaml +++ b/xaml/inputXML.xaml @@ -197,6 +197,45 @@ + + + + + + +