diff --git a/src/ui/backup_ops.py b/src/ui/backup_ops.py index ad0c5d9..f93a634 100644 --- a/src/ui/backup_ops.py +++ b/src/ui/backup_ops.py @@ -10,6 +10,7 @@ import logging import traceback from pathlib import Path from datetime import datetime +from typing import Any, Optional, Union, List, Dict, Callable logger = logging.getLogger(__name__) @@ -36,7 +37,9 @@ class BackupPane(Container): .info_pane { width: 1fr; height: auto; } .info_pane Label { width: 100%; } .pane_header { text-style: bold; color: $accent; margin-bottom: 1; } - #bp_lbl_backup { text-style: bold; margin-top: 1; } + .pane_status { text-style: bold; margin-top: 1; } + #bp_info_split Rule { height: 100%; margin: 0 2; color: $accent; } + #bp_lbl_backup { display: none; } BackupPane #bp_actions { height: auto; } BackupPane #bp_actions Button { width: 100%; margin-bottom: 1; } @@ -58,12 +61,17 @@ class BackupPane(Container): yield Label("Discord", classes="pane_header") yield Label("Server: -", id="bp_lbl_server") yield Label("Source: -", id="bp_lbl_bot") + yield Label("Status: -", id="bp_lbl_d_status", classes="pane_status") + + yield Rule(orientation="vertical", id="bp_vrule") + with Vertical(classes="info_pane", id="bp_target_pane"): - # Hidden in backup mode - pass + yield Label("Target", classes="pane_header") + yield Label("Community: -", id="bp_lbl_t_comm") + yield Label("Bot: -", id="bp_lbl_t_bot") + yield Label("Status: -", id="bp_lbl_t_status", classes="pane_status") - yield Rule() - yield Label("Status: -", id="bp_lbl_backup") + yield Label("", id="bp_lbl_backup") with Vertical(id="bp_actions"): yield Button("Backup Server Profile", id="bp_backup_profile", disabled=True) yield Button("Backup Channel Messages", id="bp_backup_msgs", disabled=True, variant="primary") @@ -122,9 +130,16 @@ class BackupPane(Container): try: self.query_one("#bp_lbl_server", Label).update(f"Server: {server_text}") self.query_one("#bp_lbl_bot", Label).update(f"Source: {bot_text}") + + # Status for Discord side + d_status = "[green][VALID][/green]" if enabled else "[red][INVALID][/red]" + self.query_one("#bp_lbl_d_status", Label).update(f"Status: {d_status}") + + # Legacy label for safety if called elsewhere self.query_one("#bp_lbl_backup", Label).update(f"Status: {backup_text}") - # Hide target pane in backup + # Hide target side in backup mode completely + self.query_one("#bp_vrule").display = False self.query_one("#bp_target_pane").display = False for bid in ("#bp_backup_profile", "#bp_backup_msgs", "#bp_backup_sync"): diff --git a/src/ui/modals.py b/src/ui/modals.py index df7d02f..c6620ad 100644 --- a/src/ui/modals.py +++ b/src/ui/modals.py @@ -11,6 +11,7 @@ from textual.screen import ModalScreen, Screen import time import logging import asyncio +from typing import Any, Optional, Union, List, Dict, Callable class UILogHandler(logging.Handler): """Custom logging handler to send logs to the Textual UI RichLog.""" diff --git a/src/ui/shuttle_ops.py b/src/ui/shuttle_ops.py index 14b9268..7d7bf2e 100644 --- a/src/ui/shuttle_ops.py +++ b/src/ui/shuttle_ops.py @@ -10,6 +10,7 @@ import time import aiohttp import traceback from pathlib import Path +from typing import Any, Optional, Union, List, Dict, Callable from textual.app import ComposeResult from textual.containers import Container, Vertical, Horizontal, VerticalScroll @@ -89,7 +90,9 @@ class ShuttlePane(Container): .info_pane { width: 1fr; height: auto; } .info_pane Label { width: 100%; } .pane_header { text-style: bold; color: $accent; margin-bottom: 1; } - #sp_lbl_status { text-style: bold; margin-top: 1; } + .pane_status { text-style: bold; margin-top: 1; } + #sp_info_split Rule { height: 100%; margin: 0 2; color: $accent; } + #sp_lbl_status { display: none; } ShuttlePane #sp_actions { height: auto; } ShuttlePane #sp_actions Button { width: 100%; margin-bottom: 1; } @@ -114,14 +117,17 @@ class ShuttlePane(Container): yield Label("Discord", classes="pane_header") yield Label("Server: [yellow]Loading...[/yellow]", id="sp_lbl_d_server") yield Label("Bot: [yellow]Loading...[/yellow]", id="sp_lbl_d_bot") + yield Label("Status: [yellow]Validating...[/yellow]", id="sp_lbl_d_status", classes="pane_status") + yield Rule(orientation="vertical") + with Vertical(classes="info_pane"): yield Label("Target", id="sp_lbl_t_header", classes="pane_header") yield Label("Community: [yellow]Loading...[/yellow]", id="sp_lbl_t_comm") yield Label("Bot: [yellow]Loading...[/yellow]", id="sp_lbl_t_bot") + yield Label("Status: [yellow]Validating...[/yellow]", id="sp_lbl_t_status", classes="pane_status") - yield Rule() - yield Label("Status: [yellow]Validating...[/yellow]", id="sp_lbl_status") + yield Label("", id="sp_lbl_status") with Vertical(id="sp_actions"): yield Button("Clone Server Template", id="sp_clone", disabled=True) yield Button("Sync Server Settings", id="sp_sync", disabled=True) @@ -174,6 +180,15 @@ class ShuttlePane(Container): else: self.query_one("#sp_lbl_d_bot", Label).update(f"Bot: {b_disp}") + # Discord Side Status + if v.get("discord_token") and v.get("discord_server"): + d_status = "[green][VALID][/green]" + elif v.get("discord_timeout"): + d_status = "[red][TIMEOUT][/red]" + else: + d_status = "[red][INVALID][/red]" + self.query_one("#sp_lbl_d_status", Label).update(f"Status: {d_status}") + # Target plat = "Fluxer" if self.target_platform == "fluxer" else "Stoat" t_name = v.get("target_community_name") @@ -194,6 +209,15 @@ class ShuttlePane(Container): self.query_one("#sp_lbl_t_comm", Label).update(f"Community: {c_disp}") self.query_one("#sp_lbl_t_bot", Label).update(f"Bot: {tb_disp}") + # Target Side Status + if v.get("target_token") and v.get("target_community"): + t_status = "[green][VALID][/green]" + elif v.get("target_timeout"): + t_status = "[red][TIMEOUT][/red]" + else: + t_status = "[red][INVALID][/red]" + self.query_one("#sp_lbl_t_status", Label).update(f"Status: {t_status}") + # Status if not self.tokens_valid: val = "[red][INVALID][/red]"