From 76d25619e64e0f8e4245be8b0afe2399874c0ca6 Mon Sep 17 00:00:00 2001 From: thorsten Date: Mon, 20 Jul 2026 18:57:57 +0200 Subject: [PATCH 1/6] chore: move solution to repo root, modernize README, add release tooling - Move CleanMyPosts.slnx to the repository root; drop the src/ copy and update the Solution env var in both workflows accordingly. - Modernize the README badge bar (flat-square + logos, sorted); drop the License badge; add Release and Downloads badges. - Add SECURITY.md and a root CLAUDE.md documenting layout, build/test, branch policy and the release process. - Add the prepare-release skill (.claude/skills/prepare-release) that cuts a release PR: version bump, release notes, PR to main. - Run CI on pull_request to main so the required build check can pass. - Pin *.sh to LF so the skill script stays runnable on Windows. --- .claude/skills/prepare-release/SKILL.md | 68 +++++++++++++++++++ .../prepare-release/assets/release-notes.md | 9 +++ .../prepare-release/scripts/check-updates.sh | 27 ++++++++ .gitattributes | 1 + .github/workflows/ci.yml | 4 +- .github/workflows/deploy-release.yml | 2 +- CLAUDE.md | 56 +++++++++++++++ CleanMyPosts.slnx | 28 ++++++++ README.md | 11 +-- SECURITY.md | 22 ++++++ src/CleanMyPosts.slnx | 19 ------ 11 files changed, 221 insertions(+), 26 deletions(-) create mode 100644 .claude/skills/prepare-release/SKILL.md create mode 100644 .claude/skills/prepare-release/assets/release-notes.md create mode 100644 .claude/skills/prepare-release/scripts/check-updates.sh create mode 100644 CLAUDE.md create mode 100644 CleanMyPosts.slnx create mode 100644 SECURITY.md delete mode 100644 src/CleanMyPosts.slnx diff --git a/.claude/skills/prepare-release/SKILL.md b/.claude/skills/prepare-release/SKILL.md new file mode 100644 index 0000000..3c89e76 --- /dev/null +++ b/.claude/skills/prepare-release/SKILL.md @@ -0,0 +1,68 @@ +--- +name: prepare-release +description: Prepare a new release of CleanMyPosts (version bump, release notes, release PR to main). Use this whenever the user mentions releasing, publishing, shipping, cutting a release, bumping the version, or preparing release notes — even if they don't say "release" explicitly. Decides the next SemVer version automatically and proceeds when there are new commits since the last tag. +--- + +# Prepare release + +Prepare a new release of the CleanMyPosts desktop app. You decide the next +version yourself. You **prepare the repository and open the release PR — then +stop.** Reviewing, merging, and publishing are **admin-only** and not part of +your job: + +- You do **not** merge the release PR (or enable auto-merge). The admin reviews + and merges every PR manually. `main` is a protected branch — direct pushes are + blocked, so every change ships through a PR. +- You do **not** trigger `deploy-release.yml`. The GitHub Release (installer + build, `v` git tag, AutoUpdater feed) is a manual `workflow_dispatch` + the admin runs **after** merging the release PR. + +## Workflow + +1. **Check whether there is anything to release** + - Run the helper: `bash .claude/skills/prepare-release/scripts/check-updates.sh` + - Exit code **3** = nothing to release (no new commits since the last tag) → **stop**. + - Exit code **0** = new commits exist → continue. + +2. **Determine current version & last tag** + - Read `` in `src/CleanMyPosts/CleanMyPosts.csproj`. + - Latest tag: `git tag --sort=-v:refname | head -1`. + +3. **Decide the next version (SemVer)** from `git log --oneline ..HEAD`: + - **MAJOR** breaking / behavior-removing changes · **MINOR** new features · + **PATCH** fixes/docs/dependency bumps. + - Must be strictly greater than the current version. State it + a one-line reason. + +4. **Confirm clean tree** — `git status --short`; if dirty, ask how to proceed. + +5. **Branch from up-to-date `main`** — `git checkout main && git pull` then + `git checkout -b release/v`. Release branches always cut from `main`. + +6. **Build & test (green required)** + - `dotnet build CleanMyPosts.slnx -c Release` + - `dotnet test src/Tests/Tests.csproj -c Release --filter "TestCategory!=Long-Running"` + (same filter CI uses; long-running tests are excluded). + +7. **Bump ``** in `src/CleanMyPosts/CleanMyPosts.csproj`. + +8. **Extend docs** — update `README.md` etc. if the changes warrant it. + +9. **Release notes** — copy `.claude/skills/prepare-release/assets/release-notes.md` + to `release-notes/v.md` and fill in the `### What's Changed` bullets + with **user-facing** notes (not raw commit subjects). This file becomes the + GitHub Release body verbatim — `deploy-release.yml` reads it via `body_path`. + +10. **Commit** (no tag) — stage the csproj, docs, and release notes; message + `release: v`. Do **not** create a git tag — `deploy-release.yml` + creates `v` at publish time. + +11. **Push & open PR to main — then stop. Do NOT merge it.** + - `git push -u origin release/v` + - `gh pr create --base main --head release/v --title "release: v" --body ` + - The admin reviews and merges the PR. You never merge it or enable auto-merge. + +12. **Report** the PR link and remind the admin: after **they** merge it, **they** + trigger **Deploy Release** manually (Actions → Deploy Release → Run workflow). + That workflow builds the installer, tags `v`, publishes the GitHub + Release from `release-notes/v.md`, and updates the AutoUpdater feed. + You do not trigger it. diff --git a/.claude/skills/prepare-release/assets/release-notes.md b/.claude/skills/prepare-release/assets/release-notes.md new file mode 100644 index 0000000..4a2ad66 --- /dev/null +++ b/.claude/skills/prepare-release/assets/release-notes.md @@ -0,0 +1,9 @@ +### What's Changed + +* {{ ... user-facing change ... }} + + diff --git a/.claude/skills/prepare-release/scripts/check-updates.sh b/.claude/skills/prepare-release/scripts/check-updates.sh new file mode 100644 index 0000000..15a696b --- /dev/null +++ b/.claude/skills/prepare-release/scripts/check-updates.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Decides whether there is anything worth releasing. +# +# A release is warranted when there are new commits since the last tag +# (features, fixes, breaking changes). +# +# Exit 0 = something to release, 3 = nothing to release, 1 = error. +set -euo pipefail + +# Run from the repository root so the tag/log lookups are unambiguous. +cd "$(git rev-parse --show-toplevel)" + +last_tag="$(git tag --sort=-v:refname | head -1)" +if [[ -n "$last_tag" ]]; then + commits="$(git log "$last_tag"..HEAD --oneline 2>/dev/null || true)" +else + commits="$(git log --oneline 2>/dev/null || true)" +fi + +if [[ -z "$commits" ]]; then + echo "No new commits since ${last_tag:-the start} — nothing to release." + exit 3 +fi + +echo "Releasable changes since ${last_tag:-the start}:" +echo "$commits" +exit 0 diff --git a/.gitattributes b/.gitattributes index 1ff0c42..ef82812 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto +*.sh text eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8075b5d..73d52f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,8 @@ name: "CI" on: push: branches: [ develop, main ] + pull_request: + branches: [ main ] permissions: contents: read @@ -15,7 +17,7 @@ jobs: runs-on: windows-latest env: - Solution: "src/CleanMyPosts.slnx" + Solution: "CleanMyPosts.slnx" Test_Project: "src/Tests/Tests.csproj" FORCE_COLOR: "true" DOTNET_LOGGING__CONSOLE__COLORBEHAVIOR: Enabled diff --git a/.github/workflows/deploy-release.yml b/.github/workflows/deploy-release.yml index 8196e85..51c88f3 100644 --- a/.github/workflows/deploy-release.yml +++ b/.github/workflows/deploy-release.yml @@ -14,7 +14,7 @@ jobs: runs-on: windows-latest env: - Solution: "src/CleanMyPosts.slnx" + Solution: "CleanMyPosts.slnx" UI_Project: "src/CleanMyPosts/CleanMyPosts.csproj" Test_Project: "src/Tests/Tests.csproj" Installer_Script: "installer/Installer.iss" diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..178178d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,56 @@ +# CLAUDE.md + +CleanMyPosts is a **.NET 10 WPF Windows desktop app** that bulk-deletes posts, +reposts, replies, likes and followings on X (Twitter) and comments/likes on +YouTube, by driving an embedded WebView2 browser with injected JavaScript. + +## Layout + +``` +CleanMyPosts.slnx # solution (repo root) +src/CleanMyPosts/CleanMyPosts.csproj # WPF app (WebView2 + MahApps.Metro + CommunityToolkit.Mvvm) + Scripts/ # injected JS (delete-all-*.js) + Services/ ViewModels/ Views/ # MVVM +src/Tests/Tests.csproj # xUnit tests (Xunit.StaFact for UI) +installer/Installer.iss # Inno Setup installer script +release-notes/vX.Y.Z.md # GitHub Release body per version +.github/workflows/ci.yml # build + test on push/PR to main +.github/workflows/deploy-release.yml # manual: installer, tag, GitHub Release, AutoUpdater feed +``` + +## Build & test + +```bash +dotnet build CleanMyPosts.slnx -c Release +dotnet test src/Tests/Tests.csproj -c Release --filter "TestCategory!=Long-Running" +``` + +The filter mirrors CI, which excludes long-running tests. + +## Branching + +`main` is **protected** — direct pushes are blocked (including for admins) and +the `build` status check must pass. Every change ships through a PR against +`main`. Use `feature/` for functionality, `fix/` for bug fixes, and +`release/vX.Y.Z` for release prep. + +## Versioning & release + +- Version lives in `src/CleanMyPosts/CleanMyPosts.csproj` (``). +- Do not bump `` without also adding `release-notes/v.md` — + that file becomes the GitHub Release body (`deploy-release.yml` reads it via + `body_path`). +- **Do not create git tags manually.** `deploy-release.yml` creates the + `v` tag when it publishes. +- The full release-prep flow (decide SemVer, branch, build/test, bump version, + write release notes, open the PR to `main`) is encoded in the + **`prepare-release`** skill at `.claude/skills/prepare-release/`. Run it via + Claude Code (`/prepare-release`) when cutting a release; it prepares the PR + only. Merging the PR and running **Deploy Release** (`workflow_dispatch`) are + manual, admin-only steps. + +## Code style + +Global conventions in `~/.claude/CLAUDE.md` apply: comments only when the *why* +is non-obvious, `var` when the type is evident, expression-bodied members, +`is null` / `is not null`, `_camelCase` private fields, no `#region`. diff --git a/CleanMyPosts.slnx b/CleanMyPosts.slnx new file mode 100644 index 0000000..044b71b --- /dev/null +++ b/CleanMyPosts.slnx @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 5804a61..9486673 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ ![Banner](https://raw.githubusercontent.com/thorstenalpers/CleanMyPosts/main/src/CleanMyPosts/Assets/banner.png) -[![Windows](https://img.shields.io/badge/platform-Windows-blue)](#) -[![License](https://img.shields.io/badge/License-MIT-blue.svg)](./LICENSE.txt) -[![CI Tests](https://github.com/thorstenalpers/CleanMyPosts/actions/workflows/ci.yml/badge.svg)](https://github.com/thorstenalpers/CleanMyPosts/actions/workflows/ci.yml) -[![Donate](https://img.shields.io/badge/donate-PayPal-yellow)](https://www.paypal.com/donate/?hosted_button_id=QYHGE9LA9SNAN) -[![Star this repo](https://img.shields.io/github/stars/thorstenalpers/CleanMyPosts.svg?style=social&label=Star&maxAge=60)](https://github.com/thorstenalpers/CleanMyPosts) +[![CI](https://img.shields.io/github/actions/workflow/status/thorstenalpers/CleanMyPosts/ci.yml?branch=main&style=flat-square&logo=githubactions&logoColor=white&label=CI)](https://github.com/thorstenalpers/CleanMyPosts/actions/workflows/ci.yml) +[![Release](https://img.shields.io/github/v/release/thorstenalpers/CleanMyPosts?style=flat-square&logo=github&label=release)](https://github.com/thorstenalpers/CleanMyPosts/releases/latest) +[![Downloads](https://img.shields.io/github/downloads/thorstenalpers/CleanMyPosts/total?style=flat-square&logo=github&label=downloads)](https://github.com/thorstenalpers/CleanMyPosts/releases) +[![Platform](https://img.shields.io/badge/platform-Windows-0078D6?style=flat-square&logo=windows&logoColor=white)](https://github.com/thorstenalpers/CleanMyPosts/releases) +[![Donate](https://img.shields.io/badge/donate-PayPal-00457C?style=flat-square&logo=paypal&logoColor=white)](https://www.paypal.com/donate/?hosted_button_id=QYHGE9LA9SNAN) +[![Stars](https://img.shields.io/github/stars/thorstenalpers/CleanMyPosts?style=flat-square&logo=github&label=stars)](https://github.com/thorstenalpers/CleanMyPosts) **CleanMyPosts** is a lightweight Windows desktop app that securely deletes all posts, reposts, replies, likes, and followings from your X (formerly Twitter) account, as well as YouTube comments, in bulk using browser automation. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..ddaa277 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +## Reporting a vulnerability + +Please report security vulnerabilities **privately** — do not open a public +issue or pull request for them. + +Use GitHub's private reporting flow: +[**Report a vulnerability**](https://github.com/thorstenalpers/CleanMyPosts/security/advisories/new). + +Please include enough detail to reproduce the issue (affected version, a minimal +repro or proof of concept, and the impact). You can expect an initial response +within a few days. Once a fix is available it will be published as a new release. + +## Supported versions + +Only the latest release receives security fixes. + +| Version | Supported | +| ------- | --------- | +| latest | ✅ | +| older | ❌ | diff --git a/src/CleanMyPosts.slnx b/src/CleanMyPosts.slnx deleted file mode 100644 index e249881..0000000 --- a/src/CleanMyPosts.slnx +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - From 4266b7035a969bb2c7b22a57bb0a11c2b647a86b Mon Sep 17 00:00:00 2001 From: thorsten Date: Mon, 20 Jul 2026 18:59:08 +0200 Subject: [PATCH 2/6] chore: track local build scripts - Narrow the .gitignore rule from *.cmd to *local.cmd so the shared build/clean/license helper scripts are versioned. - Add build.cmd, clean.cmd and create-licenses.cmd. --- .gitignore | 2 +- build.cmd | 14 +++++++++++ clean.cmd | 57 +++++++++++++++++++++++++++++++++++++++++++++ create-licenses.cmd | 3 +++ 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 build.cmd create mode 100644 clean.cmd create mode 100644 create-licenses.cmd diff --git a/.gitignore b/.gitignore index 821d1a0..9cdb63a 100644 --- a/.gitignore +++ b/.gitignore @@ -363,7 +363,7 @@ MigrationBackup/ FodyWeavers.xsd # local cmd files -*.cmd +*local.cmd # Installer releases installer/Output diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..3bc136f --- /dev/null +++ b/build.cmd @@ -0,0 +1,14 @@ +cd C:\Sources\CleanMyPosts\src\UI + +REM dotnet clean ..\CleanMyPosts.sln +REM dotnet restore ..\CleanMyPosts.sln + +REM dotnet build ..\CleanMyPosts.sln --configuration Release --no-restore + +REM dotnet publish UI.csproj -c Release -r win-x64 --self-contained true + +dotnet clean ..\CleanMyPosts.sln +REM dotnet publish ..\CleanMyPosts.sln -c Release -r win-x64 --self-contained true +dotnet publish ..\CleanMyPosts.sln -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:PublishTrimmed=false + +cd C:\Sources\CleanMyPosts\ \ No newline at end of file diff --git a/clean.cmd b/clean.cmd new file mode 100644 index 0000000..549b7ec --- /dev/null +++ b/clean.cmd @@ -0,0 +1,57 @@ +@echo off +setlocal enabledelayedexpansion + +taskkill /im dotnet.exe /f + + +set "rootDir=C:\Sources\CleanMyPosts" +set "vsDir=%rootDir%\.vs" +set "testresultDir=%rootDir%\TestResults" + +rd /s /q "%vsDir%" + +rd /s /q "%testresultDir%" + + +:: Iterate over all subdirectories under %rootDir% +for /d /r "%rootDir%" %%a in (*) do ( + if /i "%%~nxa"=="bin" ( + call :DeleteBinObj "%%a" "bin" + ) else if /i "%%~nxa"=="obj" ( + call :DeleteBinObj "%%a" "obj" + ) +) + +echo Finished. +REM pause +exit /b + +:DeleteBinObj +setlocal +set "currentDir=%~1" +set "skipDelete=" + +:: Check for .git, node_modules, or _archive in the current directory path +for %%b in ("%currentDir%") do ( + for %%c in (".git" "node_modules" "_archive") do ( + echo %%b | findstr /i "%%c" >nul + if not errorlevel 1 ( + set "skipDelete=yes" + goto :skipDeletion + ) + ) +) + +:skipDeletion +if not defined skipDelete ( + if /i "%~2"=="bin" ( + echo Deleting folder: "%currentDir%" + rd /s /q "%currentDir%" + ) else if /i "%~2"=="obj" ( + echo Deleting folder: "%currentDir%" + rd /s /q "%currentDir%" + ) +) + +endlocal + diff --git a/create-licenses.cmd b/create-licenses.cmd new file mode 100644 index 0000000..373a424 --- /dev/null +++ b/create-licenses.cmd @@ -0,0 +1,3 @@ +echo ["Tests.csproj"] > exclude.json +dotnet-project-licenses -i src/CleanMyPosts.sln --projects-filter exclude.json -o --outfile THIRD_PARTY_LICENSES.txt +rm exclude.json From 0c157a5380db49a927e4092924894176473188d1 Mon Sep 17 00:00:00 2001 From: thorsten Date: Mon, 20 Jul 2026 19:09:10 +0200 Subject: [PATCH 3/6] fix: make the Third-Party Licenses UI link work - Bundle THIRD_PARTY_LICENSES.txt into the app output (linked Content), so the installer wildcard ships it into the app directory. - Open THIRD_PARTY_LICENSES.txt from AppContext.BaseDirectory instead of a bare "license.txt" that was never bundled and didn't match the file name. - Point create-licenses.cmd at the shipped project (src/CleanMyPosts) after the solution moved to the repo root; drop the now-redundant Tests exclusion. --- create-licenses.cmd | 4 +--- src/CleanMyPosts/CleanMyPosts.csproj | 3 +++ src/CleanMyPosts/ViewModels/SettingsViewModel.cs | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/create-licenses.cmd b/create-licenses.cmd index 373a424..6981946 100644 --- a/create-licenses.cmd +++ b/create-licenses.cmd @@ -1,3 +1 @@ -echo ["Tests.csproj"] > exclude.json -dotnet-project-licenses -i src/CleanMyPosts.sln --projects-filter exclude.json -o --outfile THIRD_PARTY_LICENSES.txt -rm exclude.json +dotnet-project-licenses -i src/CleanMyPosts -o --outfile THIRD_PARTY_LICENSES.txt diff --git a/src/CleanMyPosts/CleanMyPosts.csproj b/src/CleanMyPosts/CleanMyPosts.csproj index 9873aca..52a691e 100644 --- a/src/CleanMyPosts/CleanMyPosts.csproj +++ b/src/CleanMyPosts/CleanMyPosts.csproj @@ -90,6 +90,9 @@ PreserveNewest + + PreserveNewest + diff --git a/src/CleanMyPosts/ViewModels/SettingsViewModel.cs b/src/CleanMyPosts/ViewModels/SettingsViewModel.cs index 66111f4..2e6f146 100644 --- a/src/CleanMyPosts/ViewModels/SettingsViewModel.cs +++ b/src/CleanMyPosts/ViewModels/SettingsViewModel.cs @@ -71,7 +71,8 @@ private void SetTheme(string themeName) [RelayCommand] private static void OpenLicense() { - Process.Start(new ProcessStartInfo { FileName = "license.txt", UseShellExecute = true }); + var licensePath = System.IO.Path.Combine(AppContext.BaseDirectory, "THIRD_PARTY_LICENSES.txt"); + Process.Start(new ProcessStartInfo { FileName = licensePath, UseShellExecute = true }); } [RelayCommand] From e0a4b45364f039247afaba328fd0f3f80d72de66 Mon Sep 17 00:00:00 2001 From: thorsten Date: Mon, 20 Jul 2026 19:21:08 +0200 Subject: [PATCH 4/6] fix(youtube): auto-dismiss the feedback survey banner during comment deletion Google My Activity pops a modal feedback/survey dialog mid-run (typically after the first couple of deletions). Being modal, it blocks the next delete click and stalls the loop. Dismiss it at the top of each iteration by clicking its "Close this dialog" button when present. --- .../Scripts/delete-all-youtube-posts.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/CleanMyPosts/Scripts/delete-all-youtube-posts.js b/src/CleanMyPosts/Scripts/delete-all-youtube-posts.js index b24ec16..c9c0463 100644 --- a/src/CleanMyPosts/Scripts/delete-all-youtube-posts.js +++ b/src/CleanMyPosts/Scripts/delete-all-youtube-posts.js @@ -14,6 +14,18 @@ async function DeleteAllYouTubeComments(waitAfterDelete = 1000, waitBetweenDelet console.log(`[${new Date().toLocaleTimeString()}] ${msg}`); } + // A Google feedback/survey dialog can pop up mid-run and, being modal, blocks + // the next delete click. Dismiss it whenever it appears. + function dismissSurveyBanner() { + const closeBtn = document.querySelector('button[aria-label="Close this dialog"]'); + if (closeBtn && closeBtn.getBoundingClientRect().width > 0) { + closeBtn.click(); + log("[dismissSurveyBanner] Dismissed feedback/survey banner."); + return true; + } + return false; + } + async function waitForDeleteButton(maxWait = 5000, interval = 300) { const start = Date.now(); while (true) { @@ -113,6 +125,7 @@ async function DeleteAllYouTubeComments(waitAfterDelete = 1000, waitBetweenDelet let commentNumber = 1; while (failures < maxFailures) { + dismissSurveyBanner(); const found = await waitForDeleteButton(5000, 300); if (!found) { failures++; From 2ee07a93d1518a3ca66f7fe8dfde26c6576d74ab Mon Sep 17 00:00:00 2001 From: thorsten Date: Mon, 20 Jul 2026 19:26:50 +0200 Subject: [PATCH 5/6] fix(youtube): also dismiss the feedback survey banner while unliking videos Apply the same modal feedback/survey dialog dismissal to the liked-videos unlike loop as a safeguard against the Google-wide feedback widget. --- .../Scripts/delete-all-youtube-likes.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/CleanMyPosts/Scripts/delete-all-youtube-likes.js b/src/CleanMyPosts/Scripts/delete-all-youtube-likes.js index 8a890f2..6ed333e 100644 --- a/src/CleanMyPosts/Scripts/delete-all-youtube-likes.js +++ b/src/CleanMyPosts/Scripts/delete-all-youtube-likes.js @@ -14,6 +14,18 @@ async function DeleteAllYouTubeLikes(waitAfterDelete = 1000, waitBetweenDeleteAt console.log(`[${new Date().toLocaleTimeString()}] ${msg}`); } + // A Google feedback/survey dialog can pop up mid-run and, being modal, blocks + // the next click. Dismiss it whenever it appears. + function dismissSurveyBanner() { + const closeBtn = document.querySelector('button[aria-label="Close this dialog"]'); + if (closeBtn && closeBtn.getBoundingClientRect().width > 0) { + closeBtn.click(); + log("[dismissSurveyBanner] Dismissed feedback/survey banner."); + return true; + } + return false; + } + // Multilingual patterns for "Remove from Liked videos" const removePatterns = [ // English @@ -299,6 +311,7 @@ async function DeleteAllYouTubeLikes(waitAfterDelete = 1000, waitBetweenDeleteAt let videoNumber = 1; while (failures < maxFailures) { + dismissSurveyBanner(); const found = await waitForVideo(5000, 300); if (!found) { failures++; From 931be4cb4b736971b3da24995ba70520d332f272 Mon Sep 17 00:00:00 2001 From: thorsten Date: Mon, 20 Jul 2026 19:31:30 +0200 Subject: [PATCH 6/6] release: v2.1.4 - Update NuGet dependencies to latest (CommunityToolkit.Mvvm, WebView2, Microsoft.Extensions.*, Serilog.Settings.Configuration, SonarAnalyzer, coverlet, FluentAssertions, Microsoft.NET.Test.Sdk). Xunit.StaFact held at 1.2.69 since 3.x requires xunit v3. - Bump to 2.1.4. - Add release-notes/v2.1.4.md. --- release-notes/v2.1.4.md | 5 ++++ src/CleanMyPosts/CleanMyPosts.csproj | 38 ++++++++++++++-------------- src/Tests/Tests.csproj | 18 ++++++------- 3 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 release-notes/v2.1.4.md diff --git a/release-notes/v2.1.4.md b/release-notes/v2.1.4.md new file mode 100644 index 0000000..9e36455 --- /dev/null +++ b/release-notes/v2.1.4.md @@ -0,0 +1,5 @@ +### What's Changed + +* Fix: Auto-dismiss the Google feedback/survey banner that could interrupt bulk deletion of YouTube comments and removal of liked videos. +* Fix: The "View Third-Party Licenses" link in Settings now opens the bundled license file correctly. +* Maintenance: Updated NuGet dependencies to their latest versions. diff --git a/src/CleanMyPosts/CleanMyPosts.csproj b/src/CleanMyPosts/CleanMyPosts.csproj index 52a691e..784b971 100644 --- a/src/CleanMyPosts/CleanMyPosts.csproj +++ b/src/CleanMyPosts/CleanMyPosts.csproj @@ -10,7 +10,7 @@ Assets\logo.ico CleanMyPosts net10.0-windows - 2.1.3 + 2.1.4 false latest True @@ -18,24 +18,24 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index ab5946b..4264293 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -15,31 +15,31 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - +