✨ feat(panel): improve recording indicator reliability and timer accuracy

This commit is contained in:
sankalp committed 2025-07-31 23:19:40 +05:45
1 parent 8a2efa3b5a
commit d7287e50d4
1 file changed
+156 -38
+156 -38
View File
@@ -1,3 +1,4 @@
import os
import subprocess
import time
@@ -9,8 +10,6 @@ from fabric.widgets.button import Button
from fabric.widgets.label import Label
from fabric.widgets.svg import Svg
# FIX: Make the timer consistent with the recording start time
class RecordingIndicator(Button):
def __init__(self, **kwargs):
@@ -18,6 +17,13 @@ class RecordingIndicator(Button):
self.script_path = get_relative_path("../../../scripts/screen-capture.sh")
self.recording_start_time = None
self.last_process_check = 0
self.process_check_interval = 1.0
self.timer_update_interval = 1000
self.status_check_interval = 2000
self.timer_timeout_id = None
self.status_timeout_id = None
self.recording_icon = Svg(
name="indicators-icon",
@@ -41,69 +47,181 @@ class RecordingIndicator(Button):
self.add(self.recording_box)
self.connect("clicked", self.on_stop_recording)
self.connect("button-press-event", self.on_button_press)
self.hide()
GLib.timeout_add(1, self._delayed_init)
GLib.timeout_add(100, self._delayed_init)
def check_recording_status(self):
def on_button_press(self, *args):
GLib.timeout_add(100, lambda: self.remove_style_class("pressed") or False)
return False
def is_wf_recorder_running(self):
try:
result = subprocess.run(
[self.script_path, "status"], capture_output=True, text=True, timeout=2
["pgrep", "-x", "wf-recorder"],
capture_output=True,
text=True,
timeout=1,
)
is_recording = result.stdout.strip() == "true"
return result.returncode == 0
except Exception:
return False
def check_recording_status(self):
current_time = time.time()
self.last_process_check = current_time
try:
is_recording = self.is_wf_recorder_running()
if is_recording:
if not self.get_visible():
self.show()
self.set_visible(True)
if self.timer_timeout_id is None:
self.timer_timeout_id = GLib.timeout_add(
self.timer_update_interval, self.update_timer_display
)
# Get the recording start time if we don't have it
if self.recording_start_time is None:
self.recording_start_time = self.get_recording_start_time()
# Update the recording time display
if self.recording_start_time:
elapsed_seconds = int(time.time() - self.recording_start_time)
minutes = elapsed_seconds // 60
seconds = elapsed_seconds % 60
time_text = f"{minutes:02d}:{seconds:02d}"
self.time_label.set_markup(time_text)
self.set_tooltip_text(
f"Recording in progress ({minutes:02d}:{
seconds:02d}) - Click to stop"
)
else:
self.set_tooltip_text("Recording in progress - Click to stop")
self.update_timer_display()
else:
if self.get_visible():
self.hide()
self.recording_start_time = None
self.set_visible(False)
self.cleanup_recording_state()
except Exception:
# If we can't check status, hide the indicator
except Exception as e:
print(f"[DEBUG] Error checking recording status: {e}")
if self.get_visible():
self.hide()
self.recording_start_time = None
self.set_visible(False)
self.cleanup_recording_state()
return True # Continue the timeout
return True
def update_timer_display(self):
if not self.get_visible() or self.recording_start_time is None:
return False
try:
elapsed_seconds = int(time.time() - self.recording_start_time)
minutes = elapsed_seconds // 60
seconds = elapsed_seconds % 60
time_text = f"{minutes:02d}:{seconds:02d}"
self.time_label.set_markup(time_text)
self.set_tooltip_text(
f"Recording in progress ({time_text}) - Click to stop"
)
return True
except Exception as e:
print(f"[DEBUG] Error updating timer display: {e}")
return False
def cleanup_recording_state(self):
self.recording_start_time = None
if self.timer_timeout_id:
GLib.source_remove(self.timer_timeout_id)
self.timer_timeout_id = None
def get_recording_start_time(self):
"""Get the recording start time from the file"""
start_time_file = "/tmp/recording_start_time.txt"
try:
with open("/tmp/recording_start_time.txt", "r") as f:
return float(f.read().strip())
except Exception:
return None
if not os.path.exists(start_time_file):
return None
file_mtime = os.path.getmtime(start_time_file)
with open(start_time_file, "r") as f:
content = f.read().strip()
if content:
recorded_time = float(content)
current_time = time.time()
if abs(recorded_time - current_time) > 3600:
return file_mtime
return recorded_time
else:
return file_mtime
except (ValueError, OSError):
try:
return os.path.getmtime(start_time_file)
except OSError:
return None
def on_stop_recording(self, *args):
try:
subprocess.Popen([self.script_path, "record", "stop"])
except Exception as e:
print(f"Error stopping recording: {e}")
self.set_visible(False)
self.cleanup_recording_state()
def send_stop_command():
try:
subprocess.Popen(
[self.script_path, "record", "stop"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
except Exception as e:
print(f"[DEBUG] Error sending stop command: {e}")
GLib.idle_add(send_stop_command)
GLib.timeout_add(500, self._verify_recording_stopped)
GLib.timeout_add(1500, self._verify_recording_stopped)
GLib.timeout_add(3000, self._verify_recording_stopped)
except Exception:
self.set_visible(False)
self.cleanup_recording_state()
def _verify_recording_stopped(self):
try:
if self.is_wf_recorder_running():
if self.recording_start_time is None:
self.recording_start_time = self.get_recording_start_time()
if self.recording_start_time:
self.set_visible(True)
self.update_timer_display()
if self.timer_timeout_id is None:
self.timer_timeout_id = GLib.timeout_add(
self.timer_update_interval, self.update_timer_display
)
else:
self.set_visible(False)
self.cleanup_recording_state()
except Exception:
self.set_visible(False)
self.cleanup_recording_state()
return False
def _delayed_init(self):
try:
self.check_recording_status()
self.timeout_id = GLib.timeout_add(5000, self.check_recording_status)
self.status_timeout_id = GLib.timeout_add(
self.status_check_interval, self.check_recording_status
)
except Exception as e:
print(f"[DEBUG] Error in delayed recording indicator init: {e}")
return False # Don't repeat this timeout
return False
def destroy(self):
if self.timer_timeout_id:
GLib.source_remove(self.timer_timeout_id)
self.timer_timeout_id = None
if self.status_timeout_id:
GLib.source_remove(self.status_timeout_id)
self.status_timeout_id = None
super().destroy()