Skip to main content
The UI class provides an interactive console menu system with keyboard navigation for building terminal-based user interfaces.

Namespace

UI
This class is in the global namespace, not the PhasmoDecrypt namespace.

Constructor

Creates a new interactive menu with selectable options.
public UI(
    string[] options,
    Action<int> onSelect,
    ConsoleColor selectedBackgroundColor = ConsoleColor.DarkMagenta,
    ConsoleColor selectedForegroundColor = ConsoleColor.White
)
options
string[]
required
Array of menu option labels to display.
onSelect
Action<int>
required
Callback function invoked when user presses Enter. Receives the selected index (0-based).
selectedBackgroundColor
ConsoleColor
default:"ConsoleColor.DarkMagenta"
Background color for the currently selected option.
selectedForegroundColor
ConsoleColor
default:"ConsoleColor.White"
Text color for the currently selected option.

Methods

Display()

Displays the menu and handles user input.
public void Display()
Returns: void - Blocks until user selects an option. Behavior:
  • Clears the console and displays the menu
  • Shows all options horizontally with tab spacing
  • Highlights the selected option with custom colors
  • Handles keyboard input:
    • Left Arrow: Move selection left (wraps to end)
    • Right Arrow: Move selection right (wraps to start)
    • Enter: Execute onSelect callback and exit
  • Displays the application banner using Tag() method

Example Usage

Basic Menu

string[] options = { "Decrypt", "Encrypt", "Exit" };

var menu = new UI(
    options,
    onSelect: selectedIndex =>
    {
        switch (selectedIndex)
        {
            case 0:
                Console.WriteLine("Decrypt selected");
                break;
            case 1:
                Console.WriteLine("Encrypt selected");
                break;
            case 2:
                Environment.Exit(0);
                break;
        }
    }
);

menu.Display();

Custom Colors

string[] options = { "Option 1", "Option 2", "Option 3" };

var menu = new UI(
    options,
    onSelect: index => Console.WriteLine($"Selected: {options[index]}"),
    selectedBackgroundColor: ConsoleColor.Blue,
    selectedForegroundColor: ConsoleColor.Yellow
);

menu.Display();

Real-World Example (from Program.cs)

string[] options = { "Use My Save File", "I'll add it myself", "Back" };

var menu = new UI(
    options,
    onSelect: selectedIndex =>
    {
        switch (selectedIndex)
        {
            case 0:
                string path = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
                    "AppData", "LocalLow", "Kinetic Games", "Phasmophobia"
                );
                string saveFile = Path.Combine(path, "SaveFile.txt");
                
                if (File.Exists(saveFile))
                {
                    var crypter = new Crypter();
                    string decryptedText = crypter.Decrypt(File.ReadAllBytes(saveFile));
                    Globals.DecryptedText = decryptedText;
                }
                break;
                
            case 1:
                Console.Write("File Path > ");
                string? filePath = Console.ReadLine()?.Trim('"');
                // Handle manual file input
                break;
                
            case 2:
                // Go back
                break;
        }
    }
);

menu.Display();
Options are displayed horizontally:
		Option 1		  Option 2  		  Option 3  	
        ^^^^^^^^^^^^^ (highlighted with background color)
  • Each option is prefixed with \t\t
  • Selected option has background and foreground colors applied
  • Options are wrapped in tab characters for spacing
  • Wrapping: Navigation wraps around (left from first → last, right from last → first)
  • Selection: Starts at index 0 by default
  • Exit: Only exits when Enter is pressed (no escape key)
The Display() method clears the console on every render. Any previous console output will be lost.

Private Methods

Tag()

Displays the PhasmoDecrypt ASCII art banner.
static void Tag()
Output:
 _____   __  __  ______  ____             _____       ____    ____    ______  ______   
/\  _`\ /\ \/\ \/\  _  \/\  _`\   /'\_/`\/\  __`\    /\  _`\ /\  _`\ /\__  _\/\__  _\  
\ \ \L\ \ \ \_\ \ \ \L\ \ \,\L\_\/\      \ \ \/\ \   \ \ \L\_\ \ \/\ \/_/\ \/\/_/\ \/  
 \ \ ,__/\ \  _  \ \  __ \/_\__ \\ \ \__\ \ \ \ \ \   \ \  _\L\ \ \ \ \ \ \ \   \ \ \  
  \ \ \/  \ \ \ \ \ \ \/\ \/\ \L\ \ \ \_/\ \ \ \_\ \   \ \ \L\ \ \ \_\ \ \_\ \__ \ \ \ 
   \ \_\   \ \_\ \_\ \_\ \_\ `\____\ \_\\ \_\ \_____\   \ \____/\ \____/ /\_____\ \ \_\
    \/_/    \/_/\/_/\/_/\/_/\/_____/\/_/ \/_/\/_____/    \/___/  \/___/  \/_____/  \/_/
  • Rendered in ConsoleColor.DarkMagenta
  • Automatically called before displaying menu options

Dependencies

  • System - For Console and Action types

Source Reference

See the full implementation: /workspace/source/Components/UI.cs:15-86

Build docs developers (and LLMs) love