diff --git a/.coverage b/.coverage index 494a69e..68d4746 100644 Binary files a/.coverage and b/.coverage differ diff --git a/src/cli/sync_dashboard.py b/src/cli/sync_dashboard.py index 0c69a2f..7d12c80 100644 --- a/src/cli/sync_dashboard.py +++ b/src/cli/sync_dashboard.py @@ -26,7 +26,17 @@ DEFAULT_SYNC_INTERVAL = 300 # SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"] # Alternative spinners you could use: # SPINNER_FRAMES = ["◢", "◣", "◤", "◥"] # Rotating triangle -SPINNER_FRAMES = ["▰▱▱▱▱", "▰▰▱▱▱", "▰▰▰▱▱", "▰▰▰▰▱", "▰▰▰▰▰", "▱▰▰▰▰", "▱▱▰▰▰", "▱▱▱▰▰", "▱▱▱▱▰"] # Loading bar +SPINNER_FRAMES = [ + "▰▱▱▱▱", + "▰▰▱▱▱", + "▰▰▰▱▱", + "▰▰▰▰▱", + "▰▰▰▰▰", + "▱▰▰▰▰", + "▱▱▰▰▰", + "▱▱▱▰▰", + "▱▱▱▱▰", +] # Loading bar # SPINNER_FRAMES = ["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"] # Braille dots # SPINNER_FRAMES = ["◐", "◓", "◑", "◒"] # Circle quarters # SPINNER_FRAMES = ["⠁", "⠂", "⠄", "⡀", "⢀", "⠠", "⠐", "⠈"] # Braille orbit @@ -296,6 +306,13 @@ class SyncDashboard(App): self._log_to_task("archive", "Dashboard initialized. Waiting to start sync...") self._mounted.set() + def on_unmount(self) -> None: + """Clean up when the dashboard is unmounted.""" + if self._countdown_task: + self._countdown_task.cancel() + if self._spinner_task: + self._spinner_task.cancel() + def on_list_view_selected(self, event: ListView.Selected) -> None: """Handle task selection from the list.""" if isinstance(event.item, TaskListItem): @@ -677,4 +694,13 @@ async def run_dashboard_sync(): await asyncio.sleep(1) # Run dashboard and sync loop concurrently - await asyncio.gather(dashboard.run_async(), sync_loop()) + # When dashboard exits, cancel the sync loop + sync_task = asyncio.create_task(sync_loop()) + try: + await dashboard.run_async() + finally: + sync_task.cancel() + try: + await sync_task + except asyncio.CancelledError: + pass