Skip to content

Commit 428e48c

Browse files
committed
fix(web/uninstaller): Update uninstall selected count on select + prevent selection of text in many UI elements
Signed-off-by: paulober <[email protected]>
1 parent 073853c commit 428e48c

File tree

2 files changed

+33
-15
lines changed

2 files changed

+33
-15
lines changed

web/uninstaller/main.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,11 @@ body {
1717
margin: 0;
1818
}
1919

20+
.prevent-select {
21+
-webkit-user-select: none;
22+
-moz-user-select: none;
23+
-ms-user-select: none;
24+
user-select: none;
25+
}
26+
2027
/* Fullscreen overlay tweaks handled via Tailwind classes; nothing else needed */

web/uninstaller/main.js

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -144,36 +144,36 @@ function renderToolbar() {
144144
<div class="flex flex-wrap items-center justify-between gap-3 mb-2">
145145
<div class="flex items-center gap-2 flex-1">
146146
<input id="search" type="search" placeholder="Search (name, id, version)…"
147-
class="w-full md:w-96 px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 bg-white/80 dark:bg-zinc-900/80 focus:outline-none focus:ring focus:ring-blue-500/40"
147+
class="w-full md:w-96 px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 bg-white/80 dark:bg-zinc-900/80 focus:outline-none focus:ring focus:ring-blue-500/40 prevent-select"
148148
value="${state.filter}">
149149
</div>
150150
151151
<div class="flex items-center gap-2">
152152
<button id="sort-installed"
153153
class="px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-zinc-800 ${state.sortKey === 'installedAt' ? 'ring-1 ring-blue-500/50' : ''}"
154154
title="Sort by install date">
155-
<span class="mr-1">Installed</span>
155+
<span class="mr-1 prevent-select">Installed</span>
156156
<span aria-hidden="true">${state.sortKey === 'installedAt' ? (state.sortDir === 'desc' ? '↓' : '↑') : ''}</span>
157157
</button>
158158
159159
<button id="sort-last" class="px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-zinc-800 ${state.sortKey === 'lastUsed' ? 'ring-1 ring-blue-500/50' : ''}" title="Sort by last used">
160-
<span class="mr-1">Last used</span>
160+
<span class="mr-1 prevent-select">Last used</span>
161161
<span aria-hidden="true">${state.sortKey === 'lastUsed' ? (state.sortDir === 'desc' ? '↓' : '↑') : ''}</span>
162162
</button>
163163
164164
<button id="sort-name" class="px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-zinc-800 ${state.sortKey === 'name' ? 'ring-1 ring-blue-500/50' : ''}" title="Sort by name">
165-
<span class="mr-1">Name</span>
165+
<span class="mr-1 prevent-select">Name</span>
166166
<span aria-hidden="true">${state.sortKey === 'name' ? (state.sortDir === 'asc' ? '↑' : '↓') : ''}</span>
167167
</button>
168168
169169
<div class="h-6 w-px bg-gray-300 dark:bg-zinc-700 mx-1"></div>
170170
171171
<label class="inline-flex items-center gap-2 px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-zinc-800 cursor-pointer">
172172
<input id="select-all" type="checkbox" class="h-4 w-4 accent-blue-600">
173-
<span>Select all (visible)</span>
173+
<span class="prevent-select">Select all (visible)</span>
174174
</label>
175175
176-
<button id="select-stale" class="px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-zinc-800"
176+
<button id="select-stale" class="px-3 py-2 rounded-xl border border-gray-300 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-zinc-800 prevent-select"
177177
title="Select items last used > 30 days ago that are not the latest version">
178178
Select stale & not-latest
179179
</button>
@@ -196,25 +196,25 @@ function itemRow(i) {
196196
<label class="flex items-center gap-3 flex-1 cursor-pointer">
197197
<input data-role="select" data-id="${i.id}" type="checkbox" class="h-4 w-4 accent-blue-600" ${checked} />
198198
<div class="flex flex-col">
199-
<div class="text-sm font-medium">
199+
<div class="text-sm font-medium prevent-select">
200200
${escapeHtml(i.label)}
201201
<span class="text-gray-500 dark:text-gray-400 font-normal">• ${escapeHtml(i.version || "unknown")}</span>
202202
</div>
203203
<div class="text-xs text-gray-500 dark:text-gray-400 truncate" title="${escapeHtml((i.path || i.depId) + (i.path ? "" : ""))}">
204-
${escapeHtml(i.depId)}${i.path ? `${escapeHtml(i.path)}` : ""}
204+
<span class="prevent-select">${escapeHtml(i.depId)}</span>${i.path ? `<span class="prevent-select"> • </span>${escapeHtml(i.path)}` : ""}
205205
</div>
206206
</div>
207207
</label>
208208
209209
<div class="flex items-center gap-2 sm:gap-3 shrink-0">
210210
<span class="text-xs px-2 py-1 rounded-full border border-gray-300 dark:border-zinc-700 text-gray-700 dark:text-gray-300 bg-gray-50 dark:bg-zinc-800">
211-
Last used: ${escapeHtml(last)}
211+
<span class="prevent-select">Last used: </span>${escapeHtml(last)}
212212
</span>
213213
<span class="text-xs px-2 py-1 rounded-full border border-gray-300 dark:border-zinc-700 text-gray-700 dark:text-gray-300 bg-gray-50 dark:bg-zinc-800">
214-
Installed: ${escapeHtml(installed)}
214+
<span class="prevent-select">Installed: </span>${escapeHtml(installed)}
215215
</span>
216216
<button data-role="uninstall-one" data-id="${i.id}"
217-
class="px-3 py-2 rounded-xl bg-red-600 text-white hover:bg-red-700">
217+
class="px-3 py-2 rounded-xl bg-red-600 text-white hover:bg-red-700 prevent-select">
218218
Uninstall
219219
</button>
220220
</div>
@@ -248,7 +248,7 @@ function renderOverlay(visible = false) {
248248
function renderFrame() {
249249
document.body.innerHTML = `
250250
<div class="h-full w-full overflow-hidden grid grid-rows-[auto,1fr] text-[13px] text-gray-900 dark:text-gray-100">
251-
<header class="px-5 py-4 shrink-0">
251+
<header class="px-5 py-4 shrink-0 prevent-select">
252252
<h1 class="text-lg font-semibold">Uninstall components</h1>
253253
<p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
254254
Select one or more installed items to uninstall. Sort by last used to find stale components quickly.
@@ -386,8 +386,19 @@ function bindEvents() {
386386
if (id) {
387387
if (target.checked) state.selected.add(id); else state.selected.delete(id);
388388
updateSelectAllCheckbox();
389-
$("#uninstall-selected")?.setAttribute("disabled", state.selected.size ? "" : "disabled");
390-
if (state.selected.size) $("#uninstall-selected")?.removeAttribute("disabled");
389+
const uninstallSelectedBtn = document.getElementById("uninstall-selected");
390+
if (uninstallSelectedBtn) {
391+
uninstallSelectedBtn.disabled = state.selected.size === 0;
392+
// Update content without having to re-render the whole toolbar
393+
// replace (<number>) in button text with current count
394+
const m = uninstallSelectedBtn.textContent.match(/\((\d+)\)/);
395+
if (m) {
396+
uninstallSelectedBtn.textContent = uninstallSelectedBtn.textContent.replace(
397+
m[0],
398+
`(${state.selected.size})`);
399+
}
400+
if (state.selected.size) uninstallSelectedBtn.removeAttribute("disabled");
401+
}
391402
}
392403
}
393404
});
@@ -531,7 +542,7 @@ function renderBootLoading(text = "Loading installed components…") {
531542
<div class="h-full w-full grid place-items-center">
532543
<div class="flex flex-col items-center gap-4 p-8 rounded-2xl bg-white/90 dark:bg-zinc-900/90 border border-gray-200 dark:border-zinc-800">
533544
<div class="h-10 w-10 rounded-full border-4 border-gray-300 dark:border-zinc-700 border-t-transparent animate-spin"></div>
534-
<div class="text-sm text-gray-700 dark:text-gray-200">${escapeHtml(text)}</div>
545+
<div class="text-sm text-gray-700 dark:text-gray-200 prevent-select">${escapeHtml(text)}</div>
535546
</div>
536547
</div>
537548
`;

0 commit comments

Comments
 (0)