Add ctx.ui.setFooter() for extensions to replace footer component

Extensions can now replace the built-in footer with a custom component:
- setFooter(factory) replaces with custom component
- setFooter(undefined) restores built-in footer

Includes example extension demonstrating context usage display.

Closes #481
This commit is contained in:
Mario Zechner 2026-01-06 12:31:46 +01:00
parent 2bc445498a
commit f023af0dab
11 changed files with 147 additions and 1 deletions

View file

@ -157,6 +157,9 @@ export class InteractiveMode {
private extensionWidgets = new Map<string, Component & { dispose?(): void }>();
private widgetContainer!: Container;
// Custom footer from extension (undefined = use built-in footer)
private customFooter: (Component & { dispose?(): void }) | undefined = undefined;
// Convenience accessors
private get agent() {
return this.session.agent;
@ -646,6 +649,35 @@ export class InteractiveMode {
this.ui.requestRender();
}
/**
* Set a custom footer component, or restore the built-in footer.
*/
private setExtensionFooter(factory: ((tui: TUI, thm: Theme) => Component & { dispose?(): void }) | undefined): void {
// Dispose existing custom footer
if (this.customFooter?.dispose) {
this.customFooter.dispose();
}
// Remove current footer from UI
if (this.customFooter) {
this.ui.removeChild(this.customFooter);
} else {
this.ui.removeChild(this.footer);
}
if (factory) {
// Create and add custom footer
this.customFooter = factory(this.ui, theme);
this.ui.addChild(this.customFooter);
} else {
// Restore built-in footer
this.customFooter = undefined;
this.ui.addChild(this.footer);
}
this.ui.requestRender();
}
/**
* Create the ExtensionUIContext for extensions.
*/
@ -657,6 +689,7 @@ export class InteractiveMode {
notify: (message, type) => this.showExtensionNotify(message, type),
setStatus: (key, text) => this.setExtensionStatus(key, text),
setWidget: (key, content) => this.setExtensionWidget(key, content),
setFooter: (factory) => this.setExtensionFooter(factory),
setTitle: (title) => this.ui.terminal.setTitle(title),
custom: (factory) => this.showExtensionCustom(factory),
setEditorText: (text) => this.editor.setText(text),