signalk-mareas-ihm 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/dist/build-info.json +4 -4
- package/dist/index.js +41 -5
- package/dist/mobile.html +169 -8
- package/package.json +6 -6
- package/public/mobile.html +169 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [2.3.1] - 2026-06-23
|
|
4
|
+
|
|
5
|
+
### English
|
|
6
|
+
|
|
7
|
+
**Skipper feedback round 1 (Vicente / Tunatunes Vigo)**
|
|
8
|
+
|
|
9
|
+
- **New bottom-bar widget "Drop to LW"** — large number = how many centimetres the tide will drop until the next low water (negative). Sub-label = expected final depth. Visible permanently (not only on grounding alert). Lets you decide whether to anchor with enough margin.
|
|
10
|
+
- **New bottom-bar widget "At LW"** — large number = expected depth at next low water (consistent with the main SONDA cell, raw sensor reference, not below-surface). Sub-label = LW time. Amber if <2m, red if <1m.
|
|
11
|
+
- **Depth cell sub-label rewritten** — now compact "(final X.X m)" in parentheses below the depth reading. Coherent with the new widgets above.
|
|
12
|
+
- **Bottom-bar config bug fixed** — disabling and re-enabling cells in the config UI now actually persists. The backend whitelist was filtering out new keys silently.
|
|
13
|
+
- **Left arrow of bottom-bar always visible** when the bar is open, matching the right arrow. Previously the left arrow hid when no horizontal scroll was available, getting covered by the bar.
|
|
14
|
+
|
|
15
|
+
**Signal K data hygiene (skipper feedback)**
|
|
16
|
+
|
|
17
|
+
- `environment.tide.vessel.finalExpctDepthBKeel` — **fixed historic bug**: the path name said "below keel" but the value was actually "below surface" (off by the boat's draft). Now finally publishes the real below-keel value.
|
|
18
|
+
- `environment.tide.finalExpctDepthBKeelResume` — same fix applied to the text summary "Min. depth X m at HH:MM".
|
|
19
|
+
- New: `environment.tide.expectedDropToLW` (m) — how much the tide will drop until next low water.
|
|
20
|
+
- New: `environment.depth.belowKeelExpectedAtLW` (m) — expected depth under keel at next LW.
|
|
21
|
+
- Removed `environment.depth.belowSurfaceExpectedAtLW` (it was confusing — skipper asked for below-keel only).
|
|
22
|
+
|
|
23
|
+
**Dep hygiene**
|
|
24
|
+
- `@signalk/server-api` range tagged with explicit patch `^2.0.0` (was `^2.0`) — cosmetic, fixes Socket.dev "floating dependency" warning. NPM resolution unchanged.
|
|
25
|
+
|
|
26
|
+
### Español
|
|
27
|
+
|
|
28
|
+
**Feedback navegante ronda 1 (Vicente / Tunatunes Vigo)**
|
|
29
|
+
|
|
30
|
+
- **Nuevo widget bottom-bar "Dif. Bajamar"** — número grande = cuántos centímetros bajará la marea hasta la próxima bajamar (negativo). Sub-label = profundidad final esperada. Visible permanentemente (no solo cuando hay alerta de varada). Permite decidir si fondear con margen suficiente.
|
|
31
|
+
- **Nuevo widget bottom-bar "En B.M."** — número grande = profundidad esperada en la próxima bajamar (coherente con la celda SONDA principal, referencia del sensor crudo, no bajo superficie). Sub-label = hora de la bajamar. Ámbar si <2m, rojo si <1m.
|
|
32
|
+
- **Sub-label de la celda Sonda reescrito** — ahora compacto "(final X.X m)" entre paréntesis bajo el valor de sonda. Coherente con los nuevos widgets.
|
|
33
|
+
- **Bug del config del bottom-bar arreglado** — desactivar y reactivar celdas en el config UI ahora persiste de verdad. El backend filtraba silenciosamente las claves nuevas.
|
|
34
|
+
- **Flecha izquierda del bottom-bar siempre visible** cuando la barra está abierta, igual que la derecha. Antes solo aparecía si había scroll horizontal posible, quedando tapada por la barra.
|
|
35
|
+
|
|
36
|
+
**Limpieza de datos en Signal K (feedback navegante)**
|
|
37
|
+
|
|
38
|
+
- `environment.tide.vessel.finalExpctDepthBKeel` — **bug histórico corregido**: el nombre del path decía "bajo quilla" pero el valor era "bajo superficie" (desfase = calado del barco). Ahora por fin publica el valor real bajo quilla.
|
|
39
|
+
- `environment.tide.finalExpctDepthBKeelResume` — el mismo fix aplicado al resumen textual "Prof. mínima X m a las HH:MM".
|
|
40
|
+
- Nuevo: `environment.tide.expectedDropToLW` (m) — cuánto bajará la marea hasta la próxima bajamar.
|
|
41
|
+
- Nuevo: `environment.depth.belowKeelExpectedAtLW` (m) — sonda esperada bajo quilla en la próxima bajamar.
|
|
42
|
+
- Eliminado `environment.depth.belowSurfaceExpectedAtLW` (creaba confusión — el navegante pidió solo bajo quilla).
|
|
43
|
+
|
|
44
|
+
**Limpieza de deps**
|
|
45
|
+
- `@signalk/server-api` rango etiquetado con patch explícito `^2.0.0` (antes `^2.0`) — cosmético, resuelve el aviso "floating dependency" de Socket.dev. Resolución de NPM idéntica.
|
|
46
|
+
|
|
3
47
|
## [2.3.0] - 2026-06-22
|
|
4
48
|
|
|
5
49
|
### English
|
package/dist/build-info.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.3.
|
|
3
|
-
"timestamp": "
|
|
4
|
-
"gitHash": "
|
|
2
|
+
"version": "2.3.1",
|
|
3
|
+
"timestamp": "20260623-0211",
|
|
4
|
+
"gitHash": "1fe769e",
|
|
5
5
|
"gitDirty": false,
|
|
6
|
-
"builtAt": "2026-06-
|
|
6
|
+
"builtAt": "2026-06-23T00:11:05.914Z"
|
|
7
7
|
}
|
package/dist/index.js
CHANGED
|
@@ -49,7 +49,7 @@ function isPositionValue(v) {
|
|
|
49
49
|
// timestamp + git hash so we can verify exactly which build is running on the Pi
|
|
50
50
|
// without ambiguity. ("¿Qué versión tengo deployada?" → /api/paths or landing.)
|
|
51
51
|
const PLUGIN_VERSION = esmRequire("../package.json").version;
|
|
52
|
-
const PLUGIN_REVISION = "
|
|
52
|
+
const PLUGIN_REVISION = "Rev492";
|
|
53
53
|
// Rev478 (C-17): schemaVersion=2. Introduce bloque `grounding` (FSM Physics/
|
|
54
54
|
// Config/Notification de Rev477) y `gpsAgeMs` (C-12). Frontend cacheado con
|
|
55
55
|
// expected=1 debe forzar reload. SERVER_INSTANCE_ID detecta restart vivo del
|
|
@@ -297,7 +297,10 @@ const MAX_SIDE_BUTTONS_PER_SIDE = 5;
|
|
|
297
297
|
// Whitelist de keys soportadas. Cualquier key NO en este set se descarta.
|
|
298
298
|
// El orden recibido define el orden de pintado; las celdas no listadas se ocultan.
|
|
299
299
|
// Whitelist incluye celdas opt-in (sunrise, wx_6h, wave) que NO van en defaults.
|
|
300
|
-
|
|
300
|
+
/* Rev491 (feedback Vicente): añadidas dif_lw y prof_min a la whitelist del
|
|
301
|
+
backend. Sin esto, sanitizeBBOrder() las filtraba al guardar, haciendo que
|
|
302
|
+
no se pudieran reactivar tras desactivarlas en config. */
|
|
303
|
+
const BB_CELL_KEYS = ["sog", "heading", "wind", "sonda", "dif_lw", "prof_min", "tide", "pres", "abrigo", "calidad", "cad_rec", "dist_ancla", "h_fondeo", "sunrise", "wx_6h", "wave"];
|
|
301
304
|
const DEFAULT_BB_ORDER = ["sog", "heading", "wind", "sonda", "tide", "pres", "abrigo", "calidad", "cad_rec", "dist_ancla", "h_fondeo"];
|
|
302
305
|
function sanitizeBBOrder(arr) {
|
|
303
306
|
if (!Array.isArray(arr))
|
|
@@ -5260,6 +5263,13 @@ self.addEventListener("fetch", (e) => { /* no-op: pass through to network */ });
|
|
|
5260
5263
|
risk: !!_currentGroundingRisk.risk,
|
|
5261
5264
|
physicalRisk: !!_currentGroundingRisk.physicalRisk,
|
|
5262
5265
|
expectedMinDepthM: _currentGroundingRisk.expectedMinDepth ?? null,
|
|
5266
|
+
// Rev488 (feedback Vicente): "Bajará máximo X cm" — la magnitud que el
|
|
5267
|
+
// navegante usa para decidir si fondea con margen suficiente. El evaluator
|
|
5268
|
+
// ya lo calcula como remainingDrop = tideNow - nextLowHeight. Lo exponemos
|
|
5269
|
+
// siempre (no solo cuando hay riesgo) para que el bottom-bar muestre el
|
|
5270
|
+
// sub-label permanente.
|
|
5271
|
+
remainingDropM: _currentGroundingRisk.remainingDrop ?? null,
|
|
5272
|
+
depthNowM: _currentGroundingRisk.depthNow ?? null,
|
|
5263
5273
|
effectiveDraftM: _currentGroundingRisk.effectiveDraft ?? null,
|
|
5264
5274
|
safetyMarginM: _currentGroundingRisk.safetyMargin ?? null,
|
|
5265
5275
|
nextLowTimeIso: _currentGroundingRisk.nextLowTime ?? null,
|
|
@@ -10842,9 +10852,35 @@ self.addEventListener("fetch", (e) => { /* no-op: pass through to network */ });
|
|
|
10842
10852
|
// v1.127: ALWAYS reflects physical reality, regardless of whether alarm is enabled.
|
|
10843
10853
|
// This is what KIP/external instruments need. Alarm state is in groundingAlarm.
|
|
10844
10854
|
vesselValues.push({ path: "environment.tide.vessel.groundingRisk", value: physicalRisk });
|
|
10845
|
-
//
|
|
10846
|
-
|
|
10847
|
-
|
|
10855
|
+
// Rev489-491 (feedback Vicente): publicar SOLO valores BELOW KEEL en SK.
|
|
10856
|
+
// Vicente: "Elimina todos los datos que sean SURFACE, lo que nos interesa
|
|
10857
|
+
// es el dato Below keel o below transducer (que debera ser elegido en la
|
|
10858
|
+
// configuracion). Por ahora belowKeel."
|
|
10859
|
+
//
|
|
10860
|
+
// Paths publicados:
|
|
10861
|
+
// environment.tide.expectedDropToLW = bajada hasta proxima bajamar (m)
|
|
10862
|
+
// environment.depth.belowKeelExpectedAtLW = sonda final esperada bajo
|
|
10863
|
+
// quilla (m). Coherente con environment.depth.belowKeel actual.
|
|
10864
|
+
// environment.tide.vessel.finalExpctDepthBKeel = MISMO valor que
|
|
10865
|
+
// belowKeelExpectedAtLW. Compatibilidad con KIP/integraciones que ya
|
|
10866
|
+
// usaban este path historico. CORREGIDO Rev491: antes publicaba el
|
|
10867
|
+
// valor belowSurface por bug historico (el nombre era BKeel pero el
|
|
10868
|
+
// valor era surface). Ahora corregido a belowKeel real.
|
|
10869
|
+
//
|
|
10870
|
+
// SK paths ELIMINADOS Rev491 (eran SURFACE, confusion garantizada):
|
|
10871
|
+
// environment.depth.belowSurfaceExpectedAtLW
|
|
10872
|
+
if (remainingDrop != null) {
|
|
10873
|
+
vesselValues.push({ path: "environment.tide.expectedDropToLW", value: Math.round(remainingDrop * 100) / 100 });
|
|
10874
|
+
}
|
|
10875
|
+
if (expectedMinDepth != null && typeof draft === "number" && draft > 0) {
|
|
10876
|
+
/* CUIDADO: baseDraft incluye el safetyMargin. Para belowKeel real
|
|
10877
|
+
restamos SOLO el calado, no el baseDraft. */
|
|
10878
|
+
const belowKeelAtLW = Math.round((expectedMinDepth - draft) * 100) / 100;
|
|
10879
|
+
vesselValues.push({ path: "environment.depth.belowKeelExpectedAtLW", value: belowKeelAtLW });
|
|
10880
|
+
/* Path historico — ahora publica el MISMO valor (belowKeel real) para
|
|
10881
|
+
que finalmente haga honor a su nombre "BKeel". */
|
|
10882
|
+
vesselValues.push({ path: "environment.tide.vessel.finalExpctDepthBKeel", value: belowKeelAtLW });
|
|
10883
|
+
}
|
|
10848
10884
|
// v1.127: NEW — Free water between effective draft and seabed at next low tide.
|
|
10849
10885
|
// Positive = safe clearance. Negative = GROUNDING (keel below seabed).
|
|
10850
10886
|
if (expectedMinDepth != null && eff != null) {
|
package/dist/mobile.html
CHANGED
|
@@ -1892,6 +1892,22 @@ body.mobile-ui #shelter-hours .sh-hr{flex:0 0 60px!important}
|
|
|
1892
1892
|
<span class="vl" id="m-bb-tide-val">—</span>
|
|
1893
1893
|
<span id="m-bb-tide-next" style="display:block;font-size:10px;font-weight:800;margin-top:1px;line-height:1;color:#cde">—</span>
|
|
1894
1894
|
</div>
|
|
1895
|
+
<!-- Rev489 (feedback Vicente): widget "Dif. Bajamar" — cuánto bajará la
|
|
1896
|
+
marea hasta la próxima bajamar (cm). Click abre modal Cálculo Sonda. -->
|
|
1897
|
+
<div class="it" data-bb-cell="dif_lw" data-i18n-title="bb_dif_lw_tip" title="Diferencia hasta próxima bajamar · click → Cálculo Sonda" onclick="openPopup&&openPopup('sonda-pop');typeof fetchSondaData==='function'&&fetchSondaData()">
|
|
1898
|
+
<span class="lb" data-i18n="bb_dif_lw">Dif. Bajamar</span>
|
|
1899
|
+
<span class="vl" id="m-bb-dif-lw">—</span>
|
|
1900
|
+
<span id="m-bb-dif-lw-end" style="display:block;font-size:10px;font-weight:800;margin-top:1px;line-height:1;color:#cde">—</span>
|
|
1901
|
+
</div>
|
|
1902
|
+
<!-- Rev490 (feedback Vicente): widget "Prof. Mínima" — sonda esperada en la
|
|
1903
|
+
próxima bajamar. Numero grande = profundidad final en metros (coherente
|
|
1904
|
+
con el numero grande de SONDA, misma referencia). Sub-label = hora de la
|
|
1905
|
+
proxima bajamar. Click abre modal Cálculo Sonda. -->
|
|
1906
|
+
<div class="it" data-bb-cell="prof_min" data-i18n-title="bb_prof_min_tip" title="Profundidad mínima esperada en la próxima bajamar · click → Cálculo Sonda" onclick="openPopup&&openPopup('sonda-pop');typeof fetchSondaData==='function'&&fetchSondaData()">
|
|
1907
|
+
<span class="lb" data-i18n="bb_prof_min">Prof. mín.</span>
|
|
1908
|
+
<span class="vl" id="m-bb-prof-min">—</span>
|
|
1909
|
+
<span id="m-bb-prof-min-when" style="display:block;font-size:10px;font-weight:800;margin-top:1px;line-height:1;color:#cde">—</span>
|
|
1910
|
+
</div>
|
|
1895
1911
|
<div class="it" data-bb-cell="cad_rec" data-i18n-title="bb_cadena_tip" title="Cadena recomendada" onclick="m_openInfoModal&&m_openInfoModal()"><span class="lb" data-i18n="bb_cadena_rec">Cadena rec.</span><span class="vl" id="m-bb-cad">—</span></div>
|
|
1896
1912
|
<div class="it" data-bb-cell="dist_ancla" data-i18n-title="bb_dist_tip" title="Distancia al ancla" onclick="m_openInfoModal&&m_openInfoModal()"><span class="lb" data-i18n="bb_dist_ancla">Dist. ancla</span><span class="vl" id="m-bb-dist">—</span></div>
|
|
1897
1913
|
<!-- Rev331 (item 13): HORA del fondeo (HH:MM del drop, +N si han pasado días). Siempre visible con '—' cuando no fondeado. -->
|
|
@@ -2711,10 +2727,36 @@ var _unitsSystem = localStorage.getItem('ihm-visor-units') || 'metric_nautical';
|
|
|
2711
2727
|
window._sideButtons = j.buttons.slice();
|
|
2712
2728
|
try{ if(typeof m_renderSideButtons === 'function') m_renderSideButtons(window._sideButtons); }catch(_){}
|
|
2713
2729
|
}
|
|
2714
|
-
/* Sprint F (Rev454): cargar y aplicar orden/visibilidad del bottom-bar.
|
|
2730
|
+
/* Sprint F (Rev454): cargar y aplicar orden/visibilidad del bottom-bar.
|
|
2731
|
+
Rev491: AUTO-MIGRACIoN — si el bbOrder guardado no contiene celdas
|
|
2732
|
+
nuevas (dif_lw, prof_min, etc.) las insertamos automaticamente tras
|
|
2733
|
+
'sonda' para que el usuario las vea sin tener que entrar a config. */
|
|
2715
2734
|
if (j && Array.isArray(j.bbOrder)) {
|
|
2716
|
-
|
|
2735
|
+
var loaded = j.bbOrder.slice();
|
|
2736
|
+
var MIGRATE_TARGETS = ['dif_lw','prof_min'];
|
|
2737
|
+
var anchorKey = 'sonda';
|
|
2738
|
+
var anchorIdx = loaded.indexOf(anchorKey);
|
|
2739
|
+
var didMigrate = false;
|
|
2740
|
+
MIGRATE_TARGETS.forEach(function(k){
|
|
2741
|
+
if (loaded.indexOf(k) < 0) {
|
|
2742
|
+
if (anchorIdx >= 0) {
|
|
2743
|
+
loaded.splice(anchorIdx + 1, 0, k);
|
|
2744
|
+
anchorIdx++; // siguiente nueva celda va tras esta
|
|
2745
|
+
} else {
|
|
2746
|
+
loaded.push(k);
|
|
2747
|
+
}
|
|
2748
|
+
didMigrate = true;
|
|
2749
|
+
}
|
|
2750
|
+
});
|
|
2751
|
+
window._bbOrder = loaded;
|
|
2717
2752
|
try{ if(typeof m_applyBBOrder === 'function') m_applyBBOrder(window._bbOrder); }catch(_){}
|
|
2753
|
+
/* Si migramos, persistir para que el siguiente boot no vuelva a hacerlo. */
|
|
2754
|
+
if (didMigrate) {
|
|
2755
|
+
try {
|
|
2756
|
+
fetch(A+'/settings',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({bbOrder:loaded})}).catch(function(){});
|
|
2757
|
+
console.log('[IHM-BB] migrated bbOrder, added missing cells:', MIGRATE_TARGETS.filter(function(k){return j.bbOrder.indexOf(k)<0;}));
|
|
2758
|
+
} catch(_){}
|
|
2759
|
+
}
|
|
2718
2760
|
}
|
|
2719
2761
|
}).catch(function(){});
|
|
2720
2762
|
})();
|
|
@@ -2723,8 +2765,11 @@ var _unitsSystem = localStorage.getItem('ihm-visor-units') || 'metric_nautical';
|
|
|
2723
2765
|
Whitelist de keys + defaults. Cada celda tiene data-bb-cell="key".
|
|
2724
2766
|
m_applyBBOrder(arr): reordena los hijos del #m-bottom-bar segun arr y
|
|
2725
2767
|
oculta los que no esten en arr (display:none). */
|
|
2726
|
-
|
|
2727
|
-
|
|
2768
|
+
/* Rev489-490: dos celdas nuevas tras "sonda" — "dif_lw" (bajada en cm hasta
|
|
2769
|
+
próxima bajamar) y "prof_min" (sonda esperada en esa bajamar). Vicente
|
|
2770
|
+
pidió ambas para fondear con margen. */
|
|
2771
|
+
window._BB_CELL_KEYS = ["sog","heading","wind","sonda","dif_lw","prof_min","tide","pres","abrigo","calidad","cad_rec","dist_ancla","h_fondeo","sunrise","wx_6h","wave"];
|
|
2772
|
+
window._BB_DEFAULT_ORDER = ["sog","heading","wind","sonda","dif_lw","prof_min","tide","pres","abrigo","calidad","cad_rec","dist_ancla","h_fondeo"];
|
|
2728
2773
|
window._bbOrder = window._bbOrder || window._BB_DEFAULT_ORDER.slice();
|
|
2729
2774
|
function m_applyBBOrder(arr){
|
|
2730
2775
|
var bar = document.getElementById('m-bottom-bar');
|
|
@@ -3615,6 +3660,14 @@ var _i18n={
|
|
|
3615
3660
|
/* Sprint C (Rev452): celda marea bottom-bar. */
|
|
3616
3661
|
bb_marea:{es:'Marea',en:'Tide'},
|
|
3617
3662
|
bb_marea_tip:{es:'Estado marea: subiendo (▲) o bajando (▼) · % entre extremos · proximo extremo y hora · click → Curvas',en:'Tide state: rising (▲) or falling (▼) · % between extremes · next extreme + time · click → Tide chart'},
|
|
3663
|
+
/* Rev489 (feedback Vicente): nueva celda Diferencia Bajamar. */
|
|
3664
|
+
bb_dif_lw:{es:'Dif. Bajamar',en:'Drop to LW'},
|
|
3665
|
+
bb_dif_lw_tip:{es:'Cuánto bajará la marea hasta la próxima bajamar (cm) y sonda final esperada · click → Cálculo Sonda',en:'How much the tide will drop until next low water (cm) and expected final depth · click → Depth calc'},
|
|
3666
|
+
/* Rev490 (feedback Vicente): nueva celda Profundidad Mínima esperada.
|
|
3667
|
+
Rev491: titulo cambiado a "En B.M." (En Bajamar) — mas claro para el
|
|
3668
|
+
navegante que "Prof. mín." segun Vicente. */
|
|
3669
|
+
bb_prof_min:{es:'En B.M.',en:'At LW'},
|
|
3670
|
+
bb_prof_min_tip:{es:'Profundidad mínima esperada en la próxima bajamar (coherente con sonda actual) · click → Cálculo Sonda',en:'Minimum expected depth at next low water (consistent with current depth display) · click → Depth calc'},
|
|
3618
3671
|
tide_pm_short:{es:'PM',en:'HW'},
|
|
3619
3672
|
tide_bm_short:{es:'BM',en:'LW'},
|
|
3620
3673
|
/* Sprint F (Rev454): nueva celda Heading + motor bottom-bar configurable. */
|
|
@@ -5341,6 +5394,9 @@ function _groundingDisplay(s){
|
|
|
5341
5394
|
physicalRisk: (g.physics.state === 'danger') || legacyPhysRisk,
|
|
5342
5395
|
currentDepthM: (typeof g.physics.depthBelowSurfaceM === 'number') ? g.physics.depthBelowSurfaceM : null,
|
|
5343
5396
|
expectedMinDepthM:(typeof g.physics.expectedMinDepthM === 'number') ? g.physics.expectedMinDepthM : null,
|
|
5397
|
+
/* Rev488: remainingDropM = cuanto bajara la marea hasta la proxima bajamar.
|
|
5398
|
+
Vicente lo pidio expresamente como dato principal para decidir fondear. */
|
|
5399
|
+
remainingDropM: (typeof (s.groundingDetail||{}).remainingDropM === 'number') ? s.groundingDetail.remainingDropM : null,
|
|
5344
5400
|
effectiveDraftM: (typeof g.config.effectiveDraftM === 'number') ? g.config.effectiveDraftM
|
|
5345
5401
|
: (typeof g.config.draftM === 'number' && typeof g.config.safetyMarginM === 'number'
|
|
5346
5402
|
? (g.config.draftM + g.config.safetyMarginM) * 1.15 : null),
|
|
@@ -5363,6 +5419,7 @@ function _groundingDisplay(s){
|
|
|
5363
5419
|
physicalRisk: typeof gd.physicalRisk === 'boolean' ? gd.physicalRisk : null,
|
|
5364
5420
|
currentDepthM: (typeof gd.depthNowM === 'number') ? gd.depthNowM : null,
|
|
5365
5421
|
expectedMinDepthM:(typeof gd.expectedMinDepthM === 'number') ? gd.expectedMinDepthM : null,
|
|
5422
|
+
remainingDropM: (typeof gd.remainingDropM === 'number') ? gd.remainingDropM : null,
|
|
5366
5423
|
effectiveDraftM: (typeof gd.effectiveDraftM === 'number') ? gd.effectiveDraftM : null,
|
|
5367
5424
|
nextLowTimeIso: gd.nextLowTimeIso || null,
|
|
5368
5425
|
timeUntilMin: (typeof gd.timeUntilMin === 'number') ? gd.timeUntilMin : null,
|
|
@@ -11644,10 +11701,110 @@ function m_pollBottomBar(){
|
|
|
11644
11701
|
sublabel = (typeof T==='function') ? T('bb_sonda_riesgo','⚠ Atención: riesgo varada') : '⚠ Atención: riesgo varada';
|
|
11645
11702
|
}
|
|
11646
11703
|
sst.textContent = sublabel; sst.style.color = '#f44336'; sst.style.display = 'block';
|
|
11647
|
-
} else
|
|
11648
|
-
|
|
11649
|
-
|
|
11704
|
+
} else {
|
|
11705
|
+
/* Rev488 (feedback Vicente): mostrar SIEMPRE el dato de la proxima
|
|
11706
|
+
bajamar, este la marea subiendo o bajando. El navegante decide si
|
|
11707
|
+
fondea en funcion de "cuanto bajara hasta la proxima LW" y "que
|
|
11708
|
+
profundidad final habra". Si la marea esta subiendo y la proxima LW
|
|
11709
|
+
es similar o mas alta que ahora (raro pero posible en cambios de
|
|
11710
|
+
coeficiente), el drop sera ~0 y mostramos solo la profundidad final.
|
|
11711
|
+
|
|
11712
|
+
FIX coherencia (Vicente QA): el backend calcula expectedMinDepth en
|
|
11713
|
+
referencia belowSurface (incluye calado), pero el numero grande de
|
|
11714
|
+
SONDA muestra valor RAW del sensor (sin calado). Para que "Fin Y.Z"
|
|
11715
|
+
sea visualmente coherente con el numero grande, calculamos fin como
|
|
11716
|
+
"valor_display_actual - bajada", no usamos el del backend directo.
|
|
11717
|
+
Ej: sonda raw 4.2m, bajada 1.59m -> fin 2.6m (no 3.9m). */
|
|
11718
|
+
var dropM = _gdisp.remainingDropM;
|
|
11719
|
+
var finM;
|
|
11720
|
+
if (typeof _lastDepthM === 'number' && isFinite(_lastDepthM)
|
|
11721
|
+
&& typeof dropM === 'number' && isFinite(dropM)) {
|
|
11722
|
+
finM = _lastDepthM - dropM;
|
|
11723
|
+
} else {
|
|
11724
|
+
finM = _gdisp.expectedMinDepthM; /* fallback backend (referencia belowSurface) */
|
|
11725
|
+
}
|
|
11726
|
+
var en2 = (_lang === 'en');
|
|
11727
|
+
if (typeof finM === 'number' && isFinite(finM)) {
|
|
11728
|
+
var critical = finM < 1.0; /* < 1m de sonda final = atencion aunque alarma OFF */
|
|
11729
|
+
/* Rev490 (feedback usuario): sub-label SONDA mas compacto entre
|
|
11730
|
+
parentesis. Los detalles "bajada -Xcm" + "hora LW" ya viven en
|
|
11731
|
+
los widgets propios "Dif. Bajamar" y "Prof. min.". */
|
|
11732
|
+
sst.textContent = '(' + (en2 ? 'final ' : 'final ') + unitFmt.depth(finM, 1) + ')';
|
|
11733
|
+
sst.style.color = critical ? '#ffb23f' : '#66ffaa';
|
|
11734
|
+
sst.style.display = 'block';
|
|
11735
|
+
} else if (s.tideResume) {
|
|
11736
|
+
/* Fallback: sin datos numericos pero hay resumen de marea. */
|
|
11737
|
+
sst.textContent = (typeof T==='function')?T('bb_sonda_ok','OK · sin riesgo de varada'):'OK · sin riesgo de varada';
|
|
11738
|
+
sst.style.color = '#66ffaa';
|
|
11739
|
+
sst.style.display = 'block';
|
|
11740
|
+
} else { sst.style.display = 'none'; }
|
|
11741
|
+
}
|
|
11650
11742
|
}
|
|
11743
|
+
/* Rev489 (feedback Vicente): widget propio "Diferencia Bajamar". Numero
|
|
11744
|
+
grande = bajada en cm (negativo); sub-label = sonda esperada al final.
|
|
11745
|
+
Tiene su propio scope: lee del helper _gdisp y recalcula fin coherente
|
|
11746
|
+
con el numero de sonda mostrado (depthSounderRawM, no belowSurface). */
|
|
11747
|
+
try {
|
|
11748
|
+
var difEl = document.getElementById('m-bb-dif-lw');
|
|
11749
|
+
var difEnd = document.getElementById('m-bb-dif-lw-end');
|
|
11750
|
+
if (difEl) {
|
|
11751
|
+
var _dropM2 = _gdisp ? _gdisp.remainingDropM : null;
|
|
11752
|
+
var _finM2;
|
|
11753
|
+
if (typeof _lastDepthM === 'number' && isFinite(_lastDepthM)
|
|
11754
|
+
&& typeof _dropM2 === 'number' && isFinite(_dropM2)) {
|
|
11755
|
+
_finM2 = _lastDepthM - _dropM2;
|
|
11756
|
+
} else if (_gdisp) {
|
|
11757
|
+
_finM2 = _gdisp.expectedMinDepthM;
|
|
11758
|
+
}
|
|
11759
|
+
if (typeof _dropM2 === 'number' && isFinite(_dropM2) && _dropM2 > 0.005) {
|
|
11760
|
+
difEl.textContent = '-' + Math.round(_dropM2*100) + ' cm';
|
|
11761
|
+
difEl.style.color = (typeof _finM2 === 'number' && _finM2 < 1.0) ? '#ffb23f' : '#ffd166';
|
|
11762
|
+
} else if (typeof _dropM2 === 'number' && isFinite(_dropM2)) {
|
|
11763
|
+
difEl.textContent = '0 cm';
|
|
11764
|
+
difEl.style.color = '#9aa';
|
|
11765
|
+
} else {
|
|
11766
|
+
difEl.textContent = '—';
|
|
11767
|
+
difEl.style.color = '';
|
|
11768
|
+
}
|
|
11769
|
+
if (difEnd) {
|
|
11770
|
+
if (typeof _finM2 === 'number' && isFinite(_finM2)) {
|
|
11771
|
+
var enL = (_lang === 'en');
|
|
11772
|
+
difEnd.textContent = (enL ? 'End ' : 'Fin ') + unitFmt.depth(_finM2, 1);
|
|
11773
|
+
difEnd.style.color = (_finM2 < 1.0) ? '#ff7043' : '#cde';
|
|
11774
|
+
} else {
|
|
11775
|
+
difEnd.textContent = '—';
|
|
11776
|
+
difEnd.style.color = '';
|
|
11777
|
+
}
|
|
11778
|
+
}
|
|
11779
|
+
}
|
|
11780
|
+
/* Rev490: widget "Prof. mín." — sonda esperada en proxima bajamar. */
|
|
11781
|
+
var pmEl = document.getElementById('m-bb-prof-min');
|
|
11782
|
+
var pmWhen = document.getElementById('m-bb-prof-min-when');
|
|
11783
|
+
if (pmEl) {
|
|
11784
|
+
if (typeof _finM2 === 'number' && isFinite(_finM2)) {
|
|
11785
|
+
pmEl.textContent = unitFmt.depth(_finM2, 1);
|
|
11786
|
+
pmEl.style.color = (_finM2 < 1.0) ? '#ff5252' : (_finM2 < 2.0 ? '#ffb23f' : '');
|
|
11787
|
+
} else {
|
|
11788
|
+
pmEl.textContent = '—';
|
|
11789
|
+
pmEl.style.color = '';
|
|
11790
|
+
}
|
|
11791
|
+
if (pmWhen) {
|
|
11792
|
+
var lwIso = _gdisp ? _gdisp.nextLowTimeIso : null;
|
|
11793
|
+
if (lwIso) {
|
|
11794
|
+
try {
|
|
11795
|
+
var dLW = new Date(lwIso);
|
|
11796
|
+
var pad2 = function(n){ return ('0'+n).slice(-2); };
|
|
11797
|
+
var enL2 = (_lang === 'en');
|
|
11798
|
+
pmWhen.textContent = (enL2 ? 'at LW ' : 'a BM ') + pad2(dLW.getHours()) + ':' + pad2(dLW.getMinutes());
|
|
11799
|
+
pmWhen.style.color = '#cde';
|
|
11800
|
+
} catch(_){ pmWhen.textContent = '—'; }
|
|
11801
|
+
} else {
|
|
11802
|
+
pmWhen.textContent = '—';
|
|
11803
|
+
pmWhen.style.color = '';
|
|
11804
|
+
}
|
|
11805
|
+
}
|
|
11806
|
+
}
|
|
11807
|
+
} catch(_){}
|
|
11651
11808
|
/* Cadena recomendada (en metros) */
|
|
11652
11809
|
var cad = s.chainRecommended;
|
|
11653
11810
|
if (cad == null && s.approach) cad = s.approach.chainRecNow;
|
|
@@ -12495,7 +12652,11 @@ function m_updateBBScrollIndicators(){
|
|
|
12495
12652
|
L.textContent = '▲'; L.classList.add('show');
|
|
12496
12653
|
R.textContent = '▲'; R.classList.add('show');
|
|
12497
12654
|
} else {
|
|
12498
|
-
|
|
12655
|
+
/* Rev491 (feedback Vicente QA): replicar comportamiento derecha exacto.
|
|
12656
|
+
La izquierda ahora tambien SIEMPRE visible cuando la bar esta abierta,
|
|
12657
|
+
igual que la derecha. Antes solo se mostraba si canL (scroll disponible),
|
|
12658
|
+
lo que la dejaba oculta cuando el bottom-bar cabia entero en pantalla. */
|
|
12659
|
+
L.textContent = '◀'; L.classList.add('show');
|
|
12499
12660
|
R.textContent = '▶'; R.classList.add('show');
|
|
12500
12661
|
}
|
|
12501
12662
|
_syncToggleGlow();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signalk-mareas-ihm",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "User-friendly UI, multi-layer charts and transparencies (online and offline), AIS anti-collision surveillance, multi-device ringing alarms (drift, AIS, grounding, weather), shelter forecast and assessment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -101,24 +101,24 @@
|
|
|
101
101
|
],
|
|
102
102
|
"license": "Apache-2.0",
|
|
103
103
|
"dependencies": {
|
|
104
|
-
"@signalk/server-api": "^2.0",
|
|
104
|
+
"@signalk/server-api": "^2.0.0",
|
|
105
105
|
"better-sqlite3": "^11.0.0",
|
|
106
106
|
"leaflet": "^1.9.4",
|
|
107
|
-
"moment-timezone": "^0.
|
|
107
|
+
"moment-timezone": "^0.6.2",
|
|
108
108
|
"pdf-parse": "^1.1.1"
|
|
109
109
|
},
|
|
110
110
|
"devDependencies": {
|
|
111
111
|
"@eslint/js": "^9.21.0",
|
|
112
112
|
"@react-hook/resize-observer": "^2.0.2",
|
|
113
113
|
"@tailwindcss/vite": "^4.1.3",
|
|
114
|
-
"@types/node": "^
|
|
114
|
+
"@types/node": "^26.0.0",
|
|
115
115
|
"@types/react": "^19.0.12",
|
|
116
116
|
"@types/react-dom": "^19.0.4",
|
|
117
117
|
"@vitejs/plugin-react": "^5.0.2",
|
|
118
118
|
"eslint": "^9.21.0",
|
|
119
119
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
120
|
-
"eslint-plugin-react-refresh": "^0.
|
|
121
|
-
"globals": "^
|
|
120
|
+
"eslint-plugin-react-refresh": "^0.5.3",
|
|
121
|
+
"globals": "^17.6.0",
|
|
122
122
|
"react": "^19.1.0",
|
|
123
123
|
"react-dom": "^19.1.0",
|
|
124
124
|
"signalk-server": "^2.13.5",
|
package/public/mobile.html
CHANGED
|
@@ -1892,6 +1892,22 @@ body.mobile-ui #shelter-hours .sh-hr{flex:0 0 60px!important}
|
|
|
1892
1892
|
<span class="vl" id="m-bb-tide-val">—</span>
|
|
1893
1893
|
<span id="m-bb-tide-next" style="display:block;font-size:10px;font-weight:800;margin-top:1px;line-height:1;color:#cde">—</span>
|
|
1894
1894
|
</div>
|
|
1895
|
+
<!-- Rev489 (feedback Vicente): widget "Dif. Bajamar" — cuánto bajará la
|
|
1896
|
+
marea hasta la próxima bajamar (cm). Click abre modal Cálculo Sonda. -->
|
|
1897
|
+
<div class="it" data-bb-cell="dif_lw" data-i18n-title="bb_dif_lw_tip" title="Diferencia hasta próxima bajamar · click → Cálculo Sonda" onclick="openPopup&&openPopup('sonda-pop');typeof fetchSondaData==='function'&&fetchSondaData()">
|
|
1898
|
+
<span class="lb" data-i18n="bb_dif_lw">Dif. Bajamar</span>
|
|
1899
|
+
<span class="vl" id="m-bb-dif-lw">—</span>
|
|
1900
|
+
<span id="m-bb-dif-lw-end" style="display:block;font-size:10px;font-weight:800;margin-top:1px;line-height:1;color:#cde">—</span>
|
|
1901
|
+
</div>
|
|
1902
|
+
<!-- Rev490 (feedback Vicente): widget "Prof. Mínima" — sonda esperada en la
|
|
1903
|
+
próxima bajamar. Numero grande = profundidad final en metros (coherente
|
|
1904
|
+
con el numero grande de SONDA, misma referencia). Sub-label = hora de la
|
|
1905
|
+
proxima bajamar. Click abre modal Cálculo Sonda. -->
|
|
1906
|
+
<div class="it" data-bb-cell="prof_min" data-i18n-title="bb_prof_min_tip" title="Profundidad mínima esperada en la próxima bajamar · click → Cálculo Sonda" onclick="openPopup&&openPopup('sonda-pop');typeof fetchSondaData==='function'&&fetchSondaData()">
|
|
1907
|
+
<span class="lb" data-i18n="bb_prof_min">Prof. mín.</span>
|
|
1908
|
+
<span class="vl" id="m-bb-prof-min">—</span>
|
|
1909
|
+
<span id="m-bb-prof-min-when" style="display:block;font-size:10px;font-weight:800;margin-top:1px;line-height:1;color:#cde">—</span>
|
|
1910
|
+
</div>
|
|
1895
1911
|
<div class="it" data-bb-cell="cad_rec" data-i18n-title="bb_cadena_tip" title="Cadena recomendada" onclick="m_openInfoModal&&m_openInfoModal()"><span class="lb" data-i18n="bb_cadena_rec">Cadena rec.</span><span class="vl" id="m-bb-cad">—</span></div>
|
|
1896
1912
|
<div class="it" data-bb-cell="dist_ancla" data-i18n-title="bb_dist_tip" title="Distancia al ancla" onclick="m_openInfoModal&&m_openInfoModal()"><span class="lb" data-i18n="bb_dist_ancla">Dist. ancla</span><span class="vl" id="m-bb-dist">—</span></div>
|
|
1897
1913
|
<!-- Rev331 (item 13): HORA del fondeo (HH:MM del drop, +N si han pasado días). Siempre visible con '—' cuando no fondeado. -->
|
|
@@ -2711,10 +2727,36 @@ var _unitsSystem = localStorage.getItem('ihm-visor-units') || 'metric_nautical';
|
|
|
2711
2727
|
window._sideButtons = j.buttons.slice();
|
|
2712
2728
|
try{ if(typeof m_renderSideButtons === 'function') m_renderSideButtons(window._sideButtons); }catch(_){}
|
|
2713
2729
|
}
|
|
2714
|
-
/* Sprint F (Rev454): cargar y aplicar orden/visibilidad del bottom-bar.
|
|
2730
|
+
/* Sprint F (Rev454): cargar y aplicar orden/visibilidad del bottom-bar.
|
|
2731
|
+
Rev491: AUTO-MIGRACIoN — si el bbOrder guardado no contiene celdas
|
|
2732
|
+
nuevas (dif_lw, prof_min, etc.) las insertamos automaticamente tras
|
|
2733
|
+
'sonda' para que el usuario las vea sin tener que entrar a config. */
|
|
2715
2734
|
if (j && Array.isArray(j.bbOrder)) {
|
|
2716
|
-
|
|
2735
|
+
var loaded = j.bbOrder.slice();
|
|
2736
|
+
var MIGRATE_TARGETS = ['dif_lw','prof_min'];
|
|
2737
|
+
var anchorKey = 'sonda';
|
|
2738
|
+
var anchorIdx = loaded.indexOf(anchorKey);
|
|
2739
|
+
var didMigrate = false;
|
|
2740
|
+
MIGRATE_TARGETS.forEach(function(k){
|
|
2741
|
+
if (loaded.indexOf(k) < 0) {
|
|
2742
|
+
if (anchorIdx >= 0) {
|
|
2743
|
+
loaded.splice(anchorIdx + 1, 0, k);
|
|
2744
|
+
anchorIdx++; // siguiente nueva celda va tras esta
|
|
2745
|
+
} else {
|
|
2746
|
+
loaded.push(k);
|
|
2747
|
+
}
|
|
2748
|
+
didMigrate = true;
|
|
2749
|
+
}
|
|
2750
|
+
});
|
|
2751
|
+
window._bbOrder = loaded;
|
|
2717
2752
|
try{ if(typeof m_applyBBOrder === 'function') m_applyBBOrder(window._bbOrder); }catch(_){}
|
|
2753
|
+
/* Si migramos, persistir para que el siguiente boot no vuelva a hacerlo. */
|
|
2754
|
+
if (didMigrate) {
|
|
2755
|
+
try {
|
|
2756
|
+
fetch(A+'/settings',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({bbOrder:loaded})}).catch(function(){});
|
|
2757
|
+
console.log('[IHM-BB] migrated bbOrder, added missing cells:', MIGRATE_TARGETS.filter(function(k){return j.bbOrder.indexOf(k)<0;}));
|
|
2758
|
+
} catch(_){}
|
|
2759
|
+
}
|
|
2718
2760
|
}
|
|
2719
2761
|
}).catch(function(){});
|
|
2720
2762
|
})();
|
|
@@ -2723,8 +2765,11 @@ var _unitsSystem = localStorage.getItem('ihm-visor-units') || 'metric_nautical';
|
|
|
2723
2765
|
Whitelist de keys + defaults. Cada celda tiene data-bb-cell="key".
|
|
2724
2766
|
m_applyBBOrder(arr): reordena los hijos del #m-bottom-bar segun arr y
|
|
2725
2767
|
oculta los que no esten en arr (display:none). */
|
|
2726
|
-
|
|
2727
|
-
|
|
2768
|
+
/* Rev489-490: dos celdas nuevas tras "sonda" — "dif_lw" (bajada en cm hasta
|
|
2769
|
+
próxima bajamar) y "prof_min" (sonda esperada en esa bajamar). Vicente
|
|
2770
|
+
pidió ambas para fondear con margen. */
|
|
2771
|
+
window._BB_CELL_KEYS = ["sog","heading","wind","sonda","dif_lw","prof_min","tide","pres","abrigo","calidad","cad_rec","dist_ancla","h_fondeo","sunrise","wx_6h","wave"];
|
|
2772
|
+
window._BB_DEFAULT_ORDER = ["sog","heading","wind","sonda","dif_lw","prof_min","tide","pres","abrigo","calidad","cad_rec","dist_ancla","h_fondeo"];
|
|
2728
2773
|
window._bbOrder = window._bbOrder || window._BB_DEFAULT_ORDER.slice();
|
|
2729
2774
|
function m_applyBBOrder(arr){
|
|
2730
2775
|
var bar = document.getElementById('m-bottom-bar');
|
|
@@ -3615,6 +3660,14 @@ var _i18n={
|
|
|
3615
3660
|
/* Sprint C (Rev452): celda marea bottom-bar. */
|
|
3616
3661
|
bb_marea:{es:'Marea',en:'Tide'},
|
|
3617
3662
|
bb_marea_tip:{es:'Estado marea: subiendo (▲) o bajando (▼) · % entre extremos · proximo extremo y hora · click → Curvas',en:'Tide state: rising (▲) or falling (▼) · % between extremes · next extreme + time · click → Tide chart'},
|
|
3663
|
+
/* Rev489 (feedback Vicente): nueva celda Diferencia Bajamar. */
|
|
3664
|
+
bb_dif_lw:{es:'Dif. Bajamar',en:'Drop to LW'},
|
|
3665
|
+
bb_dif_lw_tip:{es:'Cuánto bajará la marea hasta la próxima bajamar (cm) y sonda final esperada · click → Cálculo Sonda',en:'How much the tide will drop until next low water (cm) and expected final depth · click → Depth calc'},
|
|
3666
|
+
/* Rev490 (feedback Vicente): nueva celda Profundidad Mínima esperada.
|
|
3667
|
+
Rev491: titulo cambiado a "En B.M." (En Bajamar) — mas claro para el
|
|
3668
|
+
navegante que "Prof. mín." segun Vicente. */
|
|
3669
|
+
bb_prof_min:{es:'En B.M.',en:'At LW'},
|
|
3670
|
+
bb_prof_min_tip:{es:'Profundidad mínima esperada en la próxima bajamar (coherente con sonda actual) · click → Cálculo Sonda',en:'Minimum expected depth at next low water (consistent with current depth display) · click → Depth calc'},
|
|
3618
3671
|
tide_pm_short:{es:'PM',en:'HW'},
|
|
3619
3672
|
tide_bm_short:{es:'BM',en:'LW'},
|
|
3620
3673
|
/* Sprint F (Rev454): nueva celda Heading + motor bottom-bar configurable. */
|
|
@@ -5341,6 +5394,9 @@ function _groundingDisplay(s){
|
|
|
5341
5394
|
physicalRisk: (g.physics.state === 'danger') || legacyPhysRisk,
|
|
5342
5395
|
currentDepthM: (typeof g.physics.depthBelowSurfaceM === 'number') ? g.physics.depthBelowSurfaceM : null,
|
|
5343
5396
|
expectedMinDepthM:(typeof g.physics.expectedMinDepthM === 'number') ? g.physics.expectedMinDepthM : null,
|
|
5397
|
+
/* Rev488: remainingDropM = cuanto bajara la marea hasta la proxima bajamar.
|
|
5398
|
+
Vicente lo pidio expresamente como dato principal para decidir fondear. */
|
|
5399
|
+
remainingDropM: (typeof (s.groundingDetail||{}).remainingDropM === 'number') ? s.groundingDetail.remainingDropM : null,
|
|
5344
5400
|
effectiveDraftM: (typeof g.config.effectiveDraftM === 'number') ? g.config.effectiveDraftM
|
|
5345
5401
|
: (typeof g.config.draftM === 'number' && typeof g.config.safetyMarginM === 'number'
|
|
5346
5402
|
? (g.config.draftM + g.config.safetyMarginM) * 1.15 : null),
|
|
@@ -5363,6 +5419,7 @@ function _groundingDisplay(s){
|
|
|
5363
5419
|
physicalRisk: typeof gd.physicalRisk === 'boolean' ? gd.physicalRisk : null,
|
|
5364
5420
|
currentDepthM: (typeof gd.depthNowM === 'number') ? gd.depthNowM : null,
|
|
5365
5421
|
expectedMinDepthM:(typeof gd.expectedMinDepthM === 'number') ? gd.expectedMinDepthM : null,
|
|
5422
|
+
remainingDropM: (typeof gd.remainingDropM === 'number') ? gd.remainingDropM : null,
|
|
5366
5423
|
effectiveDraftM: (typeof gd.effectiveDraftM === 'number') ? gd.effectiveDraftM : null,
|
|
5367
5424
|
nextLowTimeIso: gd.nextLowTimeIso || null,
|
|
5368
5425
|
timeUntilMin: (typeof gd.timeUntilMin === 'number') ? gd.timeUntilMin : null,
|
|
@@ -11644,10 +11701,110 @@ function m_pollBottomBar(){
|
|
|
11644
11701
|
sublabel = (typeof T==='function') ? T('bb_sonda_riesgo','⚠ Atención: riesgo varada') : '⚠ Atención: riesgo varada';
|
|
11645
11702
|
}
|
|
11646
11703
|
sst.textContent = sublabel; sst.style.color = '#f44336'; sst.style.display = 'block';
|
|
11647
|
-
} else
|
|
11648
|
-
|
|
11649
|
-
|
|
11704
|
+
} else {
|
|
11705
|
+
/* Rev488 (feedback Vicente): mostrar SIEMPRE el dato de la proxima
|
|
11706
|
+
bajamar, este la marea subiendo o bajando. El navegante decide si
|
|
11707
|
+
fondea en funcion de "cuanto bajara hasta la proxima LW" y "que
|
|
11708
|
+
profundidad final habra". Si la marea esta subiendo y la proxima LW
|
|
11709
|
+
es similar o mas alta que ahora (raro pero posible en cambios de
|
|
11710
|
+
coeficiente), el drop sera ~0 y mostramos solo la profundidad final.
|
|
11711
|
+
|
|
11712
|
+
FIX coherencia (Vicente QA): el backend calcula expectedMinDepth en
|
|
11713
|
+
referencia belowSurface (incluye calado), pero el numero grande de
|
|
11714
|
+
SONDA muestra valor RAW del sensor (sin calado). Para que "Fin Y.Z"
|
|
11715
|
+
sea visualmente coherente con el numero grande, calculamos fin como
|
|
11716
|
+
"valor_display_actual - bajada", no usamos el del backend directo.
|
|
11717
|
+
Ej: sonda raw 4.2m, bajada 1.59m -> fin 2.6m (no 3.9m). */
|
|
11718
|
+
var dropM = _gdisp.remainingDropM;
|
|
11719
|
+
var finM;
|
|
11720
|
+
if (typeof _lastDepthM === 'number' && isFinite(_lastDepthM)
|
|
11721
|
+
&& typeof dropM === 'number' && isFinite(dropM)) {
|
|
11722
|
+
finM = _lastDepthM - dropM;
|
|
11723
|
+
} else {
|
|
11724
|
+
finM = _gdisp.expectedMinDepthM; /* fallback backend (referencia belowSurface) */
|
|
11725
|
+
}
|
|
11726
|
+
var en2 = (_lang === 'en');
|
|
11727
|
+
if (typeof finM === 'number' && isFinite(finM)) {
|
|
11728
|
+
var critical = finM < 1.0; /* < 1m de sonda final = atencion aunque alarma OFF */
|
|
11729
|
+
/* Rev490 (feedback usuario): sub-label SONDA mas compacto entre
|
|
11730
|
+
parentesis. Los detalles "bajada -Xcm" + "hora LW" ya viven en
|
|
11731
|
+
los widgets propios "Dif. Bajamar" y "Prof. min.". */
|
|
11732
|
+
sst.textContent = '(' + (en2 ? 'final ' : 'final ') + unitFmt.depth(finM, 1) + ')';
|
|
11733
|
+
sst.style.color = critical ? '#ffb23f' : '#66ffaa';
|
|
11734
|
+
sst.style.display = 'block';
|
|
11735
|
+
} else if (s.tideResume) {
|
|
11736
|
+
/* Fallback: sin datos numericos pero hay resumen de marea. */
|
|
11737
|
+
sst.textContent = (typeof T==='function')?T('bb_sonda_ok','OK · sin riesgo de varada'):'OK · sin riesgo de varada';
|
|
11738
|
+
sst.style.color = '#66ffaa';
|
|
11739
|
+
sst.style.display = 'block';
|
|
11740
|
+
} else { sst.style.display = 'none'; }
|
|
11741
|
+
}
|
|
11650
11742
|
}
|
|
11743
|
+
/* Rev489 (feedback Vicente): widget propio "Diferencia Bajamar". Numero
|
|
11744
|
+
grande = bajada en cm (negativo); sub-label = sonda esperada al final.
|
|
11745
|
+
Tiene su propio scope: lee del helper _gdisp y recalcula fin coherente
|
|
11746
|
+
con el numero de sonda mostrado (depthSounderRawM, no belowSurface). */
|
|
11747
|
+
try {
|
|
11748
|
+
var difEl = document.getElementById('m-bb-dif-lw');
|
|
11749
|
+
var difEnd = document.getElementById('m-bb-dif-lw-end');
|
|
11750
|
+
if (difEl) {
|
|
11751
|
+
var _dropM2 = _gdisp ? _gdisp.remainingDropM : null;
|
|
11752
|
+
var _finM2;
|
|
11753
|
+
if (typeof _lastDepthM === 'number' && isFinite(_lastDepthM)
|
|
11754
|
+
&& typeof _dropM2 === 'number' && isFinite(_dropM2)) {
|
|
11755
|
+
_finM2 = _lastDepthM - _dropM2;
|
|
11756
|
+
} else if (_gdisp) {
|
|
11757
|
+
_finM2 = _gdisp.expectedMinDepthM;
|
|
11758
|
+
}
|
|
11759
|
+
if (typeof _dropM2 === 'number' && isFinite(_dropM2) && _dropM2 > 0.005) {
|
|
11760
|
+
difEl.textContent = '-' + Math.round(_dropM2*100) + ' cm';
|
|
11761
|
+
difEl.style.color = (typeof _finM2 === 'number' && _finM2 < 1.0) ? '#ffb23f' : '#ffd166';
|
|
11762
|
+
} else if (typeof _dropM2 === 'number' && isFinite(_dropM2)) {
|
|
11763
|
+
difEl.textContent = '0 cm';
|
|
11764
|
+
difEl.style.color = '#9aa';
|
|
11765
|
+
} else {
|
|
11766
|
+
difEl.textContent = '—';
|
|
11767
|
+
difEl.style.color = '';
|
|
11768
|
+
}
|
|
11769
|
+
if (difEnd) {
|
|
11770
|
+
if (typeof _finM2 === 'number' && isFinite(_finM2)) {
|
|
11771
|
+
var enL = (_lang === 'en');
|
|
11772
|
+
difEnd.textContent = (enL ? 'End ' : 'Fin ') + unitFmt.depth(_finM2, 1);
|
|
11773
|
+
difEnd.style.color = (_finM2 < 1.0) ? '#ff7043' : '#cde';
|
|
11774
|
+
} else {
|
|
11775
|
+
difEnd.textContent = '—';
|
|
11776
|
+
difEnd.style.color = '';
|
|
11777
|
+
}
|
|
11778
|
+
}
|
|
11779
|
+
}
|
|
11780
|
+
/* Rev490: widget "Prof. mín." — sonda esperada en proxima bajamar. */
|
|
11781
|
+
var pmEl = document.getElementById('m-bb-prof-min');
|
|
11782
|
+
var pmWhen = document.getElementById('m-bb-prof-min-when');
|
|
11783
|
+
if (pmEl) {
|
|
11784
|
+
if (typeof _finM2 === 'number' && isFinite(_finM2)) {
|
|
11785
|
+
pmEl.textContent = unitFmt.depth(_finM2, 1);
|
|
11786
|
+
pmEl.style.color = (_finM2 < 1.0) ? '#ff5252' : (_finM2 < 2.0 ? '#ffb23f' : '');
|
|
11787
|
+
} else {
|
|
11788
|
+
pmEl.textContent = '—';
|
|
11789
|
+
pmEl.style.color = '';
|
|
11790
|
+
}
|
|
11791
|
+
if (pmWhen) {
|
|
11792
|
+
var lwIso = _gdisp ? _gdisp.nextLowTimeIso : null;
|
|
11793
|
+
if (lwIso) {
|
|
11794
|
+
try {
|
|
11795
|
+
var dLW = new Date(lwIso);
|
|
11796
|
+
var pad2 = function(n){ return ('0'+n).slice(-2); };
|
|
11797
|
+
var enL2 = (_lang === 'en');
|
|
11798
|
+
pmWhen.textContent = (enL2 ? 'at LW ' : 'a BM ') + pad2(dLW.getHours()) + ':' + pad2(dLW.getMinutes());
|
|
11799
|
+
pmWhen.style.color = '#cde';
|
|
11800
|
+
} catch(_){ pmWhen.textContent = '—'; }
|
|
11801
|
+
} else {
|
|
11802
|
+
pmWhen.textContent = '—';
|
|
11803
|
+
pmWhen.style.color = '';
|
|
11804
|
+
}
|
|
11805
|
+
}
|
|
11806
|
+
}
|
|
11807
|
+
} catch(_){}
|
|
11651
11808
|
/* Cadena recomendada (en metros) */
|
|
11652
11809
|
var cad = s.chainRecommended;
|
|
11653
11810
|
if (cad == null && s.approach) cad = s.approach.chainRecNow;
|
|
@@ -12495,7 +12652,11 @@ function m_updateBBScrollIndicators(){
|
|
|
12495
12652
|
L.textContent = '▲'; L.classList.add('show');
|
|
12496
12653
|
R.textContent = '▲'; R.classList.add('show');
|
|
12497
12654
|
} else {
|
|
12498
|
-
|
|
12655
|
+
/* Rev491 (feedback Vicente QA): replicar comportamiento derecha exacto.
|
|
12656
|
+
La izquierda ahora tambien SIEMPRE visible cuando la bar esta abierta,
|
|
12657
|
+
igual que la derecha. Antes solo se mostraba si canL (scroll disponible),
|
|
12658
|
+
lo que la dejaba oculta cuando el bottom-bar cabia entero en pantalla. */
|
|
12659
|
+
L.textContent = '◀'; L.classList.add('show');
|
|
12499
12660
|
R.textContent = '▶'; R.classList.add('show');
|
|
12500
12661
|
}
|
|
12501
12662
|
_syncToggleGlow();
|