Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,8 +949,18 @@ def _make_personas(self):
self._persona_box.show_all()

def _kokoro_voice_changed_event_cb(self, widget, event, voice_name):
# Remove previously shown status label to avoid stacking labels when
# users rapidly click different voices.
existing_label = getattr(self, '_kokoro_info_label', None)
if existing_label is not None:
try:
self._kokoro_voice_box.remove(existing_label)
except Exception:
pass
Comment on lines +952 to +959
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid except Exception: pass when removing the prior Kokoro status label. It can silently mask real widget hierarchy/GTK errors and can also leave the old label in the box (so stacking may still occur) without any diagnostic. Prefer checking existing_label.get_parent() is self._kokoro_voice_box (or membership in get_children()) before removing, and only catch the specific GTK/Python exceptions you expect (optionally log at debug level).

Copilot uses AI. Check for mistakes.

# Show info label(Indication of voice changing) upon click
info_label = Gtk.Label()
self._kokoro_info_label = info_label
info_label.set_markup('<span foreground="blue" size="large">%s</span>' % _('Please wait...'))
self._kokoro_voice_box.pack_start(info_label, False, False, style.DEFAULT_PADDING)
info_label.show()
Expand Down Expand Up @@ -1001,7 +1011,13 @@ def async_check_and_update():
Gtk.main_iteration()

def _remove_info_label():
self._kokoro_voice_box.remove(info_label)
if getattr(self, '_kokoro_info_label', None) is info_label:
try:
self._kokoro_voice_box.remove(info_label)
except Exception:
pass
self._kokoro_info_label = None
return False
Comment on lines +1014 to +1020
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In _remove_info_label, swallowing all exceptions and then setting _kokoro_info_label = None can make failures hard to detect and can leave a label stuck in the UI with no remaining reference to remove it later. Prefer guarding the removal (e.g., verify the label is still parented to _kokoro_voice_box), catching only expected exceptions, and only clearing _kokoro_info_label once the label is confirmed removed/destroyed.

Copilot uses AI. Check for mistakes.
GLib.timeout_add(3000, _remove_info_label)

GLib.idle_add(async_check_and_update)
Expand Down Expand Up @@ -1364,10 +1380,21 @@ def safe_face_say():
llm_thread.start()
else:
# No internet, try SLM -> Brain
response = self._try_slm_response(text)
if not response:
response = brain.respond(text)
self.face.say(response)
self.face.say("Thinking...")

def fetch_offline_response():
response = self._try_slm_response(text)
if not response:
response = brain.respond(text)

def safe_face_say():
self.face.say(response)
return False
GLib.idle_add(safe_face_say)

offline_thread = threading.Thread(target=fetch_offline_response)
offline_thread.daemon = True
offline_thread.start()
else:
# Use traditional brain chatbot
brain_response = brain.respond(text)
Expand Down
Loading