update progress tracking for migration
This commit is contained in:
parent
ad2dca7f0a
commit
803e580f17
2 changed files with 40 additions and 23 deletions
|
|
@ -65,6 +65,7 @@ class ProgressScreen(Screen[None]):
|
||||||
|
|
||||||
#prog_bar_container { height: auto; width: 100%; align: center middle; }
|
#prog_bar_container { height: auto; width: 100%; align: center middle; }
|
||||||
#prog_bar { margin-bottom: 1; width: 80%; }
|
#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 $secondary; padding: 1; margin-bottom: 1; display: none; }
|
#info_container { height: auto; layout: vertical; border: solid $secondary; padding: 1; margin-bottom: 1; display: none; }
|
||||||
.info_label { text-style: bold; content-align: center middle; width: 100%; color: $secondary-lighten-2; }
|
.info_label { text-style: bold; content-align: center middle; width: 100%; color: $secondary-lighten-2; }
|
||||||
|
|
@ -95,7 +96,8 @@ class ProgressScreen(Screen[None]):
|
||||||
|
|
||||||
# Progress bar moved inside info container
|
# Progress bar moved inside info container
|
||||||
with Center(id="prog_bar_container"):
|
with Center(id="prog_bar_container"):
|
||||||
pb = ProgressBar(total=None, show_eta=False, id="prog_bar")
|
yield Label("", id="prog_item_status")
|
||||||
|
pb = ProgressBar(total=None, show_eta=False, show_percentage=False, id="prog_bar")
|
||||||
pb.display = False
|
pb.display = False
|
||||||
yield pb
|
yield pb
|
||||||
|
|
||||||
|
|
@ -192,10 +194,22 @@ class ProgressScreen(Screen[None]):
|
||||||
|
|
||||||
def set_progress(self, current: int, total: int):
|
def set_progress(self, current: int, total: int):
|
||||||
try:
|
try:
|
||||||
self.query_one("#prog_loader", LoadingIndicator).display = False
|
# Keep loader visible during progress next to timer
|
||||||
|
self.query_one("#prog_loader", LoadingIndicator).display = True
|
||||||
|
|
||||||
bar = self.query_one("#prog_bar", ProgressBar)
|
bar = self.query_one("#prog_bar", ProgressBar)
|
||||||
bar.display = True
|
bar.display = True
|
||||||
bar.update(total=total, progress=current)
|
bar.update(total=total, progress=current)
|
||||||
|
|
||||||
|
# Ensure the container is visible if we have a bar
|
||||||
|
self.query_one("#info_container", Vertical).display = True
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_item_status(self, status: str):
|
||||||
|
try:
|
||||||
|
self.query_one("#prog_item_status", Label).update(status)
|
||||||
|
self.query_one("#info_container", Vertical).display = True
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,7 @@ class ShuttlePane(Container):
|
||||||
force_mode = (choice == "btn_start_id")
|
force_mode = (choice == "btn_start_id")
|
||||||
modal.cancel_callback = lambda: setattr(self.engine, "is_running", False)
|
modal.cancel_callback = lambda: setattr(self.engine, "is_running", False)
|
||||||
modal.phase_progress()
|
modal.phase_progress()
|
||||||
|
modal.set_status("Cloning Server Template")
|
||||||
|
|
||||||
# Connections already started above
|
# Connections already started above
|
||||||
if not connections_started:
|
if not connections_started:
|
||||||
|
|
@ -446,6 +447,7 @@ class ShuttlePane(Container):
|
||||||
force_mode = (choice == "btn_start_id")
|
force_mode = (choice == "btn_start_id")
|
||||||
modal.cancel_callback = lambda: setattr(self.engine, "is_running", False)
|
modal.cancel_callback = lambda: setattr(self.engine, "is_running", False)
|
||||||
modal.phase_progress()
|
modal.phase_progress()
|
||||||
|
modal.set_status("Syncing Server Settings")
|
||||||
await self.engine.start_connections()
|
await self.engine.start_connections()
|
||||||
self.engine.is_running = True
|
self.engine.is_running = True
|
||||||
|
|
||||||
|
|
@ -483,14 +485,14 @@ class ShuttlePane(Container):
|
||||||
else:
|
else:
|
||||||
from src.stoat.clone_server import sync_channel_state, migrate_channels
|
from src.stoat.clone_server import sync_channel_state, migrate_channels
|
||||||
|
|
||||||
modal.set_status("Processing Server Structure...")
|
modal.set_item_status("Processing Server Structure...")
|
||||||
await sync_channel_state(self.engine)
|
await sync_channel_state(self.engine)
|
||||||
categories = await self.engine.discord_reader.get_categories()
|
categories = await self.engine.discord_reader.get_categories()
|
||||||
channels = await self.engine.discord_reader.get_channels()
|
channels = await self.engine.discord_reader.get_channels()
|
||||||
|
|
||||||
async def update_progress(item_name, status, current, total):
|
async def update_progress(item_name, status, current, total):
|
||||||
color = "cyan" if status == "Copying" else "yellow"
|
color = "cyan" if status == "Copying" else "yellow"
|
||||||
modal.set_status(f"[{color}]{status}: {item_name}[/{color}]")
|
modal.set_item_status(f"[{color}]{status}: {item_name}[/{color}]")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
cloned_info = await migrate_channels(self.engine, progress_callback=update_progress, force=force)
|
cloned_info = await migrate_channels(self.engine, progress_callback=update_progress, force=force)
|
||||||
|
|
@ -507,11 +509,11 @@ class ShuttlePane(Container):
|
||||||
|
|
||||||
async def _logic_clone_roles(self, modal: ProgressScreen, force: bool = False):
|
async def _logic_clone_roles(self, modal: ProgressScreen, force: bool = False):
|
||||||
roles_mod = fluxer_roles if self.target_platform == "fluxer" else stoat_roles
|
roles_mod = fluxer_roles if self.target_platform == "fluxer" else stoat_roles
|
||||||
modal.set_status("Processing Roles...")
|
modal.set_item_status("Processing Roles...")
|
||||||
await roles_mod.sync_roles_state(self.engine)
|
await roles_mod.sync_roles_state(self.engine)
|
||||||
|
|
||||||
async def update(name, current, total):
|
async def update(name, current, total):
|
||||||
modal.set_status(f"[cyan]Copying Role: {name}[/cyan]")
|
modal.set_item_status(f"[cyan]Copying Role: {name}[/cyan]")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
cloned = await roles_mod.migrate_roles(self.engine, progress_callback=update, force=force)
|
cloned = await roles_mod.migrate_roles(self.engine, progress_callback=update, force=force)
|
||||||
|
|
@ -521,10 +523,10 @@ class ShuttlePane(Container):
|
||||||
|
|
||||||
async def _logic_sync_permissions(self, modal: ProgressScreen):
|
async def _logic_sync_permissions(self, modal: ProgressScreen):
|
||||||
roles_mod = fluxer_roles if self.target_platform == "fluxer" else stoat_roles
|
roles_mod = fluxer_roles if self.target_platform == "fluxer" else stoat_roles
|
||||||
modal.set_status("Syncing Permissions...")
|
modal.set_item_status("Syncing Permissions...")
|
||||||
|
|
||||||
async def update(name, current, total):
|
async def update(name, current, total):
|
||||||
modal.set_status(f"[cyan]Syncing Perms: {name}[/cyan]")
|
modal.set_item_status(f"[cyan]Syncing Perms: {name}[/cyan]")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
synced = await roles_mod.sync_permissions(self.engine, progress_callback=update)
|
synced = await roles_mod.sync_permissions(self.engine, progress_callback=update)
|
||||||
|
|
@ -541,11 +543,11 @@ class ShuttlePane(Container):
|
||||||
|
|
||||||
async def _logic_copy_assets(self, modal: ProgressScreen, types_to_include: list[str], force: bool = False):
|
async def _logic_copy_assets(self, modal: ProgressScreen, types_to_include: list[str], force: bool = False):
|
||||||
asset_mod = stoat_emoji_stickers if self.target_platform == "stoat" else fluxer_emoji_stickers
|
asset_mod = stoat_emoji_stickers if self.target_platform == "stoat" else fluxer_emoji_stickers
|
||||||
modal.set_status("Processing Assets...")
|
modal.set_item_status("Processing Assets...")
|
||||||
await asset_mod.sync_assets_state(self.engine)
|
await asset_mod.sync_assets_state(self.engine)
|
||||||
|
|
||||||
async def update(name, item_type, current, total):
|
async def update(name, item_type, current, total):
|
||||||
modal.set_status(f"[cyan]Copying {item_type}: {name}[/cyan]")
|
modal.set_item_status(f"[cyan]Copying {item_type}: {name}[/cyan]")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
cloned = await asset_mod.migrate_emojis(self.engine, progress_callback=update, types_to_include=types_to_include, force=force)
|
cloned = await asset_mod.migrate_emojis(self.engine, progress_callback=update, types_to_include=types_to_include, force=force)
|
||||||
|
|
@ -560,7 +562,7 @@ class ShuttlePane(Container):
|
||||||
|
|
||||||
async def _logic_sync_metadata(self, modal: ProgressScreen, components: list[str]):
|
async def _logic_sync_metadata(self, modal: ProgressScreen, components: list[str]):
|
||||||
meta_mod = fluxer_metadata if self.target_platform == "fluxer" else stoat_metadata
|
meta_mod = fluxer_metadata if self.target_platform == "fluxer" else stoat_metadata
|
||||||
modal.set_status("Syncing Server Profile...")
|
modal.set_item_status("Syncing Server Profile...")
|
||||||
|
|
||||||
async def progress_cb(item, status):
|
async def progress_cb(item, status):
|
||||||
color = "green" if status == "DONE" else "red" if status == "ERROR" else "yellow"
|
color = "green" if status == "DONE" else "red" if status == "ERROR" else "yellow"
|
||||||
|
|
@ -751,9 +753,9 @@ class ShuttlePane(Container):
|
||||||
choice = await modal.phase_wait_confirm(
|
choice = await modal.phase_wait_confirm(
|
||||||
show_continue=has_previous,
|
show_continue=has_previous,
|
||||||
show_id=True,
|
show_id=True,
|
||||||
btn_start_label="Start Migration",
|
btn_start_label="Start from\nFirst Message",
|
||||||
btn_continue_label="Continue Migration",
|
btn_continue_label="Continue\nMigration",
|
||||||
btn_id_label="Start from ID"
|
btn_id_label="Start from\nmessage ID"
|
||||||
)
|
)
|
||||||
logger.info(f"User confirmation choice: {choice}")
|
logger.info(f"User confirmation choice: {choice}")
|
||||||
if choice == "btn_back":
|
if choice == "btn_back":
|
||||||
|
|
@ -802,7 +804,7 @@ class ShuttlePane(Container):
|
||||||
c_threads = current_stats["threads"]
|
c_threads = current_stats["threads"]
|
||||||
c_files = current_stats["attachments"]
|
c_files = current_stats["attachments"]
|
||||||
|
|
||||||
modal.set_status(f"[cyan]Migrated {c_msgs}/{total_messages} messages...")
|
modal.set_item_status(f"[cyan]Migrated {c_msgs}/{total_messages} messages...")
|
||||||
modal.set_progress(c_msgs, total_messages)
|
modal.set_progress(c_msgs, total_messages)
|
||||||
|
|
||||||
modal.update_stats(
|
modal.update_stats(
|
||||||
|
|
@ -921,6 +923,7 @@ class ShuttlePane(Container):
|
||||||
|
|
||||||
modal.cancel_callback = lambda: setattr(self.engine, "is_running", False)
|
modal.cancel_callback = lambda: setattr(self.engine, "is_running", False)
|
||||||
modal.phase_progress()
|
modal.phase_progress()
|
||||||
|
modal.set_status("Danger Zone: Destructive Operations")
|
||||||
self.engine.is_running = True
|
self.engine.is_running = True
|
||||||
# Writer already started above, no need to reconnect
|
# Writer already started above, no need to reconnect
|
||||||
if not target_started:
|
if not target_started:
|
||||||
|
|
@ -1080,9 +1083,9 @@ class ShuttlePane(Container):
|
||||||
else:
|
else:
|
||||||
from src.stoat.danger_zone import danger_delete_all_channels
|
from src.stoat.danger_zone import danger_delete_all_channels
|
||||||
|
|
||||||
modal.set_status("[red]Deleting channels...")
|
modal.set_item_status("[red]Deleting channels...")
|
||||||
async def on_deleted(name, current, total):
|
async def on_deleted(name, current, total):
|
||||||
modal.set_status(f"[red]Deleting: {name}")
|
modal.set_item_status(f"[red]Deleting: {name}")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
count = await danger_delete_all_channels(self.engine, progress_callback=on_deleted)
|
count = await danger_delete_all_channels(self.engine, progress_callback=on_deleted)
|
||||||
|
|
@ -1095,9 +1098,9 @@ class ShuttlePane(Container):
|
||||||
else:
|
else:
|
||||||
from src.stoat.danger_zone import danger_reset_channel_permissions
|
from src.stoat.danger_zone import danger_reset_channel_permissions
|
||||||
|
|
||||||
modal.set_status("[red]Resetting permissions...")
|
modal.set_item_status("[red]Resetting permissions...")
|
||||||
async def on_reset(name, current, total):
|
async def on_reset(name, current, total):
|
||||||
modal.set_status(f"[red]Resetting: {name}")
|
modal.set_item_status(f"[red]Resetting: {name}")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
count = await danger_reset_channel_permissions(self.engine, progress_callback=on_reset)
|
count = await danger_reset_channel_permissions(self.engine, progress_callback=on_reset)
|
||||||
|
|
@ -1110,9 +1113,9 @@ class ShuttlePane(Container):
|
||||||
else:
|
else:
|
||||||
from src.stoat.danger_zone import danger_delete_all_roles
|
from src.stoat.danger_zone import danger_delete_all_roles
|
||||||
|
|
||||||
modal.set_status("[red]Deleting roles...")
|
modal.set_item_status("[red]Deleting roles...")
|
||||||
async def on_deleted(name, current, total):
|
async def on_deleted(name, current, total):
|
||||||
modal.set_status(f"[red]Deleting role: {name}")
|
modal.set_item_status(f"[red]Deleting role: {name}")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
count = await danger_delete_all_roles(self.engine, progress_callback=on_deleted)
|
count = await danger_delete_all_roles(self.engine, progress_callback=on_deleted)
|
||||||
|
|
@ -1125,9 +1128,9 @@ class ShuttlePane(Container):
|
||||||
else:
|
else:
|
||||||
from src.stoat.danger_zone import danger_delete_all_emojis_and_stickers
|
from src.stoat.danger_zone import danger_delete_all_emojis_and_stickers
|
||||||
|
|
||||||
modal.set_status("[red]Deleting assets...")
|
modal.set_item_status("[red]Deleting assets...")
|
||||||
async def on_deleted(name, asset_type, current, total):
|
async def on_deleted(name, asset_type, current, total):
|
||||||
modal.set_status(f"[red]Deleting {asset_type}: {name}")
|
modal.set_item_status(f"[red]Deleting {asset_type}: {name}")
|
||||||
modal.set_progress(current, total)
|
modal.set_progress(current, total)
|
||||||
|
|
||||||
counts = await danger_delete_all_emojis_and_stickers(self.engine, progress_callback=on_deleted)
|
counts = await danger_delete_all_emojis_and_stickers(self.engine, progress_callback=on_deleted)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue