Custom workspace dropdown + Launch-Unreal button
Replace the ugly native <select> on the connect screen with a themed custom dropdown (Select component). Add a Launch-Unreal button that appears when the chosen working folder contains a .uproject: backend find_uproject resolves the scope to disk and searches it (and one level down); the button opens the project via the opener plugin. Bundled the UE icon (currentColor, so white-on-dark / black-on-light per theme). New strings translated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"opener:default",
|
||||
"opener:allow-open-path",
|
||||
"core:window:allow-start-dragging",
|
||||
"core:window:allow-minimize",
|
||||
"core:window:allow-toggle-maximize",
|
||||
|
||||
@ -610,6 +610,54 @@ async fn open_in_explorer(state: State<'_, AppState>, target: String) -> Result<
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Look for an Unreal `.uproject` inside the working-folder scope (resolved to a
|
||||
/// local dir via `p4 where`). Checks the folder itself and one level of subdirs.
|
||||
/// Returns the local path of the first match, or "" if the scope isn't a UE project.
|
||||
#[tauri::command]
|
||||
async fn find_uproject(state: State<'_, AppState>, scope: String) -> Result<String, String> {
|
||||
if scope.is_empty() {
|
||||
return Ok(String::new());
|
||||
}
|
||||
let conn = current(&state)?;
|
||||
let spec = format!("{}/...", scope.trim_end_matches(['/', '.']));
|
||||
let dir = match run_json(&conn, &["where", &spec])?
|
||||
.into_iter()
|
||||
.next()
|
||||
.and_then(|v| v.get("path").and_then(|p| p.as_str()).map(String::from))
|
||||
{
|
||||
Some(p) => p.trim_end_matches(['.', '/', '\\']).to_string(),
|
||||
None => return Ok(String::new()),
|
||||
};
|
||||
let is_uproject = |p: &std::path::Path| {
|
||||
p.extension().map_or(false, |x| x.eq_ignore_ascii_case("uproject"))
|
||||
};
|
||||
// the scope folder itself
|
||||
if let Ok(entries) = std::fs::read_dir(&dir) {
|
||||
let mut subdirs = Vec::new();
|
||||
for e in entries.flatten() {
|
||||
let p = e.path();
|
||||
if is_uproject(&p) {
|
||||
return Ok(p.to_string_lossy().to_string());
|
||||
}
|
||||
if p.is_dir() {
|
||||
subdirs.push(p);
|
||||
}
|
||||
}
|
||||
// one level down
|
||||
for sd in subdirs {
|
||||
if let Ok(inner) = std::fs::read_dir(&sd) {
|
||||
for e in inner.flatten() {
|
||||
let p = e.path();
|
||||
if is_uproject(&p) {
|
||||
return Ok(p.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
/// Files and metadata of a submitted changelist (History detail).
|
||||
#[tauri::command]
|
||||
async fn p4_describe(state: State<'_, AppState>, change: String) -> Result<Value, String> {
|
||||
@ -702,6 +750,7 @@ pub fn run() {
|
||||
p4_scan,
|
||||
p4_undo_change,
|
||||
open_in_explorer,
|
||||
find_uproject,
|
||||
p4_describe,
|
||||
read_file,
|
||||
read_depot,
|
||||
|
||||
Reference in New Issue
Block a user