Branding
Rolling release / release (push) Successful in 6m57s

This commit is contained in:
2026-09-12 14:06:02 -04:00
parent 0e52942b8b
commit 18802cb55d
23 changed files with 459 additions and 39 deletions
@@ -14,7 +14,8 @@ import { ConversationView, JarvisOsd, ComputerUseChrome, SessionPanel, coerceTex
const BUS = 'io.qvac.Jarvis';
const PATH = '/io/qvac/Jarvis';
const IFACE = 'io.qvac.Jarvis.Session';
const GLYPHS = { ARMED: '◯', LISTENING: '◌', THINKING: '◉', SPEAKING: '◎', SLEEPING: '◐' };
const DEFAULT_ACCENT = '#F4B942';
const SIGNAL = '#4FD2FF';
class JarvisProxy {
async connect() {
@@ -55,17 +56,23 @@ export default class JarvisExtension extends Extension {
this._theme = St.ThemeContext.get_for_stage(global.stage).get_theme(); this._stylesheet = Gio.File.new_for_path(`${this.path}/stylesheet.css`); try { this._theme.load_stylesheet(this._stylesheet); } catch (error) { log(`Jarvis stylesheet unavailable: ${error.message}`); }
this.settings = this.getSettings();
this.proxy = new JarvisProxy();
this.popup = new ConversationView({ compact: true });
this.popup = new ConversationView({ compact: true, brandDir: this.path });
this.osd = new JarvisOsd();
this.cu = new ComputerUseChrome(); this.cu.attach();
this.session = new SessionPanel(); this.session.attach();
this.session = new SessionPanel({ brandDir: this.path }); this.session.attach();
this._bindSurface(this.popup);
this._bindSurface(this.session.view);
this._applyAccessibility();
this._removeShellService = installShellService();
this._indicator = new PanelMenu.Button(0.0, 'Jarvis QVAC', false); this._indicator.accessible_name = 'Jarvis voice assistant';
this._panelBox = new St.BoxLayout({ style_class: 'jarvis-panel-box', y_align: Clutter.ActorAlign.CENTER });
this._glyph = new St.Label({ text: '◯ Jarvis', style_class: 'jarvis-panel-glyph', y_align: Clutter.ActorAlign.CENTER }); this._glyph.accessible_name = 'Jarvis idle';
this._mark = new St.Icon({ icon_name: 'audio-input-microphone-symbolic', icon_size: 16, style_class: 'jarvis-panel-mark', y_align: Clutter.ActorAlign.CENTER });
try {
const file = Gio.File.new_for_path(`${this.path}/brand/icons/jarvis-mark.svg`);
if (file.query_exists(null)) this._mark.gicon = new Gio.FileIcon({ file });
} catch (error) { log(`Jarvis mark unavailable: ${error.message}`); }
this._glyph = new St.Label({ text: 'Jarvis', style_class: 'jarvis-panel-glyph', y_align: Clutter.ActorAlign.CENTER }); this._glyph.accessible_name = 'Jarvis idle';
this._panelBox.add_child(this._mark);
this._panelBox.add_child(this._glyph);
this.osd.attach(this._panelBox);
this._indicator.add_child(this._panelBox);
@@ -264,17 +271,27 @@ export default class JarvisExtension extends Extension {
}
_setState(state) {
const value = safeText(state);
this._glyph.text = `${GLYPHS[value] || '◯'} Jarvis`;
this._glyph.text = 'Jarvis';
this._glyph.accessible_name = `Jarvis ${value.toLowerCase()}`;
this._indicator.accessible_name = `Jarvis ${value.toLowerCase()}`;
if (this._panelBox) {
for (const name of ['armed', 'listening', 'speaking', 'thinking', 'sleeping']) {
this._panelBox.remove_style_class_name(`jarvis-state-${name}`);
}
this._panelBox.add_style_class_name(`jarvis-state-${value.toLowerCase()}`);
}
this._eachView((view) => view.setState(value));
this.osd.setState(value);
}
_applyAccent() {
const style = `--jarvis-accent: ${this.settings.get_string('accent-color')};`;
const color = this.settings.get_string('accent-color');
const accent = /^#[0-9A-Fa-f]{6}$/.test(String(color || '')) ? color : DEFAULT_ACCENT;
const style = `--jarvis-accent: ${accent}; --jarvis-signal: ${SIGNAL};`;
this.popup.root.set_style(style);
this.session.root.set_style(style);
this.osd.root.set_style(style);
this.cu.root.set_style(style);
this._panelBox?.set_style(style);
}
_applyAccessibility() {
try {
@@ -300,7 +317,7 @@ export default class JarvisExtension extends Extension {
this.osd?.destroy(); this.cu?.destroy(); this.session?.destroy(); this.popup?.destroy();
this._indicator?.destroy();
if (this._theme && this._stylesheet) { try { this._theme.unload_stylesheet(this._stylesheet); } catch {} }
this.popup = this.session = this.osd = this.cu = this._indicator = this._glyph = this.proxy = null;
this.popup = this.session = this.osd = this.cu = this._indicator = this._glyph = this._mark = this.proxy = null;
}
}