redesign: UI Work

This commit is contained in:
2026-04-14 13:18:27 -04:00
parent a015908d44
commit 66e7ca4fc7
11 changed files with 2130 additions and 812 deletions
+138 -88
View File
@@ -36,6 +36,23 @@ from update_config import get_update_config
# Load environment variables
load_dotenv()
# Steam Collections page inspired color scheme for TUI
TUI_COLORS = {
'bg_primary': '#1b2838', # Steam dark blue background
'bg_secondary': '#2a475e', # Steam medium blue background
'bg_tertiary': '#1e2328', # Steam darker background for cards
'text_primary': '#c7d5e0', # Steam primary text (light blue-gray)
'text_highlight': '#66c0f4', # Steam blue highlight color
'text_body': '#8f98a0', # Steam body text (muted blue-gray)
'text_secondary': '#acb2b8', # Steam secondary text
'text_muted': '#67707b', # Steam muted text
'accent_green': '#5ba32b', # Steam success green
'accent_red': '#cd5c5c', # Steam error red
'accent_yellow': '#ffa500', # Steam warning orange
'accent_blue': '#66c0f4', # Steam signature blue
'accent_cyan': '#66c0f4', # Steam info/header color (same as blue)
}
console = Console()
class ProgressionTUI:
@@ -114,23 +131,26 @@ class ProgressionTUI:
self.hr_systems_logo = "Hudson Riggs Systems"
def display_header(self):
"""Display the header with ASCII art"""
# Use the actual progression logo ASCII art instead of just text
"""Display the header with ASCII art using Steam Collections inspired styling"""
# Use the actual progression logo ASCII art with Steam blue highlight
header_panel = Panel(
Align.center(self.progression_logo),
box=box.DOUBLE,
style="cyan",
padding=(1, 2)
style=TUI_COLORS['accent_blue'], # Steam blue
border_style=TUI_COLORS['accent_blue'],
padding=(1, 2),
title="[bold]PROGRESSION LOADER[/bold]",
title_align="center"
)
return header_panel
def display_footer(self):
"""Display footer with HR Systems info"""
"""Display footer with HR Systems info using Steam Collections inspired styling"""
footer_text = Text()
footer_text.append("Hudson Riggs Systems", style="dim white")
footer_text.append(" - ", style="dim white")
footer_text.append("https://hudsonriggs.systems", style="dim blue underline")
footer_text.append("Hudson Riggs Systems", style=f"dim {TUI_COLORS['text_secondary']}")
footer_text.append(" - ", style=f"dim {TUI_COLORS['text_secondary']}")
footer_text.append("https://hudsonriggs.systems", style=f"dim {TUI_COLORS['accent_blue']} underline")
return Align.center(footer_text)
@@ -147,40 +167,66 @@ class ProgressionTUI:
self.console.print(self.display_header())
self.console.print()
# Create main menu options
menu_table = Table(show_header=False, box=box.SIMPLE, padding=(0, 2))
menu_table.add_column("Option", style="cyan bold", width=4)
menu_table.add_column("Description", style="white")
menu_table.add_column("Status", style="green", width=15)
# Create main menu options with Steam Collections inspired styling
menu_table = Table(show_header=False, box=box.ROUNDED, padding=(0, 2))
menu_table.add_column("Option", style=f"{TUI_COLORS['accent_blue']} bold", width=4)
menu_table.add_column("Description", style=TUI_COLORS['text_primary'])
menu_table.add_column("Status", style=TUI_COLORS['accent_green'], width=15)
# Menu options with status indicators
rimworld_status = "Valid" if self.is_rimworld_valid else "Not Set"
rimworld_color = "green" if self.is_rimworld_valid else "red"
# Menu options with Steam-styled status indicators
rimworld_status = "✓ Valid" if self.is_rimworld_valid else "Not Set"
rimworld_color = TUI_COLORS['accent_green'] if self.is_rimworld_valid else TUI_COLORS['accent_yellow']
menu_table.add_row("1", "Set RimWorld Game Folder", f"[{rimworld_color}]{rimworld_status}[/{rimworld_color}]")
menu_table.add_row("2", "Check Steam Workshop Subscriptions", "")
menu_table.add_row("3", "Check RimWorld Expansions", "")
menu_table.add_row("4", "Load Progression Pack Complete", "Enabled" if self.is_rimworld_valid else "[dim]Disabled[/dim]")
menu_table.add_row("5", "Merge with Current Mods Config", "Enabled" if self.is_rimworld_valid else "[dim]Disabled[/dim]")
menu_table.add_row("4", "Load Progression Pack Complete", f"[{TUI_COLORS['accent_green']}]✓ Ready[/{TUI_COLORS['accent_green']}]" if self.is_rimworld_valid else f"[{TUI_COLORS['text_muted']}]⚠ Disabled[/{TUI_COLORS['text_muted']}]")
menu_table.add_row("5", "Merge with Current Mods Config", f"[{TUI_COLORS['accent_green']}]✓ Ready[/{TUI_COLORS['accent_green']}]" if self.is_rimworld_valid else f"[{TUI_COLORS['text_muted']}]⚠ Disabled[/{TUI_COLORS['text_muted']}]")
menu_table.add_row("6", "Check for Updates", "")
menu_table.add_row("7", "View Configuration", "")
menu_table.add_row("0", "Exit", "")
# Create Steam-styled menu panel
menu_panel = Panel(
menu_table,
title="Main Menu",
title="[bold]Main Menu[/bold]",
title_align="center",
box=box.ROUNDED,
style="white"
style=TUI_COLORS['text_primary'],
border_style=TUI_COLORS['accent_blue']
)
self.console.print(menu_panel)
self.console.print()
# Display current paths if set
# Display current paths if set with Steam Collections styling
if self.rimworld_path or self.workshop_path:
info_table = Table(show_header=False, box=None, padding=(0, 1))
info_table.add_column("Label", style="cyan", width=25)
info_table.add_column("Path", style="white")
info_table.add_column("Label", style=f"{TUI_COLORS['accent_blue']} bold", width=25)
info_table.add_column("Path", style=TUI_COLORS['text_body'])
if self.rimworld_path:
status_icon = "" if self.is_rimworld_valid else ""
status_color = TUI_COLORS['accent_green'] if self.is_rimworld_valid else TUI_COLORS['accent_yellow']
info_table.add_row(f"[{status_color}]{status_icon}[/{status_color}] RimWorld Path:", self.rimworld_path)
if self.workshop_path:
info_table.add_row(f"[{TUI_COLORS['accent_blue']}]📁[/{TUI_COLORS['accent_blue']}] Workshop Path:", self.workshop_path)
if self.modsconfig_path:
info_table.add_row(f"[{TUI_COLORS['accent_blue']}]⚙[/{TUI_COLORS['accent_blue']}] ModsConfig Path:", self.modsconfig_path)
# Create Steam-styled info panel
info_panel = Panel(
info_table,
title="[bold]Current Configuration[/bold]",
title_align="center",
box=box.ROUNDED,
style=TUI_COLORS['text_secondary'],
border_style=TUI_COLORS['text_muted']
)
self.console.print(info_panel)
self.console.print()
if self.rimworld_path:
info_table.add_row("RimWorld Path:", self.rimworld_path)
@@ -201,7 +247,7 @@ class ProgressionTUI:
choice = Prompt.ask("Select an option", choices=["0", "1", "2", "3", "4", "5", "6", "7"], default="1")
if choice == "0":
self.console.print("\n[yellow]Thank you for using Progression Loader![/yellow]")
self.console.print(f"\n[{TUI_COLORS['accent_yellow']}]Thank you for using Progression Loader![/{TUI_COLORS['accent_yellow']}]")
break
elif choice == "1":
self.set_rimworld_path()
@@ -213,13 +259,13 @@ class ProgressionTUI:
if self.is_rimworld_valid:
self.load_progression_pack()
else:
self.console.print("\n[red]Please set a valid RimWorld path first![/red]")
self.console.print(f"\n[{TUI_COLORS['accent_red']}]Please set a valid RimWorld path first![/{TUI_COLORS['accent_red']}]")
self.console.input("\nPress Enter to continue...")
elif choice == "5":
if self.is_rimworld_valid:
self.merge_with_current_mods()
else:
self.console.print("\n[red]Please set a valid RimWorld path first![/red]")
self.console.print(f"\n[{TUI_COLORS['accent_red']}]Please set a valid RimWorld path first![/{TUI_COLORS['accent_red']}]")
self.console.input("\nPress Enter to continue...")
elif choice == "6":
self.check_for_updates()
@@ -227,10 +273,10 @@ class ProgressionTUI:
self.view_configuration()
except KeyboardInterrupt:
self.console.print("\n\n[yellow]Goodbye![/yellow]")
self.console.print(f"\n\n[{TUI_COLORS['accent_yellow']}]Goodbye![/{TUI_COLORS['accent_yellow']}]")
break
except Exception as e:
self.console.print(f"\n[red]Error: {e}[/red]")
self.console.print(f"\n[{TUI_COLORS['accent_red']}]Error: {e}[/{TUI_COLORS['accent_red']}]")
self.console.input("\nPress Enter to continue...")
def set_rimworld_path(self):
@@ -239,28 +285,30 @@ class ProgressionTUI:
self.console.print(self.display_header())
self.console.print()
# Instructions
# Instructions with modern styling - bold titles, italic emphasis
instructions = Panel(
Text.from_markup(
"To find your RimWorld path:\n"
"[bold]To find your RimWorld path:[/bold]\n\n"
"1. Open Steam\n"
"2. Right-click RimWorld in your library\n"
"3. Select 'Manage' > 'Browse local files'\n"
"4. Copy the path from the address bar\n\n"
"Example: C:\\Steam\\steamapps\\common\\RimWorld"
"[italic dim]Example: C:\\Steam\\steamapps\\common\\RimWorld[/italic dim]"
),
title="Instructions",
style="cyan"
title=f"[bold {TUI_COLORS['text_highlight']}]Instructions[/bold {TUI_COLORS['text_highlight']}]",
title_align="center",
style=TUI_COLORS['accent_cyan'],
border_style="rounded"
)
self.console.print(instructions)
self.console.print()
# Current path if set
# Current path if set with new colors
if self.rimworld_path:
current_panel = Panel(
f"Current path: {self.rimworld_path}",
title="Current RimWorld Path",
style="green" if self.is_rimworld_valid else "red"
style=TUI_COLORS['accent_green'] if self.is_rimworld_valid else TUI_COLORS['accent_red']
)
self.console.print(current_panel)
self.console.print()
@@ -283,17 +331,17 @@ class ProgressionTUI:
# Derive workshop path
self.derive_workshop_path()
progress.update(task, description="[green]Valid RimWorld installation found![/green]")
progress.update(task, description=f"[{TUI_COLORS['accent_green']}]Valid RimWorld installation found![/{TUI_COLORS['accent_green']}]")
time.sleep(1)
self.console.print(f"\n[green]RimWorld path set successfully![/green]")
self.console.print(f"\n[{TUI_COLORS['accent_green']}]RimWorld path set successfully![/{TUI_COLORS['accent_green']}]")
self.console.print(f"Workshop path: {self.workshop_path}")
else:
progress.update(task, description="[red]Invalid RimWorld path![/red]")
progress.update(task, description=f"[{TUI_COLORS['accent_red']}]Invalid RimWorld path![/{TUI_COLORS['accent_red']}]")
time.sleep(1)
self.console.print(f"\n[red]Invalid RimWorld installation at: {new_path}[/red]")
self.console.print("[red]Please ensure the path contains RimWorld.exe and Data folder[/red]")
self.console.print(f"\n[{TUI_COLORS['accent_red']}]Invalid RimWorld installation at: {new_path}[/{TUI_COLORS['accent_red']}]")
self.console.print(f"[{TUI_COLORS['accent_red']}]Please ensure the path contains RimWorld.exe and Data folder[/{TUI_COLORS['accent_red']}]")
self.console.input("\nPress Enter to continue...")
@@ -339,26 +387,28 @@ class ProgressionTUI:
self.console.print(self.display_header())
self.console.print()
# Display collections
collections_table = Table(show_header=True, box=box.ROUNDED)
collections_table.add_column("Collection", style="cyan bold", width=20)
collections_table.add_column("URL", style="blue", width=50)
collections_table.add_column("Subscribed", style="green", width=12)
# Display collections with modern styling
collections_table = Table(show_header=True, box=box.ROUNDED, border_style="bright_black")
collections_table.add_column("Collection", style=f"{TUI_COLORS['text_highlight']} bold", width=20)
collections_table.add_column("URL", style=TUI_COLORS['accent_blue'], width=50)
collections_table.add_column("Subscribed", style=TUI_COLORS['accent_green'], width=12)
for name, url in self.collections.items():
status = "Yes" if self.subscription_status[name] else "No"
status_color = "green" if self.subscription_status[name] else "red"
status_color = TUI_COLORS['accent_green'] if self.subscription_status[name] else TUI_COLORS['accent_red']
collections_table.add_row(name, url, f"[{status_color}]{status}[/{status_color}]")
collections_panel = Panel(
collections_table,
title="Steam Workshop Collections",
style="white"
title="[bold]Steam Workshop Collections[/bold]",
title_align="center",
style=TUI_COLORS['text_primary'],
border_style="rounded"
)
self.console.print(collections_panel)
self.console.print()
# Instructions
# Instructions with new color scheme
instructions = Panel(
Text.from_markup(
"To subscribe to collections:\n"
@@ -367,10 +417,10 @@ class ProgressionTUI:
"3. Click 'Subscribe' on the Steam Workshop page\n"
"4. Wait for Steam to download the collection\n"
"5. Return here and mark as subscribed\n\n"
"[yellow]All collections are required for the complete Progression experience.[/yellow]"
f"[{TUI_COLORS['accent_yellow']}]All collections are required for the complete Progression experience.[/{TUI_COLORS['accent_yellow']}]"
),
title="Instructions",
style="cyan"
style=TUI_COLORS['accent_cyan']
)
self.console.print(instructions)
self.console.print()
@@ -378,8 +428,8 @@ class ProgressionTUI:
# Menu options
while True:
menu_table = Table(show_header=False, box=box.SIMPLE, padding=(0, 2))
menu_table.add_column("Option", style="cyan bold", width=4)
menu_table.add_column("Description", style="white")
menu_table.add_column("Option", style=f"{TUI_COLORS['accent_cyan']} bold", width=4)
menu_table.add_column("Description", style=TUI_COLORS['text_primary'])
menu_table.add_row("1", "Open Core Collection in browser")
menu_table.add_row("2", "Open Content Collection in browser")
@@ -390,7 +440,7 @@ class ProgressionTUI:
menu_table.add_row("7", "Check if all subscribed")
menu_table.add_row("0", "Back to main menu")
self.console.print(Panel(menu_table, title="Subscription Menu", style="white"))
self.console.print(Panel(menu_table, title="Subscription Menu", style=TUI_COLORS['text_primary']))
self.console.print()
choice = Prompt.ask("Select an option", choices=["0", "1", "2", "3", "4", "5", "6", "7"])
@@ -399,29 +449,29 @@ class ProgressionTUI:
break
elif choice == "1":
webbrowser.open(self.collections["Core Collection"])
self.console.print("[green]Opened Core Collection in browser[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]Opened Core Collection in browser[/{TUI_COLORS['accent_green']}]")
elif choice == "2":
webbrowser.open(self.collections["Content Collection"])
self.console.print("[green]Opened Content Collection in browser[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]Opened Content Collection in browser[/{TUI_COLORS['accent_green']}]")
elif choice == "3":
webbrowser.open(self.collections["Cosmetics Collection"])
self.console.print("[green]Opened Cosmetics Collection in browser[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]Opened Cosmetics Collection in browser[/{TUI_COLORS['accent_green']}]")
elif choice == "4":
self.subscription_status["Core Collection"] = True
self.console.print("[green]Core Collection marked as subscribed[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]Core Collection marked as subscribed[/{TUI_COLORS['accent_green']}]")
elif choice == "5":
self.subscription_status["Content Collection"] = True
self.console.print("[green]Content Collection marked as subscribed[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]Content Collection marked as subscribed[/{TUI_COLORS['accent_green']}]")
elif choice == "6":
self.subscription_status["Cosmetics Collection"] = True
self.console.print("[green]Cosmetics Collection marked as subscribed[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]Cosmetics Collection marked as subscribed[/{TUI_COLORS['accent_green']}]")
elif choice == "7":
all_subscribed = all(self.subscription_status.values())
if all_subscribed:
self.console.print("[green]All collections are subscribed! You can proceed.[/green]")
self.console.print(f"[{TUI_COLORS['accent_green']}]All collections are subscribed! You can proceed.[/{TUI_COLORS['accent_green']}]")
else:
missing = [name for name, status in self.subscription_status.items() if not status]
self.console.print(f"[red]Missing subscriptions: {', '.join(missing)}[/red]")
self.console.print(f"[{TUI_COLORS['accent_red']}]Missing subscriptions: {', '.join(missing)}[/{TUI_COLORS['accent_red']}]")
self.console.print()
@@ -441,44 +491,44 @@ class ProgressionTUI:
# Check expansions
self.check_expansions_thread()
progress.update(task, description="[green]Expansion check complete![/green]")
progress.update(task, description=f"[{TUI_COLORS['accent_green']}]Expansion check complete![/{TUI_COLORS['accent_green']}]")
time.sleep(1)
# Display results
# Display results with new color scheme
if self.expansion_check_results:
expansion_table = Table(show_header=True, box=box.ROUNDED)
expansion_table.add_column("Expansion", style="cyan bold", width=15)
expansion_table.add_column("Status", style="white", width=10)
expansion_table.add_column("Expansion", style=f"{TUI_COLORS['accent_cyan']} bold", width=15)
expansion_table.add_column("Status", style=TUI_COLORS['text_primary'], width=10)
missing_expansions = []
for expansion, owned in self.expansion_check_results.items():
status = "Owned" if owned else "Missing"
status_color = "green" if owned else "red"
status_color = TUI_COLORS['accent_green'] if owned else TUI_COLORS['accent_red']
expansion_table.add_row(expansion, f"[{status_color}]{status}[/{status_color}]")
if not owned:
missing_expansions.append(expansion)
self.console.print(Panel(expansion_table, title="RimWorld Expansions", style="white"))
self.console.print(Panel(expansion_table, title="RimWorld Expansions", style=TUI_COLORS['text_primary']))
self.console.print()
if missing_expansions:
warning_text = Text()
warning_text.append("WARNING: ", style="bold red")
warning_text.append(f"You don't own {', '.join(missing_expansions)}!\n", style="red")
warning_text.append("Some progression mods may not work without these expansions.", style="yellow")
warning_text.append("WARNING: ", style=f"bold {TUI_COLORS['accent_red']}")
warning_text.append(f"You don't own {', '.join(missing_expansions)}!\n", style=TUI_COLORS['accent_red'])
warning_text.append("Some progression mods may not work without these expansions.", style=TUI_COLORS['accent_yellow'])
warning_panel = Panel(warning_text, title="Missing Expansions", style="red")
warning_panel = Panel(warning_text, title="Missing Expansions", style=TUI_COLORS['accent_red'])
self.console.print(warning_panel)
else:
success_panel = Panel(
"[green]All RimWorld expansions detected![/green]",
f"[{TUI_COLORS['accent_green']}]All RimWorld expansions detected![/{TUI_COLORS['accent_green']}]",
title="Expansion Check",
style="green"
style=TUI_COLORS['accent_green']
)
self.console.print(success_panel)
else:
self.console.print("[yellow]Could not check expansions. Please ensure RimWorld path is set correctly.[/yellow]")
self.console.print(f"[{TUI_COLORS['accent_yellow']}]Could not check expansions. Please ensure RimWorld path is set correctly.[/{TUI_COLORS['accent_yellow']}]")
self.console.input("\nPress Enter to continue...")
@@ -680,25 +730,25 @@ class ProgressionTUI:
self.console.print(self.display_header())
self.console.print()
# Check prerequisites
# Check prerequisites with new colors
all_subscribed = all(self.subscription_status.values())
if not all_subscribed:
missing = [name for name, status in self.subscription_status.items() if not status]
error_panel = Panel(
f"[red]Please subscribe to all collections first!\nMissing: {', '.join(missing)}[/red]",
f"[{TUI_COLORS['accent_red']}]Please subscribe to all collections first!\nMissing: {', '.join(missing)}[/{TUI_COLORS['accent_red']}]",
title="Prerequisites Not Met",
style="red"
style=TUI_COLORS['accent_red']
)
self.console.print(error_panel)
self.console.input("\nPress Enter to continue...")
return
# Confirm action
# Confirm action with new colors
confirm_text = Text()
confirm_text.append("This will replace your current ModsConfig.xml with the complete Progression pack.\n", style="yellow")
confirm_text.append("Your current mod configuration will be backed up.", style="white")
confirm_text.append("This will replace your current ModsConfig.xml with the complete Progression pack.\n", style=TUI_COLORS['accent_yellow'])
confirm_text.append("Your current mod configuration will be backed up.", style=TUI_COLORS['text_primary'])
confirm_panel = Panel(confirm_text, title="Confirmation", style="yellow")
confirm_panel = Panel(confirm_text, title="Confirmation", style=TUI_COLORS['accent_yellow'])
self.console.print(confirm_panel)
self.console.print()
@@ -1075,18 +1125,18 @@ class ProgressionTUI:
def main():
"""Main entry point for the TUI application"""
try:
# Check for updates first
# Check for updates first with new colors
config = get_update_config()
if config.get("check_on_startup", True):
console.print("[cyan]Checking for updates...[/cyan]")
console.print(f"[{TUI_COLORS['accent_cyan']}]Checking for updates...[/{TUI_COLORS['accent_cyan']}]")
try:
update_checker = UpdateChecker(config["current_version"])
release_info, error = update_checker.check_for_updates_sync()
if release_info and update_checker.is_newer_version(release_info['version']):
console.print(f"[yellow]Update available: {release_info['version']}[/yellow]")
console.print(f"[{TUI_COLORS['accent_yellow']}]Update available: {release_info['version']}[/{TUI_COLORS['accent_yellow']}]")
if config.get("updates_required", False):
console.print("[red]This update is required. Please update before continuing.[/red]")
console.print(f"[{TUI_COLORS['accent_red']}]This update is required. Please update before continuing.[/{TUI_COLORS['accent_red']}]")
if Confirm.ask("Open download page?"):
webbrowser.open(release_info['html_url'])
return
@@ -1100,9 +1150,9 @@ def main():
app.show_main_menu()
except KeyboardInterrupt:
console.print("\n[yellow]Goodbye![/yellow]")
console.print(f"\n[{TUI_COLORS['accent_yellow']}]Goodbye![/{TUI_COLORS['accent_yellow']}]")
except Exception as e:
console.print(f"[red]Fatal error: {e}[/red]")
console.print(f"[{TUI_COLORS['accent_red']}]Fatal error: {e}[/{TUI_COLORS['accent_red']}]")
console.print("[dim]Please report this error to the developers.[/dim]")