@@ -66,6 +66,8 @@ export default class JarvisExtension extends Extension {
|
||||
this._applyAccessibility();
|
||||
this._removeShellService = installShellService();
|
||||
this._assistantName = 'Jarvis';
|
||||
this._muted = false;
|
||||
this._muteTouched = false;
|
||||
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._mark = new St.Icon({ icon_name: 'audio-input-microphone-symbolic', icon_size: 16, style_class: 'jarvis-panel-mark', y_align: Clutter.ActorAlign.CENTER });
|
||||
@@ -84,14 +86,14 @@ export default class JarvisExtension extends Extension {
|
||||
this._mountPopup();
|
||||
this._indicator.connect('button-press-event', (_actor, event) => {
|
||||
const button = event.get_button();
|
||||
if (button === 2) { this._call('Arm'); return Clutter.EVENT_STOP; }
|
||||
if (button === 2) { if (!this._muted) this._call('SetListening', '(b)', [true]); return Clutter.EVENT_STOP; }
|
||||
return Clutter.EVENT_PROPAGATE;
|
||||
});
|
||||
this._keyName = 'hotkey';
|
||||
try {
|
||||
Main.wm.addKeybinding(this._keyName, this.settings, Meta.KeyBindingFlags.NONE, Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW, () => {
|
||||
this._openPopup();
|
||||
this._call('Arm');
|
||||
if (!this._muted) this._call('SetListening', '(b)', [true]);
|
||||
});
|
||||
} catch (error) { log(`Jarvis hotkey unavailable: ${error.message}`); }
|
||||
this._settingsChanged = this.settings.connect('changed::accent-color', () => this._applyAccent());
|
||||
@@ -102,7 +104,14 @@ export default class JarvisExtension extends Extension {
|
||||
try { this._lockChanged = Main.screenShield.connect('locked-changed', () => { if (Main.screenShield.locked) { this._closeShell(); this._call('ComputerRevoke'); } }); } catch {}
|
||||
}
|
||||
_bindSurface(view) {
|
||||
view.onTalk = (pressed) => { if (pressed) { this._call('PushToTalk', '(b)', [true]); this._call('Arm'); } else { this._call('PushToTalk', '(b)', [false]); } };
|
||||
view.onTalk = (pressed) => { if (this._muted) return; if (pressed) this._call('SetListening', '(b)', [true]); else this._call('SetListening', '(b)', [false]); };
|
||||
view.onListen = () => { if (this._muted) return; this._call('SetListening', '(b)', [view._state !== 'LISTENING']); };
|
||||
view.onMute = (muted) => {
|
||||
this._muted = Boolean(muted);
|
||||
this._muteTouched = true;
|
||||
this._eachView((surface) => surface.setMuted(this._muted));
|
||||
this._call('SetMuted', '(b)', [this._muted]);
|
||||
};
|
||||
view.onStop = () => this._call('Cancel');
|
||||
view.onReset = () => { this._eachView((surface) => { surface.clear(); surface.setNotice('New conversation'); }); this._call('ResetContext'); };
|
||||
view.onAsk = (text) => { this._eachView((surface) => surface.addRow('U', text)); this._call('Ask', '(s)', [text]); };
|
||||
@@ -257,9 +266,12 @@ export default class JarvisExtension extends Extension {
|
||||
const voice = status.voice;
|
||||
this._eachView((view) => view.setConnectionStatus(voice ? 'local' : 'voice-unavailable'));
|
||||
if (voice) {
|
||||
const input = Boolean(voice.capture);
|
||||
const remoteMuted = Boolean(voice.muted ?? status.muted);
|
||||
if (!this._muteTouched) this._muted = remoteMuted;
|
||||
const muted = Boolean(this._muted);
|
||||
const input = Boolean(voice.capture) || muted;
|
||||
const tts = Boolean(voice.tts || voice.speech);
|
||||
this._eachView((view) => view.setVoiceStatus({ tts, input, wake: voice.wake }));
|
||||
this._eachView((view) => view.setVoiceStatus({ tts, input, wake: muted ? false : voice.wake, muted }));
|
||||
}
|
||||
const name = status.settings?.assistantName;
|
||||
if (name) this._applyAssistantName(name);
|
||||
@@ -267,13 +279,13 @@ export default class JarvisExtension extends Extension {
|
||||
}
|
||||
_call(name, signature, value) {
|
||||
if (!this.proxy?.owned?.()) {
|
||||
if (name !== 'PushToTalk') this._eachView((view) => view.setNotice(`${this._assistantName || 'Jarvis'} is starting…`));
|
||||
if (name !== 'PushToTalk' && name !== 'SetMuted' && name !== 'SetListening') this._eachView((view) => view.setNotice(`${this._assistantName || 'Jarvis'} is starting…`));
|
||||
this._connectDaemon();
|
||||
return;
|
||||
}
|
||||
this.proxy.call(name, signature, value).catch((error) => {
|
||||
log(`Jarvis ${name}: ${error.message}`);
|
||||
if (name === 'PushToTalk') return;
|
||||
if (name === 'PushToTalk' || name === 'SetMuted' || name === 'SetListening') return;
|
||||
const fallback = name === 'ResetContext' ? 'Could not reset conversation' : `${name} failed: ${shortError(error.message)}`;
|
||||
this._eachView((view) => view.setNotice(fallback));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user