diff --git a/qml/pages/DetailPage.qml b/qml/pages/DetailPage.qml
index 2c65b35..b7de0fc 100644
--- a/qml/pages/DetailPage.qml
+++ b/qml/pages/DetailPage.qml
@@ -75,6 +75,15 @@ Page {
pageStack.push(Qt.resolvedUrl("SettingsPage.qml"))
}
+ function openWebcams() {
+ if (!port) return
+ // Mappa webcam pubblica di Windy centrata sul porto (nessuna API key)
+ var url = "https://www.windy.com/-Webcams/webcams/"
+ + port[2] + "/" + port[3]
+ console.log("[tide] openWebcams:", url)
+ Qt.openUrlExternally(url)
+ }
+
function refresh() {
if (!port) {
console.log("[tide] refresh: port UNDEFINED")
@@ -139,20 +148,25 @@ Page {
try {
var j = JSON.parse(xhr.responseText)
var wh = j.daily.wave_height_max
- if (wh && wh.length > 0) {
- var today = wh[0]
- var i0 = Tides.douglas(today)
- seaLabel.text = seaNames[i0] + " · " + Tides.fmtH(today, page.unit)
+ if (wh && wh.length >= 2) {
+ // riga 1: oggi
+ var i0 = Tides.douglas(wh[0])
+ seaLabel.text = qsTranslate("Sea", "Today") + ": " + seaNames[i0]
+ + " · " + Tides.fmtH(wh[0], page.unit)
seaLabel.color = i0 >= 5 ? Theme.errorColor
: (i0 >= 4 ? Theme.secondaryColor : Theme.highlightColor)
- if (wh.length > 1) {
- var i1 = Tides.douglas(wh[1])
- seaSub.text = qsTranslate("Sea", "Tomorrow") + ": " + seaNames[i1]
- + " · " + Tides.fmtH(wh[1], page.unit)
- seaSub.color = Theme.secondaryColor
- } else {
- seaSub.text = ""
+ // riga 2: domani e terzo giorno
+ var s = qsTranslate("Sea", "Tomorrow") + ": " + seaNames[Tides.douglas(wh[1])]
+ + " (" + Tides.fmtH(wh[1], page.unit) + ")"
+ if (wh.length > 2) {
+ var d2 = new Date()
+ d2.setDate(d2.getDate() + 2)
+ s += " · " + page.dayNames[d2.getDay()] + ": "
+ + seaNames[Tides.douglas(wh[2])]
+ + " (" + Tides.fmtH(wh[2], page.unit) + ")"
}
+ seaSub.text = s
+ seaSub.color = Theme.secondaryColor
return
}
} catch (e) {
@@ -239,15 +253,6 @@ Page {
}
}
- // Stato del mare (scala Douglas, previsione onde Open-Meteo)
- Item { width: parent.width; height: Theme.itemSizeSmall
- Label { text: "🌊 " + qsTranslate("Sea", "Sea state"); color: Theme.secondaryColor; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter }
- Label { id: seaLabel; text: "…"; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin + 130; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter; horizontalAlignment: Text.AlignRight; truncationMode: TruncationMode.Fade }
- }
- Item { width: parent.width; height: Theme.itemSizeSmall
- Label { id: seaSub; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin + 130; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter; horizontalAlignment: Text.AlignRight; font.pixelSize: Theme.fontSizeSmall; truncationMode: TruncationMode.Fade }
- }
-
// Intervallo (chips 24/48/72)
Row {
spacing: Theme.paddingMedium
@@ -370,6 +375,16 @@ Page {
}
}
+ // Stato del mare (scala Douglas, previsione onde Open-Meteo,
+ // oggi + domani + terzo giorno) — sotto la tabella alte/basse
+ Item { width: parent.width; height: Theme.itemSizeSmall
+ Label { text: "🌊 " + qsTranslate("Sea", "Sea state"); color: Theme.secondaryColor; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter }
+ Label { id: seaLabel; text: "…"; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin + 130; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter; horizontalAlignment: Text.AlignRight; truncationMode: TruncationMode.Fade }
+ }
+ Item { width: parent.width; height: Theme.itemSizeSmall
+ Label { id: seaSub; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter; horizontalAlignment: Text.AlignRight; font.pixelSize: Theme.fontSizeSmall; truncationMode: TruncationMode.Fade }
+ }
+
SectionHeader { text: qsTr("Astro") }
Item { width: parent.width; height: Theme.itemSizeSmall
@@ -399,6 +414,11 @@ Page {
visible: page.port !== undefined
onClicked: page.openCalendar()
}
+ MenuItem {
+ text: qsTr("Webcams")
+ visible: page.port !== undefined
+ onClicked: page.openWebcams()
+ }
MenuItem {
text: qsTr("Settings")
onClicked: page.openSettings()
diff --git a/translations/harbour-tide.ts b/translations/harbour-tide.ts
index d153ba5..eefaed9 100644
--- a/translations/harbour-tide.ts
+++ b/translations/harbour-tide.ts
@@ -22,6 +22,7 @@
DetailPage
+ Webcams
30-day calendar
lat %1°
📍 Nearest port: %1 — %2 · ±%3 m
@@ -97,6 +98,7 @@
Very high
Phenomenal
Sea state
+ Today
Tomorrow
Unavailable (offline)
diff --git a/translations/harbour-tide_it.ts b/translations/harbour-tide_it.ts
index dba5551..6ad28f1 100644
--- a/translations/harbour-tide_it.ts
+++ b/translations/harbour-tide_it.ts
@@ -22,6 +22,7 @@
DetailPage
+ WebcamsWebcam
30-day calendarCalendario 30 giorni
lat %1°lat %1°
📍 Nearest port: %1 — %2 · ±%3 m📍 Porto più vicino: %1 — %2 · ±%3 m
@@ -97,6 +98,7 @@
Very highMolto grosso
PhenomenalTempestoso
Sea stateStato del mare
+ TodayOggi
TomorrowDomani
Unavailable (offline)Non disponibile (offline)