Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 97 additions & 11 deletions src/plugins/weather/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<label class="form-label">Location: </label>
<div class="form-group">
<span>Latitude </span>
<input readonly type="text" id="latitude" name="latitude" class="form-input" />
<input type="text" id="latitude" name="latitude" class="form-input" />
</div>
<div class="form-group">
<span>Longitude </span>
<input readonly type="text" id="longitude" name="longitude" class="form-input" />
<input type="text" id="longitude" name="longitude" class="form-input" />
</div>
<button type="button" id="openMap" class="action-button compact">Select Location</button>
</div>
Expand Down Expand Up @@ -117,6 +117,50 @@ <h2 id="modalTitle">Select Location</h2>

<script>

/** Return true when value is a non-empty string that parses to a finite number. */
function hasCoord(value) {
return typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value));
}

/** Parse a coordinate string, returning fallback when empty/invalid. */
function parseCoord(value, fallback) {
return hasCoord(value) ? Number(value) : fallback;
}

/** Validate lat/long inputs. Returns true if valid or both empty. */
function validateCoordInputs() {
const latVal = document.getElementById('latitude').value.trim();
const longVal = document.getElementById('longitude').value.trim();

// Both empty is fine (no location set yet)
if (latVal === '' && longVal === '') {
return true;
}

if (latVal === '' || longVal === '') {
showResponseModal('failure', 'Error! Both latitude and longitude are required.');
return false;
}

if (!hasCoord(latVal) || !hasCoord(longVal)) {
showResponseModal('failure', 'Error! Latitude and longitude must be valid numbers.');
return false;
}

const lat = Number(latVal);
const long = Number(longVal);
if (lat < -90 || lat > 90) {
showResponseModal('failure', 'Error! Latitude must be between -90 and 90.');
return false;
}
if (long < -180 || long > 180) {
showResponseModal('failure', 'Error! Longitude must be between -180 and 180.');
return false;
}

return true;
}

function updateTitleOptions(provider) {
const titleLocationRadio = document.getElementById('title-location');
const titleLocationLabel = document.querySelector('label[for="title-location"]');
Expand Down Expand Up @@ -169,16 +213,42 @@ <h2 id="modalTitle">Select Location</h2>
const $mapModal = document.querySelector('#mapModal');
const $closeMap = document.querySelector('#closeMap');

let latitude = +$latitude.value;
let longitude = +$longitude.value;
let zoom = latitude && longitude ? 4.5 : 2.5;
let latitude = parseCoord($latitude.value, 0);
let longitude = parseCoord($longitude.value, 0);
let zoom = hasCoord($latitude.value) && hasCoord($longitude.value) ? 4.5 : 2.5;
let selectedTitle = 'location';
let weatherProvider = 'OpenMeteo';

let map, marker;
let markerMoved = false;
let hadValidCoords = false;

// Register global validation hook so handleAction can call it
window.pluginValidate = validateCoordInputs;

$openMap.addEventListener('click', () => {
openModal('mapModal')
if (!validateCoordInputs()) return;
// Re-read the current latitude/longitude inputs in case the user
// edited them manually after the page loaded.
const latInput = document.getElementById('latitude').value;
const longInput = document.getElementById('longitude').value;

hadValidCoords = hasCoord(latInput) && hasCoord(longInput);
markerMoved = false;

if (hadValidCoords) {
const parsedLat = Number(latInput);
const parsedLong = Number(longInput);
if (Number.isFinite(parsedLat) && Number.isFinite(parsedLong)) {
latitude = parsedLat;
longitude = parsedLong;
}
}
Comment thread
saulob marked this conversation as resolved.

// Recompute zoom based on whether coordinates are present
zoom = hadValidCoords ? 4.5 : 2.5;

openModal('mapModal');
setTimeout(() => {
if (!map) {
map = L.map('map').setView([latitude, longitude], zoom);
Expand All @@ -187,21 +257,33 @@ <h2 id="modalTitle">Select Location</h2>

map.on('click', event => {
marker.setLatLng(event.latlng);
markerMoved = true;
});
marker.on('dragend', () => {
markerMoved = true;
});
} else {
map.invalidateSize();
map.setView([latitude, longitude], zoom);
marker.setLatLng([latitude, longitude]);
}
}, 100);
});

$closeMap.addEventListener('click', () => {
const position = marker.getLatLng().wrap();
$latitude.value = position.lat;
$longitude.value = position.lng;
// Only persist coordinates if the user moved the marker
// or the inputs already had valid values before opening.
if (markerMoved || hadValidCoords) {
const position = marker.getLatLng().wrap();
$latitude.value = position.lat;
$longitude.value = position.lng;
}
closeModal('mapModal');
});

if (loadPluginSettings) {
document.getElementById('latitude').value = pluginSettings.latitude;
document.getElementById('longitude').value = pluginSettings.longitude;
document.getElementById('latitude').value = pluginSettings.latitude ?? '';
document.getElementById('longitude').value = pluginSettings.longitude ?? '';

document.getElementById('units').value = pluginSettings.units;

Expand Down Expand Up @@ -255,6 +337,10 @@ <h2 id="modalTitle">Select Location</h2>
document.getElementById('weatherTimeZone').value = "locationTimeZone";
}

latitude = parseCoord(document.getElementById('latitude').value, 0);
longitude = parseCoord(document.getElementById('longitude').value, 0);
zoom = hasCoord(document.getElementById('latitude').value) && hasCoord(document.getElementById('longitude').value) ? 4.5 : 2.5;

document.getElementById('weatherProvider').value = weatherProvider;
document.querySelector(`input[name="titleSelection"][value="${selectedTitle}"]`).checked = true;
updateTitleOptions(weatherProvider)
Expand Down
11 changes: 8 additions & 3 deletions src/plugins/weather/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,15 @@ def generate_settings_template(self):
return template_params

def generate_image(self, settings, device_config):
lat = float(settings.get('latitude'))
long = float(settings.get('longitude'))
if not lat or not long:
raw_lat = settings.get('latitude', '').strip()
raw_long = settings.get('longitude', '').strip()
if not raw_lat or not raw_long:
raise RuntimeError("Latitude and Longitude are required.")
try:
lat = float(raw_lat)
long = float(raw_long)
except (ValueError, TypeError):
raise RuntimeError("Latitude and Longitude must be valid numbers.")

units = settings.get('units')
if not units or units not in ['metric', 'imperial', 'standard']:
Expand Down