Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,34 @@ Press `/` to enter search mode. Type to filter the list incrementally. Press `En

## Configuration

prism-tui reads its configuration from PrismLauncher's data directory:
### PrismLauncher Data Directory

- **Linux**: `~/.local/share/PrismLauncher/`
prism-tui automatically detects your PrismLauncher data directory:

- **Linux**: `~/.local/share/PrismLauncher/` or Flatpak location
- **macOS**: `~/Library/Application Support/PrismLauncher/`
- **Windows**: `%APPDATA%/PrismLauncher/`

No additional configuration is required.
For custom or portable installations, you can override the data directory in two ways (checked in this order):

1. **Environment variable**: `PRISMLAUNCHER_DATA=/path/to/data prism-tui`
2. **Config file**: Set `data_dir` in the config (see below)

### Config File

prism-tui stores its settings in a TOML config file:

- **Linux**: `~/.config/prism-tui/config.toml`
- **macOS**: `~/Library/Application Support/prism-tui/config.toml`
- **Windows**: `%APPDATA%\prism-tui\config.toml`

```toml
default_sort = "Last Played"
sort_ascending = true
data_dir = "~/Games/PrismLauncher" # optional, overrides auto-detection
```

Sort and sort-direction preferences are saved automatically. The `data_dir` option supports `~` tilde expansion.

## Architecture

Expand Down
4 changes: 1 addition & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ pub struct App {
}

impl App {
pub fn new(config: PrismConfig) -> Result<Self> {
pub fn new(config: PrismConfig, app_config: AppConfig) -> Result<Self> {
use crate::data::{load_accounts, load_groups, load_instances};

let instances_dir = config.instances_dir();
Expand All @@ -213,8 +213,6 @@ impl App {

let active_account = accounts.iter().find(|a| a.is_active).cloned();

let app_config = AppConfig::load();

let sort_mode = app_config.default_sort_mode();
let sort_ascending = app_config.sort_ascending;

Expand Down
21 changes: 21 additions & 0 deletions src/data/app_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub struct AppConfig {
pub default_sort: String,
#[serde(default = "default_true")]
pub sort_ascending: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub data_dir: Option<String>,
}

fn default_true() -> bool {
Expand All @@ -24,6 +26,7 @@ impl Default for AppConfig {
Self {
default_sort: default_sort(),
sort_ascending: true,
data_dir: None,
}
}
}
Expand Down Expand Up @@ -65,6 +68,10 @@ impl AppConfig {
}
}

pub fn resolved_data_dir(&self) -> Option<PathBuf> {
self.data_dir.as_ref().map(|p| expand_tilde(p))
}

pub fn default_sort_mode(&self) -> SortMode {
match self.default_sort.as_str() {
"Name" => SortMode::Name,
Expand All @@ -75,3 +82,17 @@ impl AppConfig {
}
}
}

fn expand_tilde(path: &str) -> PathBuf {
let rest = path.strip_prefix("~/").or_else(|| path.strip_prefix("~\\"));
if let Some(rest) = rest {
if let Some(home) = dirs::home_dir() {
return home.join(rest);
}
} else if path == "~"
&& let Some(home) = dirs::home_dir()
{
return home;
}
PathBuf::from(path)
}
23 changes: 19 additions & 4 deletions src/data/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,39 @@ impl PrismConfig {
}
}

pub fn find_prism_data_dir() -> Result<PathBuf> {
// Check environment variable first
pub fn find_prism_data_dir(config_data_dir: Option<PathBuf>) -> Result<PathBuf> {
// 1. Check environment variable first
if let Ok(path) = env::var("PRISMLAUNCHER_DATA") {
let path = PathBuf::from(path);
if path.exists() {
return Ok(path);
}
return Err(PrismError::Config(format!(
"PRISMLAUNCHER_DATA directory does not exist: {}",
path.display()
)));
}

// Standard location
// 2. Config file data_dir
if let Some(path) = config_data_dir {
if path.exists() {
return Ok(path);
}
return Err(PrismError::Config(format!(
"Configured data_dir does not exist: {}",
path.display()
)));
}

// 3. Standard platform location
if let Some(data_dir) = dirs::data_dir() {
let standard = data_dir.join("PrismLauncher");
if standard.exists() {
return Ok(standard);
}
}

// Flatpak location (Linux only)
// 4. Flatpak location (Linux only)
#[cfg(target_os = "linux")]
{
if let Some(home) = dirs::home_dir() {
Expand Down
7 changes: 4 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod view;

use app::App;
use color_eyre::Result;
use data::{PrismConfig, find_prism_data_dir};
use data::{AppConfig, PrismConfig, find_prism_data_dir};
use message::Message;
use std::time::Duration;
use tui::{Event, EventStream, Terminal};
Expand All @@ -19,9 +19,10 @@ use tui::{Event, EventStream, Terminal};
async fn main() -> Result<()> {
color_eyre::install()?;

let data_dir = find_prism_data_dir()?;
let app_config = AppConfig::load();
let data_dir = find_prism_data_dir(app_config.resolved_data_dir())?;
let config = PrismConfig::load(&data_dir)?;
let mut app = App::new(config)?;
let mut app = App::new(config, app_config)?;
let mut terminal = Terminal::new()?;
let mut events = EventStream::new(Duration::from_millis(250));

Expand Down