Skip to content

Commit 1f29acb

Browse files
authored
refactor: Inicial structure for mobile and initial support for gsify (#52)
* refactor: prepare shell for mobile targets Group modules by feature area instead of a flat modules tree. Add runtime target detection so desktop-only features can stay out of future mobile sessions. Keep GJSify as an experimental separate build path with readable module output for review. * feat(clipboard): enhance clipboard history functionality with sample actions and clear history option feat(styles): update clipboard history styles for improved UI consistency test(clipboard): add unit tests for clipboard log operations and positioning test(ui): implement tests for clipboard panel layout and actions fix(dash): handle potential errors in dash container positioning and actions
1 parent 342cb6a commit 1f29acb

83 files changed

Lines changed: 5699 additions & 868 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ node_modules/
1212

1313
# Build output
1414
dist/
15+
dist-gjsify/
16+
dist-gjsify-probe/
1517

1618
# npm (legacy)
1719
package-lock.json
@@ -36,4 +38,8 @@ Thumbs.db
3638
.vagrant/
3739
.docs/
3840
docs/
39-
.superpowers/
41+
.superpowers/
42+
43+
# IA Stuff
44+
.agents/
45+
skills-lock.json

AGENTS.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,23 @@ Do not leave a task incomplete if either command reports errors or failures.
6464

6565
- `src/` — TypeScript source root
6666
- `extension.ts` — entry point; iterates the registry and instantiates modules via each definition's `factory`
67-
- `module.ts` — base `Module` class plus the shared `ModuleOption` / `ModuleMetadata` / `ModuleDefinition` types
67+
- `module.ts` — base `Module` class plus the shared `ModuleOption` / `ModuleMetadata` / `ModuleDefinition` / runtime policy types
6868
- `registry.ts` — aggregator; imports each module's `definition` export and returns them in UI order (used by `extension.ts`)
6969
- `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)
7070
- `prefs.ts` — generic extension preferences UI driven by `prefsMetadata.ts`; renders one `Adw.PreferencesGroup` per section
7171
- `core/` — Clean Architecture core
7272
- `context.ts``ExtensionContext` interface and implementation
7373
- `logger.ts` — Abstracted logging
7474
- `settings.ts``SettingsManager` abstraction for GSettings
75-
- `modules/` — feature modules registered by `registry.ts`
76-
- regular modules use one **folder** per feature module, named after the module (e.g., `dock/dock.ts`); the main entry file shares the folder name
75+
- feature modules are grouped by semantic area instead of a single `modules/` root:
76+
- `dock/` — dock module and dock-specific helpers
77+
- `panel/` — GNOME panel and Quick Settings integrations
78+
- `desktop/` — desktop-only modules such as tray icons
79+
- `patches/` — focused Shell behavior patches and monkey-patches
80+
- `theme/` — theme and color-scheme modules
81+
- `privacy/` — privacy and screen-sharing behavior
82+
- `clipboard/` — clipboard history module and UI
83+
- `device/` — runtime target and hardware capability detection for future mobile work
7784
- `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`
7885
- `shared/` — shared utilities used across modules (e.g., `quickSettings.ts`)
7986
- `styles/` — SCSS stylesheets (compiled to light + dark CSS)
@@ -97,13 +104,13 @@ Do not leave a task incomplete if either command reports errors or failures.
97104

98105
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.
99106
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`.
100-
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.
107+
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/dock/monitorTopology.ts`, `src/desktop/trayIcons/trayState.ts`) so they can be unit-tested with `node --test`. UI/shell glue is covered by integration tests instead.
101108
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`.
102109
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.
103110

104111
## Adding a Module
105112

106-
1. Create `src/modules/myModule/myModule.ts` with a `Module` subclass **and** a co-located `definition` export. Regular modules **must** live in their own folder named after the module (e.g., `dock/dock.ts`, `panel/panel.ts`).
113+
1. Create a module in the appropriate semantic area with a `Module` subclass **and** a co-located `definition` export. Single-file patches can live directly in `src/patches/`; complex modules should use a feature folder such as `src/panel/myModule/myModule.ts`.
107114

108115
```typescript
109116
import { gettext as _ } from 'gettext';
@@ -126,6 +133,7 @@ export const definition: ModuleDefinition = {
126133
section: 'behavior', // must match an id from getSections() in prefsMetadata.ts
127134
title: _('My Module'),
128135
subtitle: _('Description'),
136+
runtime: { targets: ['desktop'] }, // optional; omitted modules default to desktop-only
129137
options: [
130138
{ key: 'my-option', title: _('Option'), subtitle: _('Desc'), type: 'switch' },
131139
],
@@ -136,7 +144,7 @@ export const definition: ModuleDefinition = {
136144
2. Register the definition in `src/registry.ts` (one import + one array entry, preserving UI order):
137145

138146
```typescript
139-
import { definition as myModule } from '~/modules/myModule/myModule.ts';
147+
import { definition as myModule } from '~/patches/myModule.ts';
140148
// …inside getModuleRegistry():
141149
return [/* …, */ myModule];
142150
```

ARCHITECTURE.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ flowchart TD
1111
Shell[GNOME Shell] --> Extension[src/extension.ts]
1212
Extension --> Context[src/core/context.ts]
1313
Extension --> Registry[src/registry.ts]
14-
Registry --> Modules[src/modules/*]
14+
Registry --> Modules[semantic module folders]
1515
Modules --> Shared[src/shared/*]
1616
Modules --> Core[src/core/*]
17+
Context --> Device[src/device/*]
1718
Prefs[src/prefs.ts] --> PrefsMetadata[src/prefsMetadata.ts]
1819
PrefsMetadata -. mirrors .-> Registry
1920
Schema[data/schemas/*.xml] -. validates settings .-> Registry
@@ -26,11 +27,17 @@ flowchart TD
2627
```text
2728
src/
2829
core/ Extension context, settings, and logging
30+
clipboard/ Clipboard history module and UI
31+
desktop/ Desktop-only modules such as tray icons
2932
dev/ Developer-only tools
30-
modules/ Feature modules registered in the extension
31-
... One folder per regular Aurora module
33+
device/ Runtime target and hardware capability detection
34+
dock/ Dock module and dock-specific helpers
35+
panel/ GNOME panel and Quick Settings integrations
36+
patches/ Focused Shell behavior patches and monkey-patches
37+
privacy/ Privacy and screen-sharing behavior
3238
shared/ Utilities shared by modules
3339
styles/ SCSS partials compiled into Shell stylesheets
40+
theme/ Theme and color-scheme modules
3441
```
3542

3643
## Runtime Lifecycle
@@ -80,13 +87,15 @@ classDiagram
8087
+title string
8188
+subtitle string
8289
+options ModuleOption[]
90+
+runtime ModuleRuntimePolicy
8391
+factory(context) Module
8492
}
8593
8694
class ExtensionContext {
8795
+uuid string
8896
+path string
8997
+settings SettingsManager
98+
+device DeviceService
9099
}
91100
92101
ModuleDefinition --> Module : creates
@@ -97,6 +106,11 @@ Each module owns its runtime behavior and cleanup. `enable()` and `disable()` mu
97106
actors, signal handlers, timeouts, D-Bus watches, and injected Shell UI must be removed by the same
98107
module that created them.
99108

109+
`ModuleDefinition.runtime` is optional. When omitted, the module is treated as desktop-only. Use
110+
`targets: ['shared']` only for modules that are intentionally valid on both desktop and future
111+
mobile runtimes. Hardware-specific modules should declare `requires` capabilities instead of
112+
probing and failing late inside `enable()`.
113+
100114
## Registry And Preferences
101115

102116
Every registry module must stay in sync across:

CONTRIBUTING.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,35 @@ graph TD
1313
1414
A["extension.ts"] -->|Injects| B["ExtensionContext"]:::core
1515
B -->|Provides| C["SettingsManager"]:::core
16-
B -->|Provides| D["ShellEnvironment"]:::adapter
16+
B -->|Provides| D["DeviceService"]:::adapter
1717
1818
E["Module"]:::core -->|uses| B
1919
20-
M["modules/*.ts<br/>(class + definition)"]:::core -->|definition export| F["registry.ts"]:::core
20+
M["semantic folders<br/>(class + definition)"]:::core -->|definition export| F["registry.ts"]:::core
2121
F -->|Definitions + factory| A
2222
P["prefsMetadata.ts"]:::core -->|Metadata mirror| G["prefs.ts (Generic UI)"]
2323
```
2424

25-
1. **Dependency Injection:** `extension.ts` instantiates an `ExtensionContext` and injects it into every module. **Modules must never use GNOME Shell globals (like `Main`, `Gio.Settings`) directly.**
25+
1. **Dependency Injection:** `extension.ts` instantiates an `ExtensionContext` and injects it into every module. Modules read Aurora settings through `this.context.settings`; direct imports of GNOME Shell APIs such as `Main` are expected for Shell UI integration.
2626
2. **Abstractions:**
2727
- Use `this.context.settings` to interact with GSettings.
28-
- Use `this.context.shell` for Shell-wide status (e.g., startup check, overview).
29-
- This allows for easier mocking during unit tests.
28+
- Use `this.context.device` for runtime target and hardware capabilities.
29+
- Keep pure logic outside Shell imports when it needs unit coverage.
3030
3. **Layering:** Separate UI orchestration (Clutter actors) from pure business logic. Complex logic should be extracted into standalone TypeScript functions or classes.
3131
4. **Self-Registering Modules:** Each module file exports a `definition: ModuleDefinition` co-located with its class, including the factory that constructs it. `src/registry.ts` is a pure aggregator — it imports every `definition` and returns them in UI order. `extension.ts` iterates the registry and calls `def.factory(ctx)` directly; no central factory map exists.
3232
5. **Metadata-Driven Preferences:** The preferences UI is generated dynamically from `src/prefsMetadata.ts`, a hand-maintained metadata mirror. Prefs cannot import `registry.ts` because it runs in `gnome-extensions-app` (GTK/Adw), which cannot resolve `resource:///org/gnome/shell/*` imports pulled in transitively by module classes. Parity between `registry.ts`, `prefsMetadata.ts`, and the GSettings schema is enforced by `tests/unit/registry.test.ts`.
3333

3434
## Adding a Module
3535

36-
1. Create `src/modules/myModule/myModule.ts` with a `Module` subclass **and** a co-located `definition` export. Every module **must** live in its own folder named after the module (e.g., `dock/dock.ts`, `trayIcons/trayIcons.ts`). For complex modules, split supporting logic into sibling files inside that folder (e.g., `trayIcons/sniHost.ts`, `trayIcons/trayContainer.ts`):
36+
1. Choose the semantic source area, then create a `Module` subclass **and** a co-located `definition` export. Single-file modules can live directly in their area, for example `src/patches/myPatch.ts`; complex modules should use a subfolder, for example `src/panel/myPanelFeature/myPanelFeature.ts`.
37+
38+
Current source areas are `dock`, `panel`, `desktop`, `patches`, `theme`, `privacy`, and `clipboard`. Use `desktop` for desktop-only features such as tray icons. Add future hardware probes under `device`, not inside feature modules.
3739

3840
```typescript
3941
import { gettext as _ } from 'gettext';
4042

4143
import type { ExtensionContext } from '~/core/context.ts';
42-
import type { ModuleDefinition } from '~/moduleDefinition.ts';
44+
import type { ModuleDefinition } from '~/module.ts';
4345
import { Module } from '~/module.ts';
4446

4547
export class MyModule extends Module {
@@ -59,8 +61,10 @@ export class MyModule extends Module {
5961
export const definition: ModuleDefinition = {
6062
key: 'my-module',
6163
settingsKey: 'module-my-module',
64+
section: 'behavior',
6265
title: _('My Module'),
6366
subtitle: _('Description'),
67+
runtime: { targets: ['desktop'] },
6468
options: [
6569
// (Optional) add sub-settings here
6670
{ key: 'my-sub-key', title: _('Sub Setting'), subtitle: _('...'), type: 'switch' },
@@ -72,7 +76,7 @@ export const definition: ModuleDefinition = {
7276
2. Register the definition in `src/registry.ts` — one import line plus one array entry (preserve UI order):
7377

7478
```typescript
75-
import { definition as myModule } from '~/modules/myModule/myModule.ts';
79+
import { definition as myModule } from '~/patches/myPatch.ts';
7680

7781
export function getModuleRegistry(): ModuleDefinition[] {
7882
return [
@@ -88,6 +92,7 @@ export function getModuleRegistry(): ModuleDefinition[] {
8892
{
8993
key: 'my-module',
9094
settingsKey: 'module-my-module',
95+
section: 'behavior',
9196
title: _('My Module'),
9297
subtitle: _('Description'),
9398
options: [

0 commit comments

Comments
 (0)