impove modal messages

This commit is contained in:
rambros 2026-03-05 19:52:44 +05:30
parent 270d6ea391
commit d9567ace22
4 changed files with 38 additions and 49 deletions

View file

@ -617,6 +617,11 @@ class BackupGuild:
def categories(self) -> List[BackupCategory]:
return self._reader._categories if self._reader else []
def get_member(self, user_id: int) -> "BackupMember | None":
if self._reader:
return self._reader._member_map.get(int(user_id))
return None
def __repr__(self) -> str:
return f"BackupGuild(id={self.id}, name='{self.name}')"

View file

@ -158,14 +158,14 @@ class BackupPane(Container):
await self.exporter.setup()
# Gather and print summary
server = getattr(self.engine.discord_reader, 'current_server', None)
server = getattr(self.engine.discord_reader, 'guild', None)
if server:
modal.write(f"[bold cyan]Server Profile to Backup:[/bold cyan]")
modal.write(f" Name: [green]{server.name}[/green]")
modal.write(f" Icon: [green]{'Present' if server.icon else 'None'}[/green]")
modal.write(f" Roles: [green]{len(server.roles)}[/green]")
modal.write(f" Emojis: [green]{len(server.emojis)}[/green]")
modal.write(f" Channels: [green]{len(server.channels)}[/green]")
modal.write(f" Roles: [green]{len(getattr(server, 'roles', []))}[/green]")
modal.write(f" Emojis: [green]{len(getattr(server, 'emojis', []))}[/green]")
modal.write(f" Channels: [green]{len(getattr(server, 'channels', []))}[/green]")
modal.write("")
modal.show_info("[bold cyan]Profile Backup Ready[/bold cyan]", f"Overview: {len(server.channels) if server else '?'} Channels, {len(server.roles) if server else '?'} Roles")
@ -280,7 +280,7 @@ class BackupPane(Container):
new_channels = [c for c in selected_channels if c.id not in backed_up_ids]
existing_channels = [c for c in selected_channels if c.id in backed_up_ids]
server = getattr(self.engine.discord_reader, 'current_server', None)
server = getattr(self.engine.discord_reader, 'guild', None)
if server:
modal_prog.write(f"[bold cyan]Server Profile:[/bold cyan]")
modal_prog.write(f" Name: [green]{server.name}[/green]")
@ -391,14 +391,14 @@ class BackupPane(Container):
await self.exporter.setup()
# Gather and print summary
server = getattr(self.engine.discord_reader, 'current_server', None)
server = getattr(self.engine.discord_reader, 'guild', None)
if server:
modal_prog.write(f"[bold cyan]Server Profile to Sync:[/bold cyan]")
modal_prog.write(f" Name: [green]{server.name}[/green]")
modal_prog.write(f" Icon: [green]{'Present' if server.icon else 'None'}[/green]")
modal_prog.write(f" Roles: [green]{len(server.roles)}[/green]")
modal_prog.write(f" Emojis: [green]{len(server.emojis)}[/green]")
modal_prog.write(f" Channels: [green]{len(server.channels)}[/green]")
modal_prog.write(f" Roles: [green]{len(getattr(server, 'roles', []))}[/green]")
modal_prog.write(f" Emojis: [green]{len(getattr(server, 'emojis', []))}[/green]")
modal_prog.write(f" Channels: [green]{len(getattr(server, 'channels', []))}[/green]")
modal_prog.write("\n[dim]This operation will update the profile and scan existing baked-up channels for new messages.[/dim]")
modal_prog.write("")

View file

@ -63,8 +63,6 @@ class ProgressScreen(Screen[None]):
#prog_log { height: 1fr; margin-bottom: 1; border: solid $primary; }
#live_log { height: 10; margin-bottom: 1; border: solid yellow; }
#prog_bar_container { height: auto; width: 100%; align: center middle; }
#prog_bar { margin-bottom: 1; width: 80%; }
#prog_item_status { margin-bottom: 1; text-style: bold; color: cyan; width: 100%; text-align: center; }
#info_container { height: auto; layout: vertical; border: solid cyan; padding: 1; margin-bottom: 1; display: none; }
@ -73,6 +71,7 @@ class ProgressScreen(Screen[None]):
#prog_actions { height: auto; margin-top: 1; dock: bottom; margin-bottom: 0; layout: vertical; }
.action_row { height: auto; layout: horizontal; }
.action_row Button { width: 1fr; margin: 0 1; }
#prog_actions_row1, #prog_actions_row2 { display: none; }
"""
def compose(self) -> ComposeResult:
@ -93,13 +92,7 @@ class ProgressScreen(Screen[None]):
with Vertical(id="info_container"):
yield Label("", id="info_migration_status", classes="info_label")
yield Label("", id="info_new_items", classes="info_label")
# Progress bar moved inside info container
with Center(id="prog_bar_container"):
yield Label("", id="prog_item_status")
pb = ProgressBar(total=None, show_eta=False, show_percentage=False, id="prog_bar")
pb.display = False
yield pb
yield Label("", id="prog_item_status")
yield RichLog(id="prog_log", highlight=True, markup=True)
yield RichLog(id="live_log", highlight=True, markup=True)
@ -124,14 +117,6 @@ class ProgressScreen(Screen[None]):
self.start_time = time.time()
self.timer_event = self.set_interval(1.0, self.update_timer)
# Hide all action rows by default (fetch phase = no buttons)
try: self.query_one("#prog_actions_row1", Horizontal).display = False
except Exception: pass
try: self.query_one("#prog_actions_row2", Horizontal).display = False
except Exception: pass
try: self.query_one("#prog_actions_cancel", Horizontal).display = False
except Exception: pass
# Intercept Python logs and pipe to the #live_log
self.log_handler = UILogHandler(self.write_live)
@ -213,11 +198,7 @@ class ProgressScreen(Screen[None]):
# Keep loader visible during progress next to timer
self.query_one("#prog_loader", LoadingIndicator).display = True
bar = self.query_one("#prog_bar", ProgressBar)
bar.display = True
bar.update(total=total, progress=current)
# Ensure the container is visible if we have a bar
# Ensure the container is visible
self.query_one("#info_container", Vertical).display = True
except Exception:
pass
@ -255,9 +236,6 @@ class ProgressScreen(Screen[None]):
try: self.query_one("#prog_loader", LoadingIndicator).display = False
except Exception: pass
try: self.query_one("#prog_bar", ProgressBar).display = False
except Exception: pass
try: self.query_one("#prog_timer", Label).display = False
except Exception: pass
@ -353,8 +331,6 @@ class ProgressScreen(Screen[None]):
except Exception: pass
# Hide progress bar (no need to show 100% bar)
try: self.query_one("#prog_bar", ProgressBar).display = False
except Exception: pass
# Hide Cancel, show Back + Main Menu
try: self.query_one("#prog_actions_cancel", Horizontal).display = False
@ -615,7 +591,9 @@ class ChannelSelectScreen(Screen[dict]):
margin: 2 0;
background: $surface;
}
#chan_title { text-style: bold; margin-bottom: 1; }
#cs_header { height: auto; margin-bottom: 1; }
#chan_title { text-style: bold; }
#chan_warning { padding-left: 1; color: yellow; text-style: bold; }
#channel_list_scroll {
height: 1fr;
border: solid $primary;
@ -657,7 +635,10 @@ class ChannelSelectScreen(Screen[dict]):
yield Header(show_clock=True)
with Container(id="cs_outer"):
with Container(id="channel_dialog"):
yield Label("Select Channels to Backup", id="chan_title")
with Horizontal(id="cs_header"):
yield Label("Select Channels to Backup", id="chan_title")
if self.any_found:
yield Label(" (Existing backups found)", id="chan_warning")
with VerticalScroll(id="channel_list_scroll"):
cat_ids = sorted(
@ -680,6 +661,10 @@ class ChannelSelectScreen(Screen[dict]):
color = "green" if c.id in self.backed_up_ids else "white"
yield RadioButton(f"[{color}]{label}[/]", value=False, id=f"chan_{c.id}")
if self.any_found:
yield Label("", classes="label_warning")
yield Label("Note: Channels shown in green have existing backups", classes="label_warning")
with Horizontal(id="select_all_buttons"):
yield Button("Select All", id="btn_all")
yield Button("Deselect All", id="btn_none")
@ -687,7 +672,6 @@ class ChannelSelectScreen(Screen[dict]):
yield Rule()
with Horizontal(id="confirm_buttons"):
if self.any_found:
yield Label("Existing backups found:", classes="label_warning")
yield Button("Sync", variant="success", id="btn_sync")
yield Button("Force Overwrite", variant="warning", id="btn_force")
else:

View file

@ -83,7 +83,7 @@ class ShuttlePane(Container):
DEFAULT_CSS = """
ShuttlePane { height: auto; width: 100%; }
ShuttlePane #sp_info {
height: auto; border: tall cyan; padding: 1; margin-bottom: 1; layout: vertical;
height: auto; border: tall yellow; padding: 1; margin-bottom: 1; layout: vertical;
}
#sp_info_split { height: auto; layout: horizontal; width: 100%; margin-bottom: 1; }
.info_pane { width: 1fr; height: auto; }
@ -368,7 +368,7 @@ class ShuttlePane(Container):
preview = await self._fetch_clone_preview(selections) if connections_started else {}
if connections_started:
src_server = getattr(self.engine.discord_reader, 'current_server', None)
src_server = getattr(self.engine.discord_reader, 'guild', None)
tgt_server_info = await self.engine.writer.validate()
tgt_server_name = tgt_server_info.get("community_name", "target community")
@ -376,9 +376,9 @@ class ShuttlePane(Container):
modal.write(f"[bold cyan]Source Server Profile:[/bold cyan]")
modal.write(f" Name: [green]{src_server.name}[/green]")
modal.write(f" Icon: [green]{'Present' if src_server.icon else 'None'}[/green]")
modal.write(f" Roles: [green]{len(src_server.roles)}[/green]")
modal.write(f" Emojis: [green]{len(src_server.emojis)}[/green]")
modal.write(f" Channels: [green]{len(src_server.channels)}[/green]")
modal.write(f" Roles: [green]{len(getattr(src_server, 'roles', []))}[/green]")
modal.write(f" Emojis: [green]{len(getattr(src_server, 'emojis', []))}[/green]")
modal.write(f" Channels: [green]{len(getattr(src_server, 'channels', []))}[/green]")
modal.write("")
modal.write(f"[bold cyan]Target Community:[/bold cyan] [green]{tgt_server_name}[/green]\n")
@ -489,7 +489,7 @@ class ShuttlePane(Container):
logger.warning(f"Could not pre-connect for Sync preview: {e}")
if connections_started:
src_server = getattr(self.engine.discord_reader, 'current_server', None)
src_server = getattr(self.engine.discord_reader, 'guild', None)
tgt_server_info = await self.engine.writer.validate()
tgt_server_name = tgt_server_info.get("community_name", "target community")
@ -497,9 +497,9 @@ class ShuttlePane(Container):
modal.write(f"[bold cyan]Source Server Profile:[/bold cyan]")
modal.write(f" Name: [green]{src_server.name}[/green]")
modal.write(f" Icon: [green]{'Present' if src_server.icon else 'None'}[/green]")
modal.write(f" Roles: [green]{len(src_server.roles)}[/green]")
modal.write(f" Emojis: [green]{len(src_server.emojis)}[/green]")
modal.write(f" Channels: [green]{len(src_server.channels)}[/green]")
modal.write(f" Roles: [green]{len(getattr(src_server, 'roles', []))}[/green]")
modal.write(f" Emojis: [green]{len(getattr(src_server, 'emojis', []))}[/green]")
modal.write(f" Channels: [green]{len(getattr(src_server, 'channels', []))}[/green]")
modal.write("")
modal.write(f"[bold cyan]Target Community:[/bold cyan] [green]{tgt_server_name}[/green]\n")
@ -804,7 +804,7 @@ class ShuttlePane(Container):
self.app.push_screen(modal)
await asyncio.sleep(0.1)
src_server = getattr(self.engine.discord_reader, 'current_server', None)
src_server = getattr(self.engine.discord_reader, 'guild', None)
tgt_server_info = await self.engine.writer.validate()
tgt_server_name = tgt_server_info.get("community_name", "target community")