v1.1.0 — chemin Blender configurable depuis l'UI

Refonte de PathResolver : auto-detection systeme (which/where + chemins courants),
persistance du chemin dans userData, validation du fichier.
Ajout d'un modal Bootstrap pour configurer le chemin manuellement.
Badge vert/rouge dans la navbar indiquant le statut Blender.
Le modal s'ouvre automatiquement si Blender n'est pas trouve au lancement.
Suppression de extraResources (plus de Blender embarque dans le build).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
sorlinv
2026-02-25 16:44:04 +01:00
parent f31f5aa605
commit d5cb63a27b
8 changed files with 393 additions and 38 deletions

View File

@@ -0,0 +1,197 @@
const BlenderPath = {
str_current_path: null,
is_found: false,
obj_modal: null,
init: () => {
BlenderPath._create_badge();
BlenderPath._create_modal();
BlenderPath._bind_events();
},
_create_badge: () => {
let obj_nav_right = document.querySelector("nav .d-flex.gap-2");
let obj_badge = document.createElement("button");
obj_badge.id = "btn_blender_status";
obj_badge.className = "btn btn-sm btn-outline-secondary";
obj_badge.title = "Chemin Blender";
obj_badge.innerHTML = '<i class="mdi mdi-blender-software"></i>';
obj_nav_right.insertBefore(obj_badge, obj_nav_right.firstChild);
obj_badge.addEventListener("click", () => {
BlenderPath._open_modal();
});
},
_create_modal: () => {
let obj_modal_el = document.createElement("div");
obj_modal_el.id = "modal_blender_path";
obj_modal_el.className = "modal fade";
obj_modal_el.tabIndex = -1;
obj_modal_el.innerHTML =
'<div class="modal-dialog modal-dialog-centered">' +
'<div class="modal-content bg-dark text-light border-secondary">' +
'<div class="modal-header border-secondary">' +
'<h6 class="modal-title"><i class="mdi mdi-blender-software me-2"></i>Chemin Blender</h6>' +
'<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>' +
'</div>' +
'<div class="modal-body">' +
'<p class="text-light-emphasis mb-3" style="font-size: 0.85rem;">' +
'Selectionnez l\'executable Blender sur votre machine.' +
'</p>' +
'<div class="input-group input-group-sm mb-3">' +
'<input type="text" id="input_blender_path" class="form-control bg-dark text-light border-secondary" placeholder="Aucun chemin configure" readonly>' +
'<button id="btn_browse_blender" class="btn btn-outline-primary" type="button">' +
'<i class="mdi mdi-folder-search-outline"></i> Parcourir' +
'</button>' +
'</div>' +
'<div class="d-flex justify-content-between align-items-center">' +
'<button id="btn_detect_blender" class="btn btn-sm btn-outline-secondary">' +
'<i class="mdi mdi-magnify me-1"></i>Detecter automatiquement' +
'</button>' +
'<span id="label_blender_status" class="badge bg-danger">' +
'<i class="mdi mdi-close-circle me-1"></i>Non trouve' +
'</span>' +
'</div>' +
'</div>' +
'<div class="modal-footer border-secondary">' +
'<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Annuler</button>' +
'<button id="btn_validate_blender" type="button" class="btn btn-sm btn-primary" disabled>' +
'<i class="mdi mdi-check me-1"></i>Valider' +
'</button>' +
'</div>' +
'</div>' +
'</div>';
document.body.appendChild(obj_modal_el);
BlenderPath.obj_modal = new bootstrap.Modal(obj_modal_el);
},
_bind_events: () => {
let obj_btn_browse = document.getElementById("btn_browse_blender");
obj_btn_browse.addEventListener("click", () => {
BlenderPath._browse();
});
let obj_btn_detect = document.getElementById("btn_detect_blender");
obj_btn_detect.addEventListener("click", () => {
BlenderPath._detect();
});
let obj_btn_validate = document.getElementById("btn_validate_blender");
obj_btn_validate.addEventListener("click", () => {
BlenderPath._validate();
});
window.api.on_blender_path_status((obj_data) => {
BlenderPath.str_current_path = obj_data.str_path;
BlenderPath.is_found = obj_data.is_found;
BlenderPath._update_badge();
if (!obj_data.is_found) {
BlenderPath._open_modal();
}
});
},
_open_modal: () => {
let obj_input = document.getElementById("input_blender_path");
obj_input.value = BlenderPath.is_found ? BlenderPath.str_current_path : "";
BlenderPath._update_modal_status(BlenderPath.is_found, BlenderPath.str_current_path);
BlenderPath.obj_modal.show();
if (!BlenderPath.is_found) {
BlenderPath._detect();
}
},
_browse: () => {
window.api.select_blender_exe()
.then((str_path) => {
if (!str_path) {
return;
}
let obj_input = document.getElementById("input_blender_path");
obj_input.value = str_path;
BlenderPath._update_modal_status(true, str_path);
})
.catch((obj_err) => {
ConsoleLog.add("Erreur selection Blender : " + obj_err.message);
});
},
_detect: () => {
let obj_btn = document.getElementById("btn_detect_blender");
obj_btn.disabled = true;
obj_btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Detection...';
window.api.get_blender_path()
.then((obj_data) => {
obj_btn.disabled = false;
obj_btn.innerHTML = '<i class="mdi mdi-magnify me-1"></i>Detecter automatiquement';
if (obj_data.is_found) {
let obj_input = document.getElementById("input_blender_path");
obj_input.value = obj_data.str_path;
BlenderPath._update_modal_status(true, obj_data.str_path);
} else {
BlenderPath._update_modal_status(false, null);
}
})
.catch(() => {
obj_btn.disabled = false;
obj_btn.innerHTML = '<i class="mdi mdi-magnify me-1"></i>Detecter automatiquement';
BlenderPath._update_modal_status(false, null);
});
},
_validate: () => {
let str_path = document.getElementById("input_blender_path").value;
if (!str_path) {
return;
}
window.api.set_blender_path(str_path)
.then((obj_result) => {
if (obj_result.is_success) {
BlenderPath.str_current_path = obj_result.str_path;
BlenderPath.is_found = true;
BlenderPath._update_badge();
BlenderPath.obj_modal.hide();
ConsoleLog.add("Chemin Blender configure : " + obj_result.str_path);
} else {
BlenderPath._update_modal_status(false, null);
ConsoleLog.add("Chemin Blender invalide : " + (obj_result.str_error || ""));
}
})
.catch((obj_err) => {
ConsoleLog.add("Erreur configuration Blender : " + obj_err.message);
});
},
_update_badge: () => {
let obj_badge = document.getElementById("btn_blender_status");
if (BlenderPath.is_found) {
obj_badge.className = "btn btn-sm btn-outline-success";
obj_badge.title = "Blender : " + BlenderPath.str_current_path;
} else {
obj_badge.className = "btn btn-sm btn-outline-danger";
obj_badge.title = "Blender non trouve";
}
},
_update_modal_status: (is_valid, str_path) => {
let obj_label = document.getElementById("label_blender_status");
let obj_btn_validate = document.getElementById("btn_validate_blender");
if (is_valid && str_path) {
obj_label.className = "badge bg-success";
obj_label.innerHTML = '<i class="mdi mdi-check-circle me-1"></i>Trouve';
obj_btn_validate.disabled = false;
} else {
obj_label.className = "badge bg-danger";
obj_label.innerHTML = '<i class="mdi mdi-close-circle me-1"></i>Non trouve';
obj_btn_validate.disabled = true;
}
},
};