Skip to content

Commit 5213655

Browse files
committed
Sweep kernel pour openness +/- (gain ~2x), fix warp mbtiles (coins noirs faute de nodata CRS), fix GUI freeze reprise VM (offset log non persiste), fix bbox_l93 obsolete (tests), --sync-only pour choisir ombrages/carte au rapatriement VM
1 parent fbebec2 commit 5213655

7 files changed

Lines changed: 460 additions & 55 deletions

File tree

gui/app.js

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ const I18N = {
4444
"remote.mode.label":"Reprise", "remote.mode.reconnect":"Se rebrancher",
4545
"remote.mode.resume":"Reprendre (garde le cache)", "remote.mode.restart":"Relancer depuis zéro",
4646
"tip.remotemode":"Que faire si la session existe déjà : « Se rebrancher » surveille le run en cours ou déjà terminé sans rien relancer ; « Reprendre » relance le même calcul dans la session en gardant les dalles déjà en cache (ne retélécharge que celles manquantes ou en erreur) ; « Relancer depuis zéro » archive l'état existant puis redémarre tout le calcul, cache compris.",
47+
"remote.sync.label":"Résultats", "remote.sync.tout":"Tout",
48+
"remote.sync.carte":"Carte seule", "remote.sync.ombrages":"Ombrages seuls",
49+
"tip.remotesync":"Quels fichiers rapatrier localement au fur et à mesure : tout (défaut), seulement la carte finale (mbtiles/rmap/sqlitedb) ou seulement les ombrages intermédiaires (.tif).",
4750
"remote.block":"Bloc", "tip.remoteblock":"Répartit une zone géographique sur plusieurs VM : chaque machine traite un bloc différent (LiDAR uniquement). Laisser vide pour tout traiter sur cette VM.",
4851
"remote.hint.cli":"Lance ce calcul dans tmux sur la VM et resynchronise progressivement les résultats (log distant inclus). « Arrêter » ne coupe que la surveillance locale, pas le calcul distant.",
4952
"remote.hint.gui":"Installe un bureau XFCE + RDP sur la VM puis ouvre le client RDP. Les autres paramètres de ce formulaire sont ignorés.",
@@ -200,6 +203,9 @@ const I18N = {
200203
"remote.mode.label":"Resume", "remote.mode.reconnect":"Reattach only",
201204
"remote.mode.resume":"Resume (keep cache)", "remote.mode.restart":"Restart from scratch",
202205
"tip.remotemode":"What to do if the session already exists: “Reattach only” just monitors the run in progress or already finished, without relaunching anything; “Resume” reruns the same job in the same session keeping already-cached tiles (only re-downloads missing or failed ones); “Restart from scratch” archives the existing state then restarts the whole job, cache included.",
206+
"remote.sync.label":"Results", "remote.sync.tout":"Everything",
207+
"remote.sync.carte":"Map only", "remote.sync.ombrages":"Shadings only",
208+
"tip.remotesync":"Which files to sync back locally as they are produced: everything (default), only the final map (mbtiles/rmap/sqlitedb), or only the intermediate shadings (.tif).",
203209
"remote.block":"Block", "tip.remoteblock":"Splits a geographic area across several VMs: each machine processes a different block (LiDAR only). Leave empty to process the whole area on this VM.",
204210
"remote.hint.cli":"Runs this job in tmux on the VM and progressively syncs results back (remote log included). Stop only cancels local monitoring, not the remote job.",
205211
"remote.hint.gui":"Installs an XFCE + RDP desktop on the VM then opens the RDP client. The rest of this form is ignored.",
@@ -376,7 +382,7 @@ function setLang(code, persist){
376382
}
377383

378384
// ── Panneau de log ───────────────────────────────────────────────────────────
379-
function ajouterLigneLog(text, tag) {
385+
function ajouterLigneLog(text, tag, deferScroll) {
380386
const c = document.getElementById('log-content');
381387
if (!c) return;
382388
// Sémantique \r du terminal : la ligne de progression temporaire (barres
@@ -388,29 +394,41 @@ function ajouterLigneLog(text, tag) {
388394
span.className = 'log-' + (tag || 'ok');
389395
span.textContent = text;
390396
c.appendChild(span);
391-
// Auto-scroll si l'utilisateur est déjà en bas (à 30 px près)
397+
// deferScroll=true : appelant en boucle sur un lot (cf. poll_log) — le
398+
// scroll/purge est fait une seule fois après la boucle via finaliserLog(),
399+
// pas à chaque ligne (chaque lecture de scrollHeight force un reflow
400+
// synchrone ; sur un burst de plusieurs milliers de lignes d'un coup,
401+
// reconnexion VM notamment, ça figeait le panneau, bug vécu 2026-08-05).
402+
if (!deferScroll) finaliserLog();
403+
}
404+
405+
// Auto-scroll (si déjà en bas, 30 px près) + purge (~5000 lignes, évite de
406+
// saturer le DOM sur les longs runs). Appelé une seule fois par lot de
407+
// poll_log plutôt qu'à chaque ligne/repaint de progression : cf.
408+
// ajouterLigneLog/majLigneProgression.
409+
function finaliserLog() {
410+
const c = document.getElementById('log-content');
411+
if (!c) return;
392412
const isAtBottom = (c.scrollHeight - c.scrollTop - c.clientHeight) < 30;
393413
if (isAtBottom) c.scrollTop = c.scrollHeight;
394-
// Limiter à ~5000 lignes pour éviter de saturer le DOM sur les longs runs
395414
while (c.children.length > 5000) c.removeChild(c.firstChild);
396415
}
397416

398417
// Ligne de progression "en place" dans le panneau de log : équivalent du \r
399418
// terminal. Sans elle, pendant un long download le panneau paraît figé (la
400419
// barre ne vivait que dans le footer) : constaté sur un download Lyon de 3 min.
401-
function majLigneProgression(label) {
420+
function majLigneProgression(label, deferScroll) {
402421
const c = document.getElementById('log-content');
403422
if (!c || !label) return;
404423
let el = document.getElementById('log-progress-line');
405-
const atBottom = (c.scrollHeight - c.scrollTop - c.clientHeight) < 30;
406424
if (!el) {
407425
el = document.createElement('span');
408426
el.id = 'log-progress-line';
409427
el.className = 'log-ok';
410428
c.appendChild(el);
411429
}
412430
el.textContent = label;
413-
if (atBottom) c.scrollTop = c.scrollHeight;
431+
if (!deferScroll) finaliserLog();
414432
}
415433

416434
function viderLog() {
@@ -1823,6 +1841,9 @@ function getConfig() {
18231841
// garde le cache), "restart" = archiver puis repartir de zéro (--restart)
18241842
// côté rlidar2map_CLI ; cf. _wrap_remote_cmd côté Python.
18251843
remote_mode: g('f-remote-mode')?.value || '',
1844+
// "tout" (défaut, comportement inchangé) ; "carte"/"ombrages" limitent
1845+
// le rapatriement (--sync-only) côté rlidar2map_CLI, cf. _wrap_remote_cmd.
1846+
remote_sync_only: g('f-remote-sync-only')?.value || 'tout',
18261847
// Sharding multi-VM (--block i/M) : combiné en une seule chaîne ici, les
18271848
// deux champs numériques ne sont qu'une commodité de saisie côté GUI.
18281849
remote_block: (() => {
@@ -2034,6 +2055,7 @@ function loadConfig(cfg) {
20342055
s('f-remote-identity', cfg.remote_identity);
20352056
s('f-remote-session', cfg.remote_session);
20362057
s('f-remote-mode', cfg.remote_mode);
2058+
s('f-remote-sync-only', cfg.remote_sync_only || 'tout');
20372059
if (cfg.remote_block && cfg.remote_block.includes('/')) {
20382060
const [bi, bm] = cfg.remote_block.split('/');
20392061
s('f-remote-block-i', bi);
@@ -2591,20 +2613,26 @@ function executerCfg(cfg, silent) {
25912613
polling = setInterval(async () => {
25922614
const r = await pywebview.api.poll_log();
25932615
if (r.items) {
2616+
// deferScroll=true partout dans la boucle : un seul reflow/scroll
2617+
// via finaliserLog() pour tout le lot, pas un par ligne (cf.
2618+
// ajouterLigneLog) — sinon un burst de milliers d'items d'un coup
2619+
// (reconnexion VM notamment) fige le panneau le temps de tout
2620+
// digérer.
25942621
r.items.forEach(item => {
2595-
if (item.line !== undefined) ajouterLigneLog(item.line, item.tag || 'ok');
2622+
if (item.line !== undefined) ajouterLigneLog(item.line, item.tag || 'ok', true);
25962623
if (item.pct !== undefined && item.pct >= 0) {
25972624
setLogProgress(item.pct, '');
25982625
document.getElementById('footer-status').textContent =
25992626
item.pct + '% ' + (item.label || '').substring(0, 80);
2600-
majLigneProgression(item.label);
2627+
majLigneProgression(item.label, true);
26012628
}
26022629
if (item.pct === -1 && item.label) {
26032630
document.getElementById('footer-status').textContent =
26042631
item.label.substring(0, 100);
2605-
majLigneProgression(item.label);
2632+
majLigneProgression(item.label, true);
26062633
}
26072634
});
2635+
if (r.items.length) finaliserLog();
26082636
}
26092637
if (r.done) {
26102638
clearInterval(polling); polling = null;

gui/index.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,13 @@
136136
<option value="resume" data-i18n="remote.mode.resume">Reprendre (garde le cache)</option>
137137
<option value="restart" data-i18n="remote.mode.restart">Relancer depuis zéro</option>
138138
</select>
139+
<label style="min-width:auto;margin-left:10px" data-i18n="remote.sync.label"
140+
data-i18n-title="tip.remotesync" title="Quels fichiers rapatrier localement au fur et à mesure : tout (défaut), seulement la carte finale (mbtiles/rmap/sqlitedb) ou seulement les ombrages intermédiaires (.tif).">Résultats</label>
141+
<select id="f-remote-sync-only">
142+
<option value="tout" data-i18n="remote.sync.tout">Tout</option>
143+
<option value="carte" data-i18n="remote.sync.carte">Carte seule</option>
144+
<option value="ombrages" data-i18n="remote.sync.ombrages">Ombrages seuls</option>
145+
</select>
139146
<label style="min-width:auto;margin-left:10px" data-i18n="remote.block"
140147
data-i18n-title="tip.remoteblock" title="Répartit une zone géographique sur plusieurs VM : chaque machine traite un bloc différent (LiDAR uniquement). Laisser vide pour tout traiter sur cette VM.">Bloc</label>
141148
<input type="number" id="f-remote-block-i" min="1" placeholder="i" style="max-width:45px">

0 commit comments

Comments
 (0)