feat(install): write launcher language marker files
Some games include a language.txt marker in the unpacked local tree, similar in spirit to account_name.txt. Installs and updates now carry the launcher language alongside the account name so those game-provided marker files are rewritten before staged files are promoted into local/. The Tauri command boundary keeps the UI setting vocabulary as de/en, then maps it to the file vocabulary expected by games: german or english. Unknown values continue through the existing DEFAULT_LANGUAGE path, so the marker file falls back to english just like script launch arguments fall back to en. The transaction layer deliberately reuses the same first-match traversal helper for both marker files. The searches stay independent, so games may place account_name.txt and language.txt in different directories if their archive layout requires that. Test Plan: - just fmt - just test - just frontend-test - just clippy - deno task build - git diff --check Refs: none
This commit is contained in:
@@ -200,6 +200,7 @@ pub async fn handle_download_game_files_command(
|
||||
file_descriptions: Vec<GameFileDescription>,
|
||||
install_after_download: bool,
|
||||
account_name: Option<String>,
|
||||
language: Option<String>,
|
||||
) {
|
||||
log::info!("Got PeerCommand::DownloadGameFiles");
|
||||
if !catalog_contains(ctx, &id).await {
|
||||
@@ -277,7 +278,7 @@ pub async fn handle_download_game_files_command(
|
||||
log::error!("Failed to send DownloadGameFilesFinished event: {e}");
|
||||
}
|
||||
if install_after_download {
|
||||
spawn_install_operation(ctx, tx_notify_ui, id.clone(), account_name);
|
||||
spawn_install_operation(ctx, tx_notify_ui, id.clone(), account_name, language);
|
||||
}
|
||||
} else {
|
||||
log::error!("No trusted peers available after majority validation for game {id}");
|
||||
@@ -364,6 +365,7 @@ pub async fn handle_download_game_files_command(
|
||||
download_id,
|
||||
prepared,
|
||||
account_name,
|
||||
language,
|
||||
)
|
||||
.await;
|
||||
} else {
|
||||
@@ -422,8 +424,9 @@ pub async fn handle_install_game_command(
|
||||
tx_notify_ui: &UnboundedSender<PeerEvent>,
|
||||
id: String,
|
||||
account_name: Option<String>,
|
||||
language: Option<String>,
|
||||
) {
|
||||
spawn_install_operation(ctx, tx_notify_ui, id, account_name);
|
||||
spawn_install_operation(ctx, tx_notify_ui, id, account_name, language);
|
||||
}
|
||||
|
||||
/// Handles the `UninstallGame` command.
|
||||
@@ -471,11 +474,12 @@ fn spawn_install_operation(
|
||||
tx_notify_ui: &UnboundedSender<PeerEvent>,
|
||||
id: String,
|
||||
account_name: Option<String>,
|
||||
language: Option<String>,
|
||||
) {
|
||||
let ctx = ctx.clone();
|
||||
let tx_notify_ui = tx_notify_ui.clone();
|
||||
ctx.task_tracker.clone().spawn(async move {
|
||||
run_install_operation(&ctx, &tx_notify_ui, id, account_name).await;
|
||||
run_install_operation(&ctx, &tx_notify_ui, id, account_name, language).await;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -484,6 +488,7 @@ async fn run_install_operation(
|
||||
tx_notify_ui: &UnboundedSender<PeerEvent>,
|
||||
id: String,
|
||||
account_name: Option<String>,
|
||||
language: Option<String>,
|
||||
) {
|
||||
let Some(prepared) = prepare_install_operation(ctx, tx_notify_ui, &id).await else {
|
||||
return;
|
||||
@@ -494,7 +499,7 @@ async fn run_install_operation(
|
||||
return;
|
||||
}
|
||||
|
||||
run_started_install_operation(ctx, tx_notify_ui, id, prepared, account_name).await;
|
||||
run_started_install_operation(ctx, tx_notify_ui, id, prepared, account_name, language).await;
|
||||
}
|
||||
|
||||
struct PreparedInstallOperation {
|
||||
@@ -547,6 +552,7 @@ async fn run_started_install_operation(
|
||||
id: String,
|
||||
prepared: PreparedInstallOperation,
|
||||
account_name: Option<String>,
|
||||
language: Option<String>,
|
||||
) {
|
||||
let PreparedInstallOperation {
|
||||
game_root,
|
||||
@@ -577,6 +583,7 @@ async fn run_started_install_operation(
|
||||
&id,
|
||||
ctx.unpacker.clone(),
|
||||
account_name.as_deref(),
|
||||
language.as_deref(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -587,6 +594,7 @@ async fn run_started_install_operation(
|
||||
&id,
|
||||
ctx.unpacker.clone(),
|
||||
account_name.as_deref(),
|
||||
language.as_deref(),
|
||||
)
|
||||
.await
|
||||
}
|
||||
@@ -1503,7 +1511,7 @@ mod tests {
|
||||
update_and_announce_games(&ctx, &tx, scan).await;
|
||||
assert_local_update(recv_event(&mut rx).await, true, true);
|
||||
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None).await;
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None, None).await;
|
||||
|
||||
assert_active_update(
|
||||
recv_event(&mut rx).await,
|
||||
@@ -1534,7 +1542,7 @@ mod tests {
|
||||
let ctx = test_ctx(temp.path().to_path_buf());
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None).await;
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None, None).await;
|
||||
|
||||
assert_active_update(
|
||||
recv_event(&mut rx).await,
|
||||
@@ -1588,7 +1596,8 @@ mod tests {
|
||||
.await
|
||||
);
|
||||
clear_active_download(&ctx, "game").await;
|
||||
run_started_install_operation(&ctx, &tx, "game".to_string(), prepared, None).await;
|
||||
run_started_install_operation(&ctx, &tx, "game".to_string(), prepared, None, None)
|
||||
.await;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1655,7 +1664,7 @@ mod tests {
|
||||
let ctx = test_ctx(temp.path().to_path_buf());
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None).await;
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None, None).await;
|
||||
|
||||
assert_active_update(
|
||||
recv_event(&mut rx).await,
|
||||
@@ -1687,7 +1696,7 @@ mod tests {
|
||||
let ctx = test_ctx(temp.path().to_path_buf());
|
||||
let (tx, mut rx) = mpsc::unbounded_channel();
|
||||
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None).await;
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None, None).await;
|
||||
assert_active_update(
|
||||
recv_event(&mut rx).await,
|
||||
active_update("game", ActiveOperationKind::Installing),
|
||||
@@ -1710,7 +1719,7 @@ mod tests {
|
||||
write_file(&root.join("version.ini"), b"20250101");
|
||||
write_file(&root.join("game.eti"), b"new archive");
|
||||
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None).await;
|
||||
run_install_operation(&ctx, &tx, "game".to_string(), None, None).await;
|
||||
assert_active_update(
|
||||
recv_event(&mut rx).await,
|
||||
active_update("game", ActiveOperationKind::Updating),
|
||||
|
||||
Reference in New Issue
Block a user