Compare commits

...

7 Commits

Author SHA1 Message Date
undergroundwires
493fb1ec16 mac: add new scripts and category for services 2023-10-19 01:21:03 +02:00
undergroundwires
b167a69976 Fix YAML error for site release in CI/CD
Fix the syntax error in the GitHub action script that was caused by
improper multi-line YAML notation. This correction ensures the action
can successfully parse and execute.
2023-10-19 00:45:23 +02:00
undergroundwires
79b46bf210 Improve performance of rendering during search
Optimize the tree view rendering during searches by enhancing the render
queue ordering. This update changes the rendering order to prioritize
visible nodes, leading to faster appearance of these nodes during
searches. The ordering logic now ignores the depth in the hierarchy and
instead focused on the node order. The collapsed check for the node
itself is removed, ensuring that visible collapsed parents are first
while their invisible children are rendered later.
2023-10-18 16:44:49 +02:00
undergroundwires
98a26f9ae4 win: improve system app uninstall /w fallback #260
This commit improves soft deletion of system apps. Before if the package
was missing, it failed to recover or delete system apps. Now, it works
even though if `Get-AppxPackage` returns null (i.e. package is
non-existing), so it can be executed even after a hard delete. This
allows safely introducing hard-delete of system apps (as discussed in
 #260) with still keeping a robust soft-delete as complement.

Before, the script was dependent on `Get-AppxPackage.InstallLocation`,
however a system app can only be located in one of these folders:

- C:\Windows\SystemApps\{PackageFamilyName}
- C:\Windows\{ShortAppName}

To ensure resilience, this commit adjust the script to rename the files
within these directories if Get-AppxPackage fails, this provides a
fallback.
2023-10-17 13:56:32 +02:00
undergroundwires
dbe3c5cfb9 win: improve system app uninstall cleanup #73
- Add documentation about folders.
- Add more user-friendly logging.
- Continue uninstallation if single folder fails (remove throw).
- Continue uninstallation if renaming single file fails.
- Add handling of `Metadata` folder as suggested in #73.
2023-10-16 18:42:29 +02:00
undergroundwires
25d7f7b2a4 Bump dependencies to latest
This commit updates various dependencies to their latest versions.

Other changes include:

- Moved the following from `devDependencies` to `dependencies`:
  - `electron-log`
  - `electron-updater`
- Remove `npm` dependency.
- Code changes:
  - Add type casting in several places to align with the latest
    `typescript` version.
  - Adopt to new return type of `setTimeout`.
- Dependencies not upgraded due to
  `@vue/eslint-config-airbnb-with-typescript` not supporting
  `@eslint-typescript` V6 (see vuejs/eslint-config-airbnb#58):
  - `vue/eslint-config-typescript`
  - `@typescript-eslint/eslint-plugin`
  - `@typescript-eslint/parser`
- Enable video recording for cypress as it's disabled by default since
  13.X.X.
2023-10-16 02:06:19 +02:00
undergroundwires-bot
b76e99ac0f ⬆️ bump everywhere to 0.12.5 2023-10-14 14:17:25 +00:00
31 changed files with 4429 additions and 5990 deletions

View File

@@ -3,6 +3,6 @@ runs:
steps:
-
name: Setup node
uses: actions/setup-node@v2
uses: actions/setup-node@v3
with:
node-version: 16.x

View File

@@ -21,7 +21,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node
@@ -49,7 +49,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node
@@ -78,7 +78,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Install Docker on macOS
if: matrix.os == 'macos' # macOS runner is missing Docker

View File

@@ -15,7 +15,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -10,7 +10,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -18,7 +18,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -14,7 +14,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node
@@ -42,7 +42,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -13,7 +13,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -25,7 +25,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
-
name: Initialize CodeQL
uses: github/codeql-action/init@v2

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ${{ matrix.os }}-latest
steps:
-
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
ref: master # otherwise it defaults to the version tag missing bump commit
fetch-depth: 0 # fetch all history

View File

@@ -10,7 +10,7 @@ jobs:
steps:
-
name: "Infrastructure: Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
path: aws
repository: undergroundwires/aws-static-site-with-cd
@@ -75,7 +75,7 @@ jobs:
working-directory: aws
-
name: "App: Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
path: app
ref: master # otherwise we don't get version bump commit
@@ -102,7 +102,7 @@ jobs:
-
name: "App: Deploy to S3"
shell: bash
run: >-
run: |-
declare web_output_dir
if ! web_output_dir=$(cd app && node scripts/print-dist-dir.js --web); then
echo 'Error: Could not determine distribution directory.'

View File

@@ -14,7 +14,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -16,7 +16,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Setup node
uses: ./.github/actions/setup-node

View File

@@ -14,7 +14,7 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Set-up node
uses: ./.github/actions/setup-node

View File

@@ -1,5 +1,26 @@
# Changelog
## 0.12.5 (2023-10-13)
* Fix Docker build and improve checks #220 | [7669985](https://github.com/undergroundwires/privacy.sexy/commit/7669985f8e1446e726a95626ecf35b3ce6b60a16)
* Add SAST security checks with SECURITY.md #178 | [3e5239f](https://github.com/undergroundwires/privacy.sexy/commit/3e5239f7d35e57749c01adf3dbbcd365aebb39c8)
* Add Scoop download instructions #174 | [cf55ca9](https://github.com/undergroundwires/privacy.sexy/commit/cf55ca9e28b064fa7a516077a9da23e3a8e3f534)
* win: fix and improve temp dir cleanup #176, #89 | [d457504](https://github.com/undergroundwires/privacy.sexy/commit/d45750428cca010daf2721b33a8ae3a01b28813b)
* win, linux: improve VSCode setting robustness #196 | [e8a52f7](https://github.com/undergroundwires/privacy.sexy/commit/e8a52f717dc799b34ceeb1c27c2b8219391dff6a)
* linux: fix obsolete Firefox DPI script #239 | [e5f6edf](https://github.com/undergroundwires/privacy.sexy/commit/e5f6edf405bcec7c29ea4d7932d1910620fa15f8)
* win: add removal of Edge assocations #64 | [888c916](https://github.com/undergroundwires/privacy.sexy/commit/888c9166fc66a2094137fa8be739cc21bafef5f6)
* win: improve Edge & OneDrive shortcut removal #73 | [8501495](https://github.com/undergroundwires/privacy.sexy/commit/8501495c170af61913288a63dbd369db5bbc5003)
* win: relocate and document SecHealthUI #190 | [2862951](https://github.com/undergroundwires/privacy.sexy/commit/286295128d0179358e0c6b7b6415d752175a1aed)
* Add developer toolkit UI component | [2147eae](https://github.com/undergroundwires/privacy.sexy/commit/2147eae687b82d05bc43bb4605d9068f148bb92a)
* win: fix and improve network data usage reset #265 | [5e359c2](https://github.com/undergroundwires/privacy.sexy/commit/5e359c2fb82a08e6acf7159b70ca86a8234b359b)
* win: improve app reversion and docs #260 | [a3f11df](https://github.com/undergroundwires/privacy.sexy/commit/a3f11dff187c821a00910c20dac05e285cda9073)
* Fix working directory in CI/CD web release | [698b570](https://github.com/undergroundwires/privacy.sexy/commit/698b570ee6e300d6703015464f4345b5e706f1cb)
* Implement new UI component for icons #230 | [48730bc](https://github.com/undergroundwires/privacy.sexy/commit/48730bca0506120bca4bf3a23545d59f2b1a9009)
* win: fix and improve AppCompat disabling #255 | [bab6316](https://github.com/undergroundwires/privacy.sexy/commit/bab6316e7625230cf4a4cf67c3aca417347db75c)
* win, linux, mac: fix typos and improve naming | [67c3677](https://github.com/undergroundwires/privacy.sexy/commit/67c3677621b201525a813e8a26f07d607176e89b)
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.12.4...0.12.5)
## 0.12.4 (2023-09-25)
* win: fix Windows spotlight revert, docs, recommend | [659fea7](https://github.com/undergroundwires/privacy.sexy/commit/659fea7afcabcd0ea273cfdcc8c4bae190c126f3)

View File

@@ -122,7 +122,7 @@
## Get started
- 🌍️ **Online**: [https://privacy.sexy](https://privacy.sexy).
- 🖥️ **Offline**: Download directly for: [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.4/privacy.sexy-Setup-0.12.4.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.4/privacy.sexy-0.12.4.dmg), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.4/privacy.sexy-0.12.4.AppImage). For more options, see [here](#additional-install-options).
- 🖥️ **Offline**: Download directly for: [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.5/privacy.sexy-Setup-0.12.5.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.5/privacy.sexy-0.12.5.dmg), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.12.5/privacy.sexy-0.12.5.AppImage). For more options, see [here](#additional-install-options).
Online version does not require to run any software on your computer. Offline version has more functions such as running the scripts directly.

View File

@@ -6,7 +6,10 @@ const CYPRESS_BASE_DIR = 'tests/e2e/';
export default defineConfig({
fixturesFolder: `${CYPRESS_BASE_DIR}/fixtures`,
screenshotsFolder: `${CYPRESS_BASE_DIR}/screenshots`,
video: true,
videosFolder: `${CYPRESS_BASE_DIR}/videos`,
e2e: {
baseUrl: `http://localhost:${ViteConfig.server.port}/`,
specPattern: `${CYPRESS_BASE_DIR}/**/*.cy.{js,jsx,ts,tsx}`, // Default: cypress/e2e/**/*.cy.{js,jsx,ts,tsx}

9284
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "privacy.sexy",
"version": "0.12.4",
"version": "0.12.5",
"private": true,
"slogan": "Now you have the choice",
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy 🍑🍆",
@@ -36,18 +36,19 @@
"dependencies": {
"@floating-ui/vue": "^1.0.2",
"@juggle/resize-observer": "^3.4.0",
"ace-builds": "^1.23.4",
"ace-builds": "^1.30.0",
"cross-fetch": "^4.0.0",
"electron-log": "^4.4.8",
"electron-progressbar": "^2.1.0",
"electron-updater": "^6.1.4",
"file-saver": "^2.0.5",
"markdown-it": "^13.0.1",
"npm": "^9.8.1",
"markdown-it": "^13.0.2",
"vue": "^2.7.14"
},
"devDependencies": {
"@modyfi/vite-plugin-yaml": "^1.0.4",
"@rushstack/eslint-patch": "^1.3.2",
"@types/ace": "^0.0.48",
"@rushstack/eslint-patch": "^1.5.1",
"@types/ace": "^0.0.49",
"@types/file-saver": "^2.0.5",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
@@ -56,47 +57,42 @@
"@vue/eslint-config-airbnb-with-typescript": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.3",
"@vue/test-utils": "^1.3.6",
"autoprefixer": "^10.4.15",
"cypress": "^12.17.2",
"electron": "^25.3.2",
"electron-builder": "^24.6.3",
"autoprefixer": "^10.4.16",
"cypress": "^13.3.1",
"electron": "^27.0.0",
"electron-builder": "^24.6.4",
"electron-devtools-installer": "^3.2.0",
"electron-icon-builder": "^2.0.1",
"electron-log": "^4.4.8",
"electron-updater": "^6.1.4",
"electron-vite": "^1.0.27",
"eslint": "^8.46.0",
"eslint-plugin-cypress": "^2.14.0",
"eslint-plugin-vue": "^9.6.0",
"eslint-plugin-vuejs-accessibility": "^1.2.0",
"icon-gen": "^3.0.1",
"eslint": "^8.51.0",
"eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-vue": "^9.17.0",
"eslint-plugin-vuejs-accessibility": "^2.2.0",
"icon-gen": "^4.0.0",
"jsdom": "^22.1.0",
"markdownlint-cli": "^0.35.0",
"postcss": "^8.4.28",
"remark-cli": "^11.0.0",
"markdownlint-cli": "^0.37.0",
"postcss": "^8.4.31",
"remark-cli": "^12.0.0",
"remark-lint-no-dead-urls": "^1.1.0",
"remark-preset-lint-consistent": "^5.1.2",
"remark-validate-links": "^12.1.1",
"sass": "^1.64.1",
"start-server-and-test": "^2.0.0",
"remark-validate-links": "^13.0.0",
"sass": "^1.69.3",
"start-server-and-test": "^2.0.1",
"svgexport": "^0.4.2",
"terser": "^5.19.2",
"tslib": "~2.4.0",
"typescript": "~4.6.2",
"vite": "^4.4.9",
"vitest": "^0.34.2",
"vue-tsc": "^1.8.8",
"terser": "^5.21.0",
"tslib": "^2.6.2",
"typescript": "^5.2.2",
"vite": "^4.4.11",
"vitest": "^0.34.6",
"vue-tsc": "^1.8.19",
"yaml-lint": "^1.7.0"
},
"//devDependencies": {
"terser": "Used by @vitejs/plugin-legacy for minification",
"typescript": [
"Cannot upgrade to 5.X.X due to unmaintained @vue/cli-plugin-typescript, https://github.com/vuejs/vue-cli/issues/7401",
"Cannot upgrade to > 4.6.X otherwise unit tests do not work, https://github.com/evanw/node-source-map-support/issues/252"
],
"tslib": "Cannot upgrade to > 2.4.X otherwise unit tests do not work, https://github.com/evanw/node-source-map-support/issues/252",
"@typescript-eslint/eslint-plugin": "Cannot upgrade to 6.X.X due to @vue/eslint-config-typescript, https://github.com/vuejs/eslint-config-typescript/pull/60",
"@typescript-eslint/parser": "Cannot upgrade to 6.X.X due to @vue/eslint-config-typescript, https://github.com/vuejs/eslint-config-typescript/pull/60"
"@rushstack/eslint-patch": "Needed by @vue/eslint-config-typescript",
"@vue/eslint-config-typescript": "Cannot upgrade to 12.X.X due to @vue/eslint-config-airbnb-with-typescript, https://github.com/vuejs/eslint-config-airbnb/issues/58",
"@typescript-eslint/eslint-plugin": "Cannot upgrade to 6.X.X due to @vue/eslint-config-airbnb-with-typescript, https://github.com/vuejs/eslint-config-airbnb/issues/58",
"@typescript-eslint/parser": "Cannot upgrade to 6.X.X due to @vue/eslint-config-airbnb-with-typescript, https://github.com/vuejs/eslint-config-airbnb/issues/58"
},
"homepage": "https://privacy.sexy",
"repository": {

View File

@@ -1238,6 +1238,376 @@ actions:
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate 'CriticalUpdateInstall' -bool true
# Trigger background check with normal scan (critical updates only)
sudo softwareupdate --background-critical
-
category: Disable OS services
children:
# Get active services : launchctl list | grep -v "\-\t0"
# Find a service : sudo grep -lR [service] /System/Library/Launch* /Library/Launch* ~/Library/LaunchAgents
# Locate a service : pgrep -fl [service]
# TODO: https://gist.github.com/ecompayment/b1054421eb90f296bbca226683c7ff7e
-
category: Disable continuously data-collecting services by default
children:
-
name: Disable diagnostics and usage data sender
recommend: standard
docs: https://apple.stackexchange.com/questions/66119/disable-submitdiaginfo
call:
function: DisableService
parameters:
name: com.apple.SubmitDiagInfo
type: LaunchDaemons
-
name: Disable diagnostics and usage data sender
recommend: standard
call:
-
function: DisableService
parameters:
name: com.apple.rtcreportingd.plist
type: LaunchDaemons
-
function: RenameSystemFile
parameters:
filePath: /usr/libexec/rtcreportingd
-
name: Disable Family Circle Daemon for Family Sharing
docs: https://support.apple.com/en-us/HT201060
recommend: standard
# Connects to setup.icloud.com HTTPS (TCP 443 )
call:
-
function: DisableService
parameters:
name: com.apple.familycircled
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/FamilyCircle.framework/Versions/A/Resources/familycircled
-
name: Disable home sharing
docs: https://discussions.apple.com/thread/7434075?answerId=29677460022#29677460022
# Connects to apps.mzstatic.com and init.itunes.apple.com HTTPS (TCP 443 )
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.itunescloudd
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /usr/libexec/rtcreportingd # TODO: SIP required?
-
name: Disable CommerceKit handling purchases for Apple products
# the Mac App Store, iTunes store, and Book Store
# Connects to init.itunes.apple.com and xp.apple.com HTTPS (TCP 443 )
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.commerce.plist
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/CommerceKit.framework/Versions/A/Resources/commerce
-
category: Disable Siri services # TODO: merge with other assistantd script
children:
-
name: Disable Siri dictation service sending voice data
recommend: strict
docs: https://apple.stackexchange.com/questions/57514/what-is-assistantd
# Connects to guzzoni.apple.com HTTPS (TCP 443 )
call:
-
function: DisableService
parameters:
name: com.apple.assistantd
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/AssistantServices.framework/Versions/A/Support/assistantd
-
name: Disable Siri assistant service
recommend: strict
docs: https://www.howtogeek.com/354897/what-are-assistant_service-and-assistantd-and-why-are-they-running-on-my-mac/
# Connects to radio.itunes.apple.com HTTPS (TCP 443 )
call:
-
function: DisableService
parameters:
name: com.apple.assistant_service.plist
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/AssistantServices.framework/Versions/A/Support/assistant_service
-
category: Disable Messages services
docs: https://blog.quarkslab.com/imessage-privacy.html
children:
-
name: Disable Apple Push Service Daemon used for Notification Center and Messages
# Connects to *-courier.push.apple.com (where * is a number) using HTTPS (TCP 443) and apple-push (TCP 5223)
call:
-
function: DisableService
parameters:
name: com.apple.apsd
type: LaunchDaemons
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/ApplePushService.framework/apsd
-
name: Disable iMessage Agent in Messages app
# Used for e.g. FaceTime invitations
docs:
- https://apple.stackexchange.com/questions/86814/firewall-settings-with-imagent
- https://blog.quarkslab.com/imessage-privacy.html
# Connects to using HTTPS (TCP 443) and apple-push (TCP 5223)
call:
-
function: DisableService
parameters:
name: com.apple.imagent
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/IMCore.framework/imagent.app/Contents/MacOS/imagent
-
name: Disable Address Book Source Sync (breaks Contacts data sync)
# Synchronizes data data for the “Contacts” app with iCloud, CardDAV, and Exchange servers
docs: https://apple.stackexchange.com/questions/219774/how-to-disable-addressbooksourcesync-in-el-capitan
# Connects to p25-contacts.icloud.com using HTTPS (TCP 443) and apple-push (TCP 5223)
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.AddressBook.SourceSync
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/Frameworks/AddressBook.framework/Versions/A/Helpers/AddressBookSourceSync.app/Contents/MacOS/AddressBookSourceSync
-
name: Disable usage tracking agent
recommend: strict
docs: https://www.unix.com/man-page/mojave/8/USAGETRACKINGAGENT/
# Connects to itunes.apple.com using HTTPS 443 (TCP)
call:
-
function: DisableService
parameters:
name: com.apple.UsageTrackingAgent
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/UsageTracking.framework/Versions/A/UsageTrackingAgent
-
name: Disable AMPLibraryAgent for Apple Music
# Connects to buy.itunes.apple.com, init.itunes.apple.com, play.itunes.apple.com, xp.apple.com using HTTPS 443 (TCP)
call:
-
function: DisableService
parameters:
name: com.apple.AMPLibraryAgent
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: System/Library/PrivateFrameworks/AMPLibrary.framework/Versions/A/Support/AMPLibraryAgent
-
category: Disable location services
children:
-
name: Disable Maps push daemon
docs:
- https://www.unix.com/man-page/mojave/8/MAPSPUSHD/
- https://discussions.apple.com/thread/7025815
call:
function: DisableService
parameters:
name: com.apple.Maps.pushdaemon
type: LaunchAgents
-
name: Disable Geo Daemon / geolocation daemon used to show maps by apps e.g. Maps
# Connects to Apple servers for loading map data on behalf of other apps and for resolving geographical coordinates to readable addresses.
# Connects to gspe*-ssl.ls.apple.com (where * is a number from 1 to 100 ), sp-ssl.ls.apple.com, configuration.ls.apple.com using HTTPS 443 (TCP)
call:
function: "RenameSystemFile (TODO: Just like Windows.yaml, requires SIP)"
parameters:
filePath: /System/Library/PrivateFrameworks/GeoServices.framework/Versions/A/XPCServices/com.apple.geod.xpc/Contents/MacOS/com.apple.geod
-
name: Disable Location-Based Suggestions for Siri, Spotlight and other places
# Used for suggestions in Spotlight, Messages, Lookup, Safari, Siri, and other place
# Connects to api-glb-euc1b.smoot.apple.com, api.smoot.apple.com using HTTPS 443 (TCP)
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.parsecd
type: LaunchAgents
-
function: "RenameSystemFile (TODO: Just like Windows.yaml, requires SIP)"
parameters:
filePath: /System/Library/PrivateFrameworks/CoreParsec.framework/parsecd
-
category: Disable iCloud services
children:
-
name: Disable iCloud notification agent
recommend: strict
call:
function: DisableService
parameters:
name: com.apple.iCloudNotificationAgent
type: LaunchAgents
-
name: Disable Sync Defaults Daemon
# Syncs user preferences or other configuration related data via iCloud
docs: https://www.unix.com/man-page/mojave/8/syncdefaultsd
# Connects to keyvalueservice.icloud.com and p*-keyvalueservice.icloud.com (where * is a number) using HTTPS 443 (TCP)
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.syncdefaultsd
type: LaunchAgents
-
function: "RenameSystemFile (TODO: Just like Windows.yaml, requires SIP)"
parameters:
filePath: /System/Library/PrivateFrameworks/SyncedDefaults.framework/Support/syncdefaultsd
-
name: Disable Reminder Daemon that synchronizes the reminder list in "Reminders" with iCloud
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.remindd
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /usr/libexec/remindd #TODO: Mb don't require SIP
-
name: Disable Cloud Daemon used for iCloud syncing
# Connects to gateway.icloud.com, metrics.icloud.com using HTTPS 443 (TCP)
recommend: strict
call:
-
function: DisableService
parameters:
name: com.apple.cloudd
type: LaunchAgents
-
function: DisableService
parameters:
name: com.apple.cloudd
type: LaunchDaemons
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/CloudKitDaemon.framework/Support/cloudd
-
name: Disable Help Daemon (breaks HelpViewer feature)
recommend: strict
docs: https://discussions.apple.com/thread/3930621
# Connects to cds.apple.com, help.apple.com using HTTPS (TCP 443)
call:
-
function: DisableService
parameters:
name: com.apple.helpd
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/HelpData.framework/Versions/A/Resources/helpd
-
name: Disable Rapport Daemon for communication between Apple devices
# Rapport Daemon is a macOS system process that enables Phone Call Handoff and other communication features between Apple devices.
# Connects to init.ess.apple.com using HTTPS (TCP 443)
docs: https://apple.stackexchange.com/questions/308294/what-is-rapportd-and-why-does-it-want-incoming-network-connections
call:
-
function: DisableService
parameters:
name: com.apple.rapportd-user
type: LaunchAgents
-
function: DisableService
parameters:
name: com.apple.rapportd
type: LaunchDaemons
-
function: RenameSystemFile
parameters:
filePath: /usr/libexec/rapportd #TODO: No SIP required?
-
name: Disable App Tracking Transparency framework
docs:
- https://apple.stackexchange.com/questions/409349/what-is-the-transparencyd-daemon-for
- https://developer.apple.com/documentation/apptrackingtransparency
# Connects to server kt-prod.apple.com using HTTPS (TCP 443 )
call:
-
function: DisableService
parameters:
name: com.apple.transparencyd
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /usr/libexec/transparencyd #TODO: No need for SIP?
-
category: Disable Calendar Agent that sync Calender App to iCloud and other servers
call:
-
function: DisableService
parameters:
name: com.apple.CalendarAgent
type: LaunchAgents
-
function: RenameSystemFile
parameters:
filePath: /System/Library/PrivateFrameworks/CalendarAgent.framework/Executables/CalendarAgent
-
name: Disable advertising services daemon
recommend: strict
docs: https://www.unix.com/man-page/mojave/8/adservicesd
call:
function: DisableService
parameters:
name: com.apple.ap.adservicesd
type: LaunchAgents
-
name: Disable NetBIOS interactions (might break Microsoft services)
# Mostly used for mostly SMB network volumes
docs: https://www.manpagez.com/man/8/netbiosd/
call:
-
function: DisableService
parameters:
name: com.apple.netbiosd
type: LaunchDaemons
function: RenameSystemFile
parameters:
filePath: /usr/sbin/netbiosd
requireSip: false # TODO: Test
functions:
-
name: PersistUserEnvironmentConfiguration
@@ -1268,3 +1638,31 @@ functions:
echo "[$profile_file] No need for any action, configuration does not exist"
fi
done
-
name: DisableService
parameters:
- name: name
- name: type
code: |-
original_file='/System/Library/{{ $type }}/{{ $name }}.plist'
backup_file="$original_file.disabled"
if [ -f "$original_file" ]; then
sudo launchctl unload -w "$original_file" 2> /dev/null
mv "$original_file" "$backup_file"
echo 'Disabled successfully'
else
echo 'Already disabled'
fi
revertCode: |-
original_file='/System/Library/{{ $type }}/{{ $name }}.plist'
backup_file="$original_file.disabled"
if [ -f "$original_file" ]; then
sudo launchctl unload -w "$original_file" 2> /dev/null
if mv "$original_file" "$backup_file"; then
echo 'Disabled successfully'
else
>&2 echo 'Failed to disable'
fi
else
echo 'Already disabled'
fi

View File

@@ -5999,9 +5999,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.SecHealthUI
packageName: Microsoft.Windows.SecHealthUI
publisherId: cw5n1h2txyewy
-
category: UI for privacy
children:
@@ -7733,7 +7733,7 @@ actions:
This category includes scripts for uninstalling default system apps in Windows.
System apps are pre-installed [1] [2] applications located in the `C:\Windows*` directory [1] [2].
These apps are typically found on `C:\Windows\SystemApps\{PackageFamilyName}` or `C:\Windows\{AppName}` folders.
These apps are typically found on `C:\Windows\SystemApps\{PackageFamilyName}` or `C:\Windows\{ShortAppName}` folders.
To view all system apps:
@@ -7758,9 +7758,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage 1527c705-839a-4832-9118-54d4Bd6a0c89
packageName: 1527c705-839a-4832-9118-54d4Bd6a0c89
publisherId: cw5n1h2txyewy
-
name: Remove "File Explorer" app
docs: |
@@ -7772,9 +7772,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage c5e2524a-ea46-4f67-841f-6a9465d9d515
packageName: c5e2524a-ea46-4f67-841f-6a9465d9d515
publisherId: cw5n1h2txyewy
-
name: Remove "App Resolver UX" app
docs: |-
@@ -7786,9 +7786,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage E2A4F912-2574-4A75-9BB0-0D023378592B
packageName: E2A4F912-2574-4A75-9BB0-0D023378592B
publisherId: cw5n1h2txyewy
-
name: Remove "Add Suggested Folders To Library" app
docs: |-
@@ -7801,16 +7801,16 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE
packageName: F46D4000-FD22-4DB4-AC8E-4E1DDDE828FE
publisherId: cw5n1h2txyewy
-
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage InputApp
packageName: InputApp
publisherId: cw5n1h2txyewy
-
name: Remove "Microsoft AAD Broker Plugin" app (breaks Night Light settings, taskbar keyboard selection and Office app authentication)
# recommend: strict (Unrecommended due to too many side-effects)
@@ -7843,9 +7843,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.AAD.BrokerPlugin
packageName: Microsoft.AAD.BrokerPlugin # Offical docs point to wrong "Microsoft.AAD.Broker.Plugin"
publisherId: cw5n1h2txyewy
-
name: Remove "Microsoft Accounts Control" app
docs: |-
@@ -7860,9 +7860,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.AccountsControl
packageName: Microsoft.AccountsControl
publisherId: cw5n1h2txyewy
-
name: Remove "Microsoft Async Text Service" app
docs: |-
@@ -7874,9 +7874,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : 8wekyb3d8bbwe
# More info : Get-AppxPackage Microsoft.AsyncTextService
packageName: Microsoft.AsyncTextService
publisherId: 8wekyb3d8bbwe
-
category: Remove Windows Hello setup UI apps
children:
@@ -7894,9 +7894,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.BioEnrollment
packageName: Microsoft.BioEnrollment
publisherId: cw5n1h2txyewy
-
name: Remove "Credentials Dialog Host" app
docs: |-
@@ -7909,9 +7909,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.CredDialogHost
packageName: Microsoft.CredDialogHost
publisherId: cw5n1h2txyewy
-
name: Remove "EC" app
docs: |-
@@ -7923,9 +7923,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : 8wekyb3d8bbwe
# More info : Get-AppxPackage Microsoft.ECApp
packageName: Microsoft.ECApp
publisherId: 8wekyb3d8bbwe
-
name: Remove "Lock" app (shows lock screen)
docs: |-
@@ -7939,9 +7939,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.LockApp
packageName: Microsoft.LockApp
publisherId: cw5n1h2txyewy
-
category: Remove Edge apps
docs: |-
@@ -7992,9 +7992,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : 8wekyb3d8bbwe
# More info : Get-AppxPackage Microsoft.MicrosoftEdge
packageName: Microsoft.MicrosoftEdge
publisherId: 8wekyb3d8bbwe
-
name: Remove "Microsoft Edge Dev Tools Client" app
recommend: strict
@@ -8018,9 +8018,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : 8wekyb3d8bbwe
# More info : Get-AppxPackage Microsoft.MicrosoftEdgeDevToolsClient
packageName: Microsoft.MicrosoftEdgeDevToolsClient
publisherId: 8wekyb3d8bbwe
-
name: Remove Edge (legacy) file and URL associations
recommend: strict
@@ -8078,9 +8078,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Win32WebViewHost
packageName: Microsoft.Win32WebViewHost
publisherId: cw5n1h2txyewy
-
name: Remove "Microsoft PPI Projection" app
docs: |-
@@ -8095,9 +8095,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.PPIProjection
packageName: Microsoft.PPIProjection
publisherId: cw5n1h2txyewy
-
name: Remove "ChxApp" app
docs: |-
@@ -8109,9 +8109,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.Apprep.ChxApp
packageName: Microsoft.Windows.Apprep.ChxApp
publisherId: cw5n1h2txyewy
-
name: Remove "Assigned Access Lock App" app
docs: |-
@@ -8123,9 +8123,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.AssignedAccessLockApp
packageName: Microsoft.Windows.AssignedAccessLockApp
publisherId: cw5n1h2txyewy
-
name: Remove "Capture Picker" app
docs: |-
@@ -8137,9 +8137,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.CapturePicker
packageName: Microsoft.Windows.CapturePicker
publisherId: cw5n1h2txyewy
-
name: Remove "Cloud Experience Host" app (breaks Windows Hello password/PIN sign-in options, and Microsoft cloud/corporate sign in)
# recommend: strict (Unrecommended due to too many side-effects)
@@ -8180,9 +8180,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.CloudExperienceHost
packageName: Microsoft.Windows.CloudExperienceHost
publisherId: cw5n1h2txyewy
-
name: Remove "Content Delivery Manager" app
recommend: strict
@@ -8206,9 +8206,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.ContentDeliveryManager
packageName: Microsoft.Windows.ContentDeliveryManager
publisherId: cw5n1h2txyewy
-
category: Remove Cortana system apps
children:
@@ -8238,9 +8238,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyew
# More info : Get-AppxPackage Microsoft.Windows.Cortana
packageName: Microsoft.Windows.Cortana # Removed since version 2004
publisherId: cw5n1h2txyewy
-
function: UninstallStoreApp
parameters:
@@ -8265,9 +8265,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyew
# More info : Get-AppxPackage Microsoft.Windows.Holographic.FirstRun
packageName: Microsoft.Windows.Holographic.FirstRun
publisherId: cw5n1h2txyewy
-
category: Remove Out-of-Box Experience (OOBE) apps
docs: |-
@@ -8296,9 +8296,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.OOBENetworkCaptivePortal
packageName: Microsoft.Windows.OOBENetworkCaptivePortal # Offical docs point to wrong "Microsoft.Windows.OOBENetworkCaptivePort"
publisherId: cw5n1h2txyewy
-
name: Remove "OOBE Network Connection Flow" app
docs: |-
@@ -8324,9 +8324,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.OOBENetworkConnectionFlow
packageName: Microsoft.Windows.OOBENetworkConnectionFlow
publisherId: cw5n1h2txyewy
-
name: Remove "Microsoft Family Safety" / "Parental control" app
recommend: standard
@@ -8358,9 +8358,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.ParentalControls
packageName: Microsoft.Windows.ParentalControls
publisherId: cw5n1h2txyewy
-
category: Remove People Hub apps
children:
@@ -8389,9 +8389,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.PeopleExperienceHost
packageName: Microsoft.Windows.PeopleExperienceHost
publisherId: cw5n1h2txyewy
-
name: Remove "Pinning Confirmation Dialog" app
docs: |-
@@ -8403,9 +8403,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.PinningConfirmationDialog
packageName: Microsoft.Windows.PinningConfirmationDialog
publisherId: cw5n1h2txyewy
-
name: Remove "Secondary Tile Experience" app
recommend: strict
@@ -8427,9 +8427,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.SecondaryTileExperience
packageName: Microsoft.Windows.SecondaryTileExperience
publisherId: cw5n1h2txyewy
-
name: Remove "Take a Test" app
recommend: strict
@@ -8457,9 +8457,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.Windows.SecureAssessmentBrowser
packageName: Microsoft.Windows.SecureAssessmentBrowser
publisherId: cw5n1h2txyewy
-
category: Remove Windows Feedback apps
children:
@@ -8474,9 +8474,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.WindowsFeedback
packageName: Microsoft.WindowsFeedback
publisherId: cw5n1h2txyewy
-
name: Remove "Xbox Game Callable UI" app (breaks Xbox Live games)
docs: |-
@@ -8497,9 +8497,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Microsoft.XboxGameCallableUI
packageName: Microsoft.XboxGameCallableUI
publisherId: cw5n1h2txyewy
-
name: Remove "CBS Preview" app
recommend: standard
@@ -8512,9 +8512,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Windows.CBSPreview
packageName: Windows.CBSPreview
publisherId: cw5n1h2txyewy
-
name: Remove "Contact Support" app
docs: |-
@@ -8525,9 +8525,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Windows.ContactSupport
packageName: Windows.ContactSupport
publisherId: cw5n1h2txyewy
-
name: Remove "Windows Print 3D" app
docs: |-
@@ -8539,9 +8539,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ❌ Missing | Windows 11 (≥ 22H2): ❌ Missing
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Windows.Print3D
packageName: Windows.Print3D
publisherId: cw5n1h2txyewy
-
name: Remove "Print UI" app
docs: |-
@@ -8553,9 +8553,9 @@ actions:
function: UninstallSystemApp
parameters:
# Existence : Windows 10 (≥ 22H2): ✅ Exists | Windows 11 (≥ 22H2): ✅ Exists
# Publisher ID : cw5n1h2txyewy
# More info : Get-AppxPackage Windows.PrintDialog
packageName: Windows.PrintDialog
publisherId: cw5n1h2txyewy
-
category: Remove OneDrive
docs: |-
@@ -9797,50 +9797,131 @@ functions:
name: UninstallSystemApp
parameters:
- name: packageName
# It simply renames files
- name: publisherId
# It simply renames files in application folders.
# Because system apps are non removable (check: (Get-AppxPackage -AllUsers 'Windows.CBSPreview').NonRemovable)
# Otherwise they throw 0x80070032 when trying to uninstall them
# This script all files in three application folders to make them inaccessible for the operating system:
# 1. Installation
# - Parent : `%WINDIR%\SystemApps\{PackageFamilyName}` or `%WINDIR%\{AppName}`
# - Example : `C:\Windows\SystemApps\Windows.CBSPreview_cw5n1h2txyewy` or `C:\Windows\PrintDialog`
# - Check :
# - `(Get-AppxPackage -AllUsers 'Windows.CBSPreview').InstallLocation` or `(Get-AppxPackage -AllUsers 'Windows.PrintDialog').InstallLocation`
# - `Get-AppxPackage -PackageTypeFilter Main | ? { $_.SignatureKind -eq "System" } | Sort Name | Format-Table Name, InstallLocation`
# 2. User-specific data
# - Parent : %LOCALAPPDATA%\Packages\
# - Example : C:\Users\undergroundwires\AppData\Local\Packages\Windows.CBSPreview_cw5n1h2txyewy
# - Check : "$env:LOCALAPPDATA\Packages\$((Get-AppxPackage -AllUsers 'Windows.CBSPreview').PackageFamilyName)"
# 3. Metadata
# - Parent : `%PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\${PackageFullName}`
# - Example : C:\ProgramData\Microsoft\Windows\AppRepository\Packages\Windows.CBSPreview_10.0.19580.1000_neutral_neutral_cw5n1h2txyewy
# - Check : "$env:PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\$((Get-AppxPackage -AllUsers 'Windows.CBSPreview').PackageFullName)"
call:
function: RunPowerShell
parameters:
code: |-
$package = Get-AppxPackage -AllUsers '{{ $packageName }}'
if (!$package) {
Write-Host 'Not installed'
exit 0
$packageName = '{{ $packageName }}'
$publisherId='{{ $publisherId }}'
Write-Host "Soft-deleting `"$packageName`" folders."
$directories = @(
@{ Name = 'User-specific data'; Path = "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)"; }
@{ Name = 'Metadata'; Path = "$env:PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\$($package.PackageFullName)"; }
)
$package = Get-AppxPackage -AllUsers $packageName
if ($package -and $package.InstallLocation) {
$directories += @{ Name = 'Installation'; Path = $package.InstallLocation; }
} else {
Write-Host "The package `"$packageName`" could not be found, residual files will still be handled."
$packageFamilyName = "$($packageName)_$($publisherId)"
$appShortName = ($packageName -Split '\.')[-1]
$directories +=@(
@{ Name = 'Installation (SystemApps)'; Path = "$env:WINDIR\SystemApps\$packageFamilyName"; }
@{ Name = 'Installation (Root)'; Path = "$env:WINDIR\$appShortName"; }
)
}
foreach($directory in $directories) {
Write-Host "Processing folder: `"$($directory.Name)`"..."
if (!$directory.Path) {
Write-Host 'Skipping, path not found.'
continue
}
if (!(Test-Path $directory.Path)) {
Write-Host "Skipping, directory `"$($directory.Path)`" does not exist."
continue
}
cmd /c ("takeown /f `"$($directory.Path)`" /r /d y 1> nul")
if ($LASTEXITCODE) {
Write-Error "Failed to obtain ownership for `"$($directory.Path)`"."
continue
}
cmd /c ("icacls `"$($directory.Path))`" /grant administrators:F /t 1> nul")
if ($LASTEXITCODE) {
Write-Error "Failed to assign permissions for `"$($directory.Path)`"."
continue
}
$files = Get-ChildItem -File -Path $directory.Path -Recurse -Force
foreach ($file in $files) {
if($file.Name.EndsWith('.OLD')) {
continue
}
$newName = "$($file.FullName).OLD"
try {
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force -ErrorAction Stop
Write-Host "Successfully renamed `"$($file.FullName)`"."
} catch {
Write-Error "Failed to rename `"$($file.FullName)`" to `"$newName`": $($_.Exception.Message)"
}
$directories = @($package.InstallLocation, "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)")
foreach($dir in $directories) {
if ( !$dir -Or !(Test-Path "$dir") ) { continue }
cmd /c ('takeown /f "' + $dir + '" /r /d y 1> nul')
if($LASTEXITCODE) { throw 'Failed to take ownership' }
cmd /c ('icacls "' + $dir + '" /grant administrators:F /t 1> nul')
if($LASTEXITCODE) { throw 'Failed to take ownership' }
$files = Get-ChildItem -File -Path $dir -Recurse -Force
foreach($file in $files) {
if($file.Name.EndsWith('.OLD')) { continue }
$newName = $file.FullName + '.OLD'
Write-Host "Rename '$($file.FullName)' to '$newName'"
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force
}
}
revertCode: |-
$package = Get-AppxPackage -AllUsers '{{ $packageName }}'
if (!$package) {
Write-Error 'App could not be found' -ErrorAction Stop
$packageName = '{{ $packageName }}'
$publisherId='{{ $publisherId }}'
Write-Host "Restoring `"$packageName`" folders."
$directories = @(
@{ Name = 'User-specific data'; Path = "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)"; }
@{ Name = 'Metadata'; Path = "$env:PROGRAMDATA\Microsoft\Windows\AppRepository\Packages\$($package.PackageFullName)"; }
)
$package = Get-AppxPackage -AllUsers $packageName
if ($package -and $package.InstallLocation) {
$directories += @{ Name = 'Installation'; Path = $package.InstallLocation; }
} else {
Write-Warning "The package `"$packageName`" could not be found, its files will still be handled."
$packageFamilyName = "$($packageName)_$($publisherId)"
$appShortName = ($packageName -Split '\.')[-1]
$directories +=@(
@{ Name = 'Installation (SystemApps)'; Path = "$env:WINDIR\SystemApps\$packageFamilyName"; }
@{ Name = 'Installation (Root)'; Path = "$env:WINDIR\$appShortName"; }
)
}
$directories = @($package.InstallLocation, "$env:LOCALAPPDATA\Packages\$($package.PackageFamilyName)")
foreach($dir in $directories) {
if ( !$dir -Or !(Test-Path "$dir") ) { continue; }
cmd /c ('takeown /f "' + $dir + '" /r /d y 1> nul')
if($LASTEXITCODE) { throw 'Failed to take ownership' }
cmd /c ('icacls "' + $dir + '" /grant administrators:F /t 1> nul')
if($LASTEXITCODE) { throw 'Failed to take ownership' }
$files = Get-ChildItem -File -Path "$dir\*.OLD" -Recurse -Force
foreach($file in $files) {
foreach ($directory in $directories) {
Write-Host "Processing folder: `"$($directory.Name)`" directory..."
if (!$directory.Path) {
Write-Host "Skipping `"$($directory.Name)`" directory, path not found."
continue
}
if (!(Test-Path $directory.Path)) {
Write-Host "Skipping, directory `"$($directory.Path)`" does not exist."
continue
}
cmd /c ("takeown /f `"$($directory.Path)`" /r /d y 1> nul")
if ($LASTEXITCODE) {
Write-Error "Failed to obtain ownership for `"$($directory.Path)`"."
continue
}
cmd /c ("icacls `"$($directory.Path)`" /grant administrators:F /t 1> nul")
if ($LASTEXITCODE) {
Write-Error "Failed to assign permissions for `"$($directory.Path)`"."
continue
}
$files = Get-ChildItem -File -Path "$($directory.Path)\*.OLD" -Recurse -Force
foreach ($file in $files) {
$newName = $file.FullName.Substring(0, $file.FullName.Length - 4)
Write-Host "Rename '$($file.FullName)' to '$newName'"
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force
try {
Move-Item -LiteralPath "$($file.FullName)" -Destination "$newName" -Force -ErrorAction Stop
Write-Host "Successfully renamed `"$($file.FullName)`" back to original."
} catch {
Write-Error "Failed to rename `"$($file.FullName)`" back to original `"$newName`": $($_.Exception.Message)"
}
}
}
-

View File

@@ -1,29 +0,0 @@
import { ReadOnlyTreeNode } from '../../Node/TreeNode';
import { RenderQueueOrderer } from './RenderQueueOrderer';
export class CollapseDepthOrderer implements RenderQueueOrderer {
public orderNodes(nodes: Iterable<ReadOnlyTreeNode>): ReadOnlyTreeNode[] {
return orderNodes(nodes);
}
}
function orderNodes(nodes: Iterable<ReadOnlyTreeNode>): ReadOnlyTreeNode[] {
return [...nodes]
.sort((a, b) => {
const [aCollapseStatus, bCollapseStatus] = [isNodeCollapsed(a), isNodeCollapsed(b)];
if (aCollapseStatus !== bCollapseStatus) {
return (aCollapseStatus ? 1 : 0) - (bCollapseStatus ? 1 : 0);
}
return a.hierarchy.depthInTree - b.hierarchy.depthInTree;
});
}
function isNodeCollapsed(node: ReadOnlyTreeNode): boolean {
if (!node.state.current.isExpanded) {
return true;
}
if (node.hierarchy.parent) {
return isNodeCollapsed(node.hierarchy.parent);
}
return false;
}

View File

@@ -0,0 +1,35 @@
import { ReadOnlyTreeNode } from '../../Node/TreeNode';
import { RenderQueueOrderer } from './RenderQueueOrderer';
export class CollapsedParentOrderer implements RenderQueueOrderer {
public orderNodes(nodes: Iterable<ReadOnlyTreeNode>): ReadOnlyTreeNode[] {
return orderNodes(nodes);
}
}
function orderNodes(nodes: Iterable<ReadOnlyTreeNode>): ReadOnlyTreeNode[] {
return [...nodes]
.map((node, index) => ({ node, index }))
.sort((a, b) => {
const [
isANodeOfCollapsedParent,
isBNodeOfCollapsedParent,
] = [isParentCollapsed(a.node), isParentCollapsed(b.node)];
if (isANodeOfCollapsedParent !== isBNodeOfCollapsedParent) {
return (isANodeOfCollapsedParent ? 1 : 0) - (isBNodeOfCollapsedParent ? 1 : 0);
}
return a.index - b.index;
})
.map(({ node }) => node);
}
function isParentCollapsed(node: ReadOnlyTreeNode): boolean {
const parentNode = node.hierarchy.parent;
if (parentNode) {
if (!parentNode.state.current.isExpanded) {
return true;
}
return isParentCollapsed(parentNode);
}
return false;
}

View File

@@ -9,7 +9,7 @@ import { NodeRenderingStrategy } from './Scheduling/NodeRenderingStrategy';
import { DelayScheduler } from './DelayScheduler';
import { TimeoutDelayScheduler } from './Scheduling/TimeoutDelayScheduler';
import { RenderQueueOrderer } from './Ordering/RenderQueueOrderer';
import { CollapseDepthOrderer } from './Ordering/CollapseDepthOrderer';
import { CollapsedParentOrderer } from './Ordering/CollapsedParentOrderer';
/**
* Renders tree nodes gradually to prevent UI freeze when loading large amounts of nodes.
@@ -21,7 +21,7 @@ export function useGradualNodeRendering(
scheduler: DelayScheduler = new TimeoutDelayScheduler(),
initialBatchSize = 30,
subsequentBatchSize = 5,
orderer: RenderQueueOrderer = new CollapseDepthOrderer(),
orderer: RenderQueueOrderer = new CollapsedParentOrderer(),
): NodeRenderingStrategy {
const nodesToRender = new Set<ReadOnlyTreeNode>();
const nodesBeingRendered = shallowRef(new Set<ReadOnlyTreeNode>());

View File

@@ -59,7 +59,7 @@ describe('Script', () => {
describe('level', () => {
it('cannot construct with invalid wrong value', () => {
// arrange
const invalidValue: RecommendationLevel = 55;
const invalidValue: RecommendationLevel = 55 as never;
const expectedError = 'invalid level';
// act
const construct = () => new ScriptBuilder()

View File

@@ -22,7 +22,7 @@ describe('ScriptingDefinition', () => {
});
it('throws if unknown', () => {
// arrange
const unknownValue: ScriptingLanguage = 666;
const unknownValue: ScriptingLanguage = 666 as never;
const errorMessage = `unsupported language: ${unknownValue}`;
// act
const act = () => new ScriptingDefinitionBuilder()

View File

@@ -1,93 +0,0 @@
import { describe, it, expect } from 'vitest';
import { TreeNode } from '@/presentation/components/Scripts/View/Tree/TreeView/Node/TreeNode';
import { CollapseDepthOrderer } from '@/presentation/components/Scripts/View/Tree/TreeView/Rendering/Ordering/CollapseDepthOrderer';
import { HierarchyAccessStub } from '@tests/unit/shared/Stubs/HierarchyAccessStub';
import { TreeNodeStateAccessStub } from '@tests/unit/shared/Stubs/TreeNodeStateAccessStub';
import { TreeNodeStateDescriptorStub } from '@tests/unit/shared/Stubs/TreeNodeStateDescriptorStub';
import { TreeNodeStub } from '@tests/unit/shared/Stubs/TreeNodeStub';
describe('CollapseDepthOrderer', () => {
describe('orderNodes', () => {
it('should order by collapsed state and then by depth in', () => {
// arrange
const node1 = createNodeForOrder({
isExpanded: false,
depthInTree: 1,
});
const node2 = createNodeForOrder({
isExpanded: true,
depthInTree: 2,
});
const node3 = createNodeForOrder({
isExpanded: false,
depthInTree: 3,
});
const node4 = createNodeForOrder({
isExpanded: false,
depthInTree: 4,
});
const nodes = [node1, node2, node3, node4];
const expectedOrder = [node2, node1, node3, node4];
// act
const orderer = new CollapseDepthOrderer();
const orderedNodes = orderer.orderNodes(nodes);
// assert
expect(orderedNodes.map((node) => node.id)).to.deep
.equal(expectedOrder.map((node) => node.id));
});
it('should handle parent collapsed state', () => {
// arrange
const collapsedParent = createNodeForOrder({
isExpanded: false,
depthInTree: 0,
});
const childWithCollapsedParent = createNodeForOrder({
isExpanded: true,
depthInTree: 1,
parent: collapsedParent,
});
const deepExpandedNode = createNodeForOrder({
isExpanded: true,
depthInTree: 3,
});
const nodes = [childWithCollapsedParent, collapsedParent, deepExpandedNode];
const expectedOrder = [
deepExpandedNode, // comes first due to collapse parent of child
collapsedParent,
childWithCollapsedParent,
];
// act
const orderer = new CollapseDepthOrderer();
const orderedNodes = orderer.orderNodes(nodes);
// assert
expect(orderedNodes.map((node) => node.id)).to.deep
.equal(expectedOrder.map((node) => node.id));
});
});
});
function createNodeForOrder(options: {
readonly isExpanded: boolean;
readonly depthInTree: number;
readonly parent?: TreeNode;
}): TreeNode {
return new TreeNodeStub()
.withId([
`isExpanded: ${options.isExpanded}`,
`depthInTree: ${options.depthInTree}`,
...(options.parent ? [`parent: ${options.parent.id}`] : []),
].join(', '))
.withState(
new TreeNodeStateAccessStub()
.withCurrent(
new TreeNodeStateDescriptorStub()
.withVisibility(true)
.withExpansion(options.isExpanded),
),
)
.withHierarchy(
new HierarchyAccessStub()
.withDepthInTree(options.depthInTree)
.withParent(options.parent),
);
}

View File

@@ -0,0 +1,165 @@
import { describe, it, expect } from 'vitest';
import { TreeNode } from '@/presentation/components/Scripts/View/Tree/TreeView/Node/TreeNode';
import { CollapsedParentOrderer } from '@/presentation/components/Scripts/View/Tree/TreeView/Rendering/Ordering/CollapsedParentOrderer';
import { HierarchyAccessStub } from '@tests/unit/shared/Stubs/HierarchyAccessStub';
import { TreeNodeStateAccessStub } from '@tests/unit/shared/Stubs/TreeNodeStateAccessStub';
import { TreeNodeStateDescriptorStub } from '@tests/unit/shared/Stubs/TreeNodeStateDescriptorStub';
import { TreeNodeStub } from '@tests/unit/shared/Stubs/TreeNodeStub';
describe('CollapsedParentOrderer', () => {
describe('orderNodes', () => {
const scenarios: ReadonlyArray<{
readonly description: string;
readonly nodes: TreeNode[];
readonly expectedOrderedNodes: TreeNode[];
}> = [
{
description: 'handles empty nodes list',
nodes: [],
expectedOrderedNodes: [],
},
(() => {
const expectedNode = createNodeForOrder({
isExpanded: false,
});
return {
description: 'handles single node list',
nodes: [expectedNode],
expectedOrderedNodes: [expectedNode],
};
})(),
(() => {
const node1 = createNodeForOrder({
isExpanded: false,
});
const node2 = createNodeForOrder({
isExpanded: true,
});
const node3 = createNodeForOrder({
isExpanded: true,
});
const node4 = createNodeForOrder({
isExpanded: false,
});
return {
description: 'orders by index ignoring self collapsed state',
nodes: [node1, node2, node3, node4],
expectedOrderedNodes: [node1, node2, node3, node4],
};
})(),
(() => {
const node1 = createNodeForOrder({
isExpanded: false,
parent: createNodeForOrder({ isExpanded: true }),
});
const node2 = createNodeForOrder({
isExpanded: true,
parent: createNodeForOrder({ isExpanded: true }),
});
const node3 = createNodeForOrder({
isExpanded: true,
parent: createNodeForOrder({ isExpanded: true }),
});
const node4 = createNodeForOrder({
isExpanded: false,
parent: createNodeForOrder({ isExpanded: true }),
});
return {
description: 'orders by index if all parents are expanded',
nodes: [node1, node2, node3, node4],
expectedOrderedNodes: [node1, node2, node3, node4],
};
})(),
(() => {
const node1 = createNodeForOrder({
isExpanded: true,
parent: createNodeForOrder({ isExpanded: false }),
});
const node2 = createNodeForOrder({
isExpanded: true,
parent: createNodeForOrder({ isExpanded: true }),
});
const node3 = createNodeForOrder({
isExpanded: true,
});
const node4 = createNodeForOrder({
isExpanded: true,
parent: createNodeForOrder({ isExpanded: false }),
});
return {
description: 'order by parent collapsed state then by index',
nodes: [node1, node2, node3, node4],
expectedOrderedNodes: [node2, node3, node1, node4],
};
})(),
(() => {
const collapsedNode = createNodeForOrder({
isExpanded: false,
});
const collapsedNodeChild = createNodeForOrder({
isExpanded: true,
parent: collapsedNode,
});
const collapsedNodeNestedChild = createNodeForOrder({
isExpanded: true,
parent: collapsedNodeChild,
});
const expandedNode = createNodeForOrder({
isExpanded: true,
});
const expandedNodeChild = createNodeForOrder({
isExpanded: true,
parent: expandedNode,
});
const expandedNodeNestedChild = createNodeForOrder({
isExpanded: true,
parent: expandedNodeChild,
});
return {
description: 'should handle deep parent collapsed state',
nodes: [
collapsedNode, collapsedNodeChild, collapsedNodeNestedChild,
expandedNode, expandedNodeChild, expandedNodeNestedChild,
],
expectedOrderedNodes: [
collapsedNode, expandedNode, expandedNodeChild,
expandedNodeNestedChild, collapsedNodeChild, collapsedNodeNestedChild,
],
};
})(),
];
scenarios.forEach(({ description, nodes, expectedOrderedNodes }) => {
it(description, () => {
// act
const orderer = new CollapsedParentOrderer();
const orderedNodes = orderer.orderNodes(nodes);
// assert
expect(orderedNodes.map((node) => node.id)).to.deep
.equal(expectedOrderedNodes.map((node) => node.id));
});
});
});
});
function createNodeForOrder(options: {
readonly isExpanded: boolean;
readonly parent?: TreeNode;
}): TreeNode {
return new TreeNodeStub()
.withId([
`isExpanded: ${options.isExpanded}`,
...(options.parent ? [`parent: ${options.parent.id}`] : []),
].join(', '))
.withState(
new TreeNodeStateAccessStub()
.withCurrent(
new TreeNodeStateDescriptorStub()
.withVisibility(true)
.withExpansion(options.isExpanded),
),
)
.withHierarchy(
new HierarchyAccessStub()
.withParent(options.parent),
);
}

View File

@@ -1,6 +1,7 @@
import { describe, it, expect } from 'vitest';
import { TimeFunctions, TimeoutDelayScheduler } from '@/presentation/components/Scripts/View/Tree/TreeView/Rendering/Scheduling/TimeoutDelayScheduler';
import { StubWithObservableMethodCalls } from '@tests/unit/shared/Stubs/StubWithObservableMethodCalls';
import { createMockTimeout } from '@tests/unit/shared/Stubs/TimeoutStub';
describe('TimeoutDelayScheduler', () => {
describe('scheduleNext', () => {
@@ -56,7 +57,8 @@ describe('TimeoutDelayScheduler', () => {
expect(setTimeoutCalls.length).toBe(2);
const clearTimeoutCalls = timerStub.callHistory.filter((c) => c.methodName === 'clearTimeout');
expect(clearTimeoutCalls.length).toBe(1);
const [actualId] = clearTimeoutCalls[0].args;
const [timeout] = clearTimeoutCalls[0].args;
const actualId = Number(timeout);
expect(actualId).toBe(idOfFirstSetTimeoutCall);
});
});
@@ -78,6 +80,7 @@ class TimeFunctionsStub
methodName: 'setTimeout',
args: [callback, delayInMs],
});
return this.callHistory.filter((c) => c.methodName === 'setTimeout').length as unknown as ReturnType<typeof setTimeout>;
const id = this.callHistory.filter((c) => c.methodName === 'setTimeout').length;
return createMockTimeout(id);
}
}

View File

@@ -3,6 +3,7 @@ import { throttle, ITimer, TimeoutType } from '@/presentation/components/Shared/
import { EventSource } from '@/infrastructure/Events/EventSource';
import { IEventSubscription } from '@/infrastructure/Events/IEventSource';
import { getAbsentObjectTestCases, itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
import { createMockTimeout } from '@tests/unit/shared/Stubs/TimeoutStub';
describe('throttle', () => {
describe('validates parameters', () => {
@@ -153,7 +154,7 @@ class TimerMock implements ITimer {
});
this.subscriptions.push(subscription);
const id = this.subscriptions.length - 1;
return TimerMock.mockTimeout(id);
return createMockTimeout(id);
}
public clearTimeout(timeoutId: TimeoutType): void {
@@ -172,15 +173,4 @@ class TimerMock implements ITimer {
this.currentTime = ms;
this.timeChanged.notify(this.currentTime);
}
private static mockTimeout(subscriptionId: number): TimeoutType {
const throwNodeSpecificCode = () => { throw new Error('node specific code'); };
return {
[Symbol.toPrimitive]: () => subscriptionId,
hasRef: throwNodeSpecificCode,
refresh: throwNodeSpecificCode,
ref: throwNodeSpecificCode,
unref: throwNodeSpecificCode,
};
}
}

View File

@@ -0,0 +1,13 @@
export function createMockTimeout(timerId: number): ReturnType<typeof setTimeout> {
const throwErrorForNodeOperation = () => {
throw new Error('node specific operation was called');
};
return {
[Symbol.toPrimitive]: () => timerId,
[Symbol.dispose]: throwErrorForNodeOperation, // Cancels the timeout in node
hasRef: throwErrorForNodeOperation,
refresh: throwErrorForNodeOperation,
ref: throwErrorForNodeOperation,
unref: throwErrorForNodeOperation,
};
}

18
tst.sh Executable file
View File

@@ -0,0 +1,18 @@
echo '--- Disable Location-Based Suggestions for Siri'
if $(csrutil status | grep 'enabled'); then
echo 'SIP must be disabled'
exit 1
fi
original_file='/System/Library/LaunchAgents/com.apple.parsecd.plist'
backup_file="/Users/tst/aq.disabled"
if [ -f "$original_file" ]; then
sudo launchctl unload -w "$original_file" 2> /dev/null
if sudo mv "$original_file" "$backup_file"; then
echo 'Disabled successfully'
else
>&2 echo 'Failed to disable'
fi
else
echo 'Already disabled'
fi