Make changing a default application actually take effect
Three bugs, all silent, all in the same feature. The write always worked. What failed was the refresh after it. That refresh is called from the mutation's own onExited handler and was guarded on `busy`, a binding over both processes -- and a binding hands back its cached value until the change notification feeding it has been delivered, which inside that handler has not happened yet. So `busy` read true, refresh returned immediately, and the page kept showing the old application with no error anywhere. Guards now read the Process objects directly, where the value is current, and a refresh is no longer blocked by the mutation that asked for it. The service also kept its own list of which roles it would accept. It stayed at seven when the helper and the page grew documents, text and archives, so choosing a PDF viewer set an error and changed nothing. It is derived from the snapshot now. And category matching never worked. DesktopEntries returns a QML list, for which Array.isArray is false, so the code stringified it into "Network,WebBrowser" and split on ";" alone -- one token matching no category. Browsers still appeared because their generic name contains "web browser" and the terms fallback carried the role by itself. Archives matched nothing at all, so that row could only ever offer the application it already had. The harness that should have caught the first bug passed while it was live: it set each role to the value it already had and asserted no error appeared, and the bug produces no error. It now changes a role to a genuinely different application, requires the service to observe the new value, and changes it back -- with the contract restoring the original from the outside however the run ends. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
This commit is contained in:
@@ -50,16 +50,26 @@ SettingsPage {
|
||||
}
|
||||
|
||||
function matchesRole(entry: var, role: var): bool {
|
||||
const rawCategories = Array.isArray(entry.categories)
|
||||
? entry.categories
|
||||
: [String(entry.categories ?? "")];
|
||||
// DesktopEntries hands back a QML list, not a JavaScript array, so
|
||||
// Array.isArray is false for it. The old code took that as "this is a
|
||||
// string", stringified the list into "Network,WebBrowser" and then split
|
||||
// on ";" only -- producing the single token "network,webbrowser", which
|
||||
// matches no category at all.
|
||||
//
|
||||
// Nothing failed loudly. Browsers still appeared because their generic
|
||||
// name contains "web browser", so the terms fallback carried the role
|
||||
// by itself. Archives matched NOTHING, which meant that row could only
|
||||
// ever offer the application it already had.
|
||||
//
|
||||
// Joining first and splitting on both separators handles the list form
|
||||
// and a plain string equally.
|
||||
const raw = entry.categories;
|
||||
const joined = Array.isArray(raw) ? raw.join(";") : String(raw ?? "");
|
||||
const categories = [];
|
||||
for (const rawCategory of rawCategories) {
|
||||
for (const value of String(rawCategory).split(";")) {
|
||||
const category = value.trim().toLowerCase();
|
||||
if (category !== "")
|
||||
categories.push(category);
|
||||
}
|
||||
for (const value of joined.split(/[;,]/)) {
|
||||
const category = value.trim().toLowerCase();
|
||||
if (category !== "")
|
||||
categories.push(category);
|
||||
}
|
||||
const metadata = [entry.name, entry.genericName]
|
||||
.map(value => String(value ?? "").toLowerCase())
|
||||
|
||||
Reference in New Issue
Block a user