You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(prefs)!: organize modules into preference sections (#41)
Add section metadata to module definitions and render preferences grouped by category. Add shortcut preference support for Clipboard History and remove its default keybinding to comply with GNOME review guidance.
Move developer tooling out of the module tree, remove the shell adapter from the extension context, improve Quick Settings attachment reuse, and update tray icon deduplication, translations, tests, and credits.
BREAKING CHANGE: ModuleDefinition metadata now requires a section field, and ExtensionContext no longer exposes the shell adapter. Clipboard History no longer ships with a default shortcut; users must assign one in preferences.
Copy file name to clipboardExpand all lines: AGENTS.md
+37-17Lines changed: 37 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,35 +52,34 @@ Do not leave a task incomplete if either command reports errors or failures.
52
52
53
53
### Translation commands
54
54
55
-
-**Regenerate POT template:**`just pot` — builds then scans compiled JS (`dist/`) and rewrites the `.pot`file with all `_()` strings. Run this whenever translatable strings are added or removed.
56
-
-**Merge new strings into .po files:**`just update-po` — runs `msgmerge` on every `po/*.po`file against the current `.pot`. Run after `just pot`.
55
+
-**Regenerate POT template:**`just pot` — builds then scans compiled JS (`dist/`) and writes the `.pot`into `dist/` (a build artifact, **not** committed — avoids `POT-Creation-Date` churn). Run this whenever translatable strings are added or removed.
56
+
-**Merge new strings into .po files:**`just update-po` — depends on `pot`; regenerates the template into `dist/` then runs `msgmerge` on every `data/po/*.po` against it. The hand-translated `data/po/*.po` files are the committed source of truth.
57
57
-**Compile .mo binaries:**`just compile-mo` — compiles each `po/*.po` into `dist/locale/<lang>/LC_MESSAGES/*.mo`. Called automatically by `just build`.
58
58
59
59
## Repository Structure
60
60
61
61
-`src/` — TypeScript source root
62
62
-`extension.ts` — entry point; iterates the registry and instantiates modules via each definition's `factory`
63
-
-`module.ts` — base `Module` class (accepts `ExtensionContext`)
-`module.ts` — base `Module` class plus the shared `ModuleOption` / `ModuleMetadata` / `ModuleDefinition` types
65
64
-`registry.ts` — aggregator; imports each module's `definition` export and returns them in UI order (used by `extension.ts`)
66
-
-`prefsMetadata.ts` — pure metadata mirror for the prefs UI; cannot import modules because prefs runs in `gnome-extensions-app` (no `resource:///org/gnome/shell/*` available)
67
-
-`prefs.ts` — generic extension preferences UI driven by `prefsMetadata.ts`
65
+
-`prefsMetadata.ts` — pure metadata mirror for the prefs UI; cannot import modules because prefs runs in `gnome-extensions-app` (no `resource:///org/gnome/shell/*` available). Also exports `getSections()` (the ordered list of prefs sections)
66
+
-`prefs.ts` — generic extension preferences UI driven by `prefsMetadata.ts`; renders one `Adw.PreferencesGroup` per section
68
67
-`core/` — Clean Architecture core
69
68
-`context.ts` — `ExtensionContext` interface and implementation
70
69
-`logger.ts` — Abstracted logging
71
70
-`settings.ts` — `SettingsManager` abstraction for GSettings
-`modules/` — one **folder** per feature module, named after the module (e.g., `dock/dock.ts`); the main entry file shares the folder name
74
-
-`shared/` — shared utilities used across modules
72
+
-`dev/` — developer-only tooling (e.g., `devTool.ts`), gated behind the `AURORA_DEVTOOLS=1` env var. **Not** a feature module: it is not in the registry, prefs, or gschema, and is instantiated directly by `extension.ts`
73
+
-`shared/` — shared utilities used across modules (e.g., `quickSettings.ts`)
75
74
-`styles/` — SCSS stylesheets (compiled to light + dark CSS)
76
75
-`types/` — TypeScript type declarations (`@girs`, GJS, etc.)
77
76
-`data/` — resources files
78
77
-`schemas/` — GSettings schema XML
79
78
-`icons/` — SVG icons used in the project
80
79
-`po/` — translation files
81
80
-`tests/` — automated tests
82
-
-`unit/` — vitest unit tests (metadata, registry, schema)
83
-
-`shell/` — GNOME Shell integration test scripts (run via `gnome-shell-test-tool`)
81
+
-`unit/` — Node test-runner unit tests (`node --test` via `tsx`), auto-discovered by the `tests/unit/*.test.ts` glob — just drop a new `*.test.ts` file in here, no `package.json` edit needed. For pure logic that does not import shell internals.
82
+
-`shell/` — GNOME Shell integration test scripts (run via `gnome-shell-test-tool`) — exercise modules against a real headless GNOME Shell
84
83
-`.github/workflows/ci.yml` — CI pipeline (lint + type-check → unit tests + build → integration tests)
@@ -91,9 +90,9 @@ Do not leave a task incomplete if either command reports errors or failures.
91
90
92
91
## Architecture
93
92
94
-
1.**Dependency Injection:** Modules **must not** access global variables (like `Main` or `Gio.Settings`) directly. Instead, they receive an `ExtensionContext` in their constructor.
95
-
2.**Abstractions:**Use `this.context.settings` for configuration and `this.context.shell` for GNOME Shell environment interactions.
96
-
3.**Layering:** Keep UI logic (Clutter/St) separated from pure domain logic. Complex algorithms should be extracted into pure TypeScript files (e.g., `src/modules/dock/monitorTopology.ts`).
93
+
1.**Settings via context:** Modules receive an `ExtensionContext` in their constructor and read configuration through `this.context.settings` (the `SettingsManager` abstraction) rather than touching `Gio.Settings` directly.
94
+
2.**`Main` is fair game:**Importing `Main` (`resource:///org/gnome/shell/ui/main.js`) directly is the idiomatic GNOME-extension way and is expected — there is no shell adapter. Confidence in shell interactions comes from the `tests/shell/` integration suite running a real headless GNOME Shell, not from mocking `Main`.
95
+
3.**Layering & testability:** Keep UI logic (Clutter/St) separated from pure domain logic. Extract complex algorithms into pure TypeScript files with no shell imports (e.g., `src/modules/dock/monitorTopology.ts`, `src/modules/trayIcons/trayState.ts`) so they can be unit-tested with `node --test`. UI/shell glue is covered by integration tests instead.
97
96
4.**Metadata-Driven UI:** The preferences window is generated dynamically from `src/prefsMetadata.ts` (a hand-maintained mirror of each module's metadata, kept in parity by `tests/unit/registry.test.ts`). If a module needs options, define them in the `options` array of its `ModuleDefinition` and mirror them into `prefsMetadata.ts`.
98
97
5.**Self-Registering Modules:** Each module file exports a `definition: ModuleDefinition` co-located with its class. The factory that constructs the module lives on the definition itself — `src/registry.ts` is a pure aggregator and never references module classes directly.
99
98
@@ -105,7 +104,7 @@ Do not leave a task incomplete if either command reports errors or failures.
@@ -119,6 +118,7 @@ export class MyModule extends Module {
119
118
exportconst definition:ModuleDefinition= {
120
119
key: 'my-module',
121
120
settingsKey: 'module-my-module',
121
+
section: 'behavior', // must match an id from getSections() in prefsMetadata.ts
122
122
title: _('My Module'),
123
123
subtitle: _('Description'),
124
124
options: [
@@ -136,12 +136,13 @@ import { definition as myModule } from '~/modules/myModule/myModule.ts';
136
136
return [/* …, */myModule];
137
137
```
138
138
139
-
3. Mirror the metadata into `src/prefsMetadata.ts` (prefs cannot import modules — see the file header):
139
+
3. Mirror the metadata into `src/prefsMetadata.ts` (prefs cannot import modules — see the file header). Include the same `section`:
140
140
141
141
```typescript
142
142
{
143
143
key: 'my-module',
144
144
settingsKey: 'module-my-module',
145
+
section: 'behavior',
145
146
title: _('My Module'),
146
147
subtitle: _('Description'),
147
148
options: [
@@ -160,7 +161,26 @@ return [/* …, */ myModule];
160
161
</key>
161
162
```
162
163
163
-
`tests/unit/registry.test.ts` enforces that step 2, step 3, and step 4 stay in parity — a half-finished addition will fail CI.
164
+
`tests/unit/registry.test.ts` enforces that step 2, step 3, and step 4 stay in parity — including that every module's `section` is a known section id and matches between the registry and `prefsMetadata.ts`. A half-finished addition will fail CI.
165
+
166
+
### Prefs sections
167
+
168
+
The prefs window groups modules by `section`. The ordered section list lives in `getSections()` in `src/prefsMetadata.ts`:
169
+
170
+
```typescript
171
+
exportfunction getSections():ModuleSection[] {
172
+
return [
173
+
{ id: 'dock-panel', title: _('Dock & Panel') },
174
+
// …
175
+
];
176
+
}
177
+
```
178
+
179
+
To add a new section, append a `{ id, title }` entry here (the array order is the on-screen group order), then reference its `id` from a module's `section`. A module whose `section` matches no known id falls into a defensive "Other" group at the bottom.
180
+
181
+
### Clipboard shortcuts
182
+
183
+
Per the GNOME review guidelines, clipboard-related keyboard shortcuts must not ship with a default. The Clipboard History `clipboard-history-shortcut` key defaults to `[]`; users assign it via the `type: 'shortcut'` row in prefs. Keep any future clipboard shortcuts unset by default.
164
184
165
185
## Coding Standards
166
186
@@ -169,7 +189,7 @@ return [/* …, */ myModule];
169
189
- Private members: `_prefixed`
170
190
- Constants: `UPPER_CASE`
171
191
- Keep `enable()` and `disable()` symmetric.
172
-
-**Strictly follow Dependency Injection.** No direct imports of `gi://Shell`, `Main`, etc., inside module domain logic.
192
+
-Read settings through `this.context.settings`. Importing `Main`/`Shell`/`St` directly is fine — keep heavy algorithms in shell-free pure files so they stay unit-testable.
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -133,7 +133,9 @@ Maintenance branches are created automatically when the first tag for a new majo
133
133
134
134
### New features
135
135
136
-
New features land on `main` and are released alongside a new major GNOME Shell version. **Do not add new features to maintenance branches** — they are strictly for bug fixes.
136
+
Each major Aurora Shell release targets a single GNOME Shell version. New features land on `main` and are released alongside a new major GNOME Shell version.
137
+
138
+
Branches targeting already-released GNOME Shell versions are in maintenance mode. **Do not add new features to maintenance branches** — they are strictly for bug fixes and compatibility updates.
Aurora Shell stands on the work of the wider GNOME community. This file records the projects and people whose work made parts of this extension possible.
4
+
5
+
## Bluetooth-Battery-Meter
6
+
7
+
The animated Bluetooth icons used by the **Bluetooth Menu** module come from
Copy file name to clipboardExpand all lines: README.md
+13Lines changed: 13 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,10 @@
6
6
7
7
A modular GNOME Shell extension that adds quality-of-life features missing in vanilla GNOME.
8
8
9
+
> **Project goal:** Aurora Shell is a proving ground. Over time, the aim is for some of its
10
+
> features to mature and make their way upstream into GNOME Shell itself. Modules here are
11
+
> meant to be useful on their own today, and good candidates for upstream tomorrow.
12
+
9
13
## Modules
10
14
11
15
Aurora is split into independent modules, so you can enable only what you want.
@@ -63,3 +67,12 @@ just toolbox-run
63
67
## Contributing
64
68
65
69
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for information on project architecture, code style, and step-by-step instructions on how to add a new module.
70
+
71
+
## Credits & Acknowledgements
72
+
73
+
Aurora Shell builds on the work of the wider GNOME community. Special thanks to:
74
+
75
+
-[**maniacx/Bluetooth-Battery-Meter**](https://github.com/maniacx/Bluetooth-Battery-Meter) the animated Bluetooth icons used by the Bluetooth Menu module come from this project.
76
+
-[**swsnr/gnome-shell-extension-xwayland-indicator**](https://codeberg.org/swsnr/gnome-shell-extension-xwayland-indicator/) the inspiration behind the XWayland Indicator module.
77
+
78
+
See [CREDITS.md](CREDITS.md) for the full list of attributed work.
0 commit comments