Two changes that pull in the same direction: the panel says less, and the menu stops pretending to do anything. The chip row had no bound. It sits in the centre box next to the clock, so enough open sessions would have shoved the clock off centre. It now shows the first N, settable and three by default, and counts the rest as "+N". Chips are already ordered by urgency, so the ones that survive the cut are the ones that need you soonest. Labels are still assigned across every session, including hidden ones, so a chip does not change when the cap does or when a session ahead of it disappears. Clicking a menu row used to switch the zellij tab and raise a terminal. That is gone. It cost real machinery for what it saved -- gnome-terminal runs every window under one shared server process, so windows cannot be matched by pid and the code fell back to matching the zellij session name against window titles, with all the ways that misses. The menu reports status; alt-tab is not the bottleneck. Rows are built inert rather than demoted after the fact, because PopupBaseMenuItem latches _activatable in its constructor. zellij tab lookup stays: naming the tab is the better half of that feature and costs one process every couple of minutes. The preferences test now asserts a control per settings key rather than a switch per key, so the new spin row counts and a future non-boolean setting cannot slip in without one.
90 lines
3.6 KiB
JavaScript
90 lines
3.6 KiB
JavaScript
#!/usr/bin/gjs -m
|
|
// Builds the preferences window for real, under real Adw.
|
|
//
|
|
// prefs.js runs in its own process, not in the compositor, so a nested-shell
|
|
// check cannot reach it -- without this it is the one file in the extension
|
|
// that never executes until a user opens it and finds it broken.
|
|
//
|
|
// The shell's own base class and gettext are stubbed rather than loaded: they
|
|
// resolve an extension by walking the caller's URL up to a registered UUID,
|
|
// which needs the whole extension manager. Stubbing them keeps the test about
|
|
// this extension's code, which is the part that can be wrong.
|
|
//
|
|
// Run: gjs -m tests/test-prefs.js
|
|
|
|
import Gio from 'gi://Gio';
|
|
import GLib from 'gi://GLib';
|
|
import Adw from 'gi://Adw';
|
|
|
|
Adw.init();
|
|
|
|
const HERE = GLib.path_get_dirname(
|
|
GLib.filename_from_uri(import.meta.url)[0]);
|
|
const EXT = GLib.path_get_dirname(HERE);
|
|
const SHELL_PREFS = 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js';
|
|
|
|
const tmp = GLib.dir_make_tmp('ccs-prefs-XXXXXX');
|
|
const [, source] = GLib.file_get_contents(`${EXT}/prefs.js`);
|
|
GLib.file_set_contents(`${tmp}/stub.js`,
|
|
'export class ExtensionPreferences {}\nexport const gettext = s => s;\n');
|
|
GLib.file_set_contents(`${tmp}/prefs.js`,
|
|
new TextDecoder().decode(source).replace(SHELL_PREFS, './stub.js'));
|
|
|
|
const schemas = Gio.SettingsSchemaSource.new_from_directory(
|
|
`${EXT}/schemas`, Gio.SettingsSchemaSource.get_default(), false);
|
|
|
|
const { default: Prefs } = await import(`file://${tmp}/prefs.js`);
|
|
const prefs = new Prefs();
|
|
Object.defineProperty(prefs, 'path', { value: EXT }); // a getter upstream
|
|
prefs.getSettings = () => new Gio.Settings({
|
|
settings_schema: schemas.lookup(
|
|
'org.gnome.shell.extensions.claude-code-status', true),
|
|
});
|
|
|
|
const window = new Adw.PreferencesWindow();
|
|
prefs.fillPreferencesWindow(window);
|
|
|
|
const rows = [];
|
|
const walk = widget => {
|
|
for (let c = widget.get_first_child?.(); c; c = c.get_next_sibling()) {
|
|
const type = c.constructor.$gtype.name;
|
|
if (type === 'AdwSwitchRow' || type === 'AdwSpinRow' || type === 'AdwActionRow')
|
|
rows.push({ type, title: c.title, subtitle: c.subtitle });
|
|
walk(c);
|
|
}
|
|
};
|
|
walk(window);
|
|
|
|
let failures = 0;
|
|
function check(name, condition, detail = '') {
|
|
if (!condition)
|
|
failures++;
|
|
print(`${condition ? 'ok ' : 'FAIL'} ${name}${detail ? ` (${detail})` : ''}`);
|
|
}
|
|
|
|
for (const row of rows)
|
|
print(` ${row.type.replace('Adw', '').padEnd(10)} ${row.title}`);
|
|
|
|
// One control per settings key, so a key added without a row to change it is
|
|
// caught here rather than by a user wondering why nothing happens.
|
|
const keys = schemas.lookup('org.gnome.shell.extensions.claude-code-status', true)
|
|
.list_keys().length;
|
|
const controls = rows.filter(
|
|
r => r.type === 'AdwSwitchRow' || r.type === 'AdwSpinRow').length;
|
|
check('a control for every settings key', controls === keys, `${controls} of ${keys}`);
|
|
|
|
// The hook status line is the reason this page is worth opening at all: a
|
|
// silent panel looks the same whether nothing runs or nothing is installed.
|
|
const status = rows.find(r => r.title === 'Status');
|
|
check('hook status reported', !!status?.subtitle, status?.subtitle);
|
|
check('status names the events it found',
|
|
/SessionStart|Not installed/.test(status?.subtitle ?? ''), status?.subtitle);
|
|
|
|
const dir = rows.find(r => r.title === 'State directory');
|
|
check('state directory shown', (dir?.subtitle ?? '').endsWith('claude-code-status'),
|
|
dir?.subtitle);
|
|
|
|
GLib.spawn_command_line_sync(`rm -rf ${tmp}`);
|
|
print(failures ? `\n${failures} failure(s)` : '\nall passed');
|
|
imports.system.exit(failures ? 1 : 0);
|