summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/WeatherService.qml
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/WeatherService.qml')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/WeatherService.qml914
1 files changed, 0 insertions, 914 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/WeatherService.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/WeatherService.qml
deleted file mode 100644
index 134789e..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Services/WeatherService.qml
+++ /dev/null
@@ -1,914 +0,0 @@
-pragma Singleton
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import Quickshell.Io
-import qs.Common
-import qs.Modules.Greetd
-import "../Common/suncalc.js" as SunCalc
-
-Singleton {
- id: root
-
- property int refCount: 0
-
- property var selectedDate: new Date()
- property var weather: ({
- "available": false,
- "loading": true,
- "temp": 0,
- "tempF": 0,
- "feelsLike": 0,
- "feelsLikeF": 0,
- "city": "",
- "country": "",
- "wCode": 0,
- "humidity": 0,
- "wind": "",
- "sunrise": "06:00",
- "sunset": "18:00",
- "uv": 0,
- "pressure": 0,
- "precipitationProbability": 0,
- "isDay": true,
- "forecast": []
- })
-
- property var location: null
- property int updateInterval: 900000 // 15 minutes
- property int retryAttempts: 0
- property int maxRetryAttempts: 3
- property int retryDelay: 30000
- property int lastFetchTime: 0
- property int minFetchInterval: 30000
- property int persistentRetryCount: 0
-
- readonly property var lowPriorityCmd: ["nice", "-n", "19", "ionice", "-c3"]
- readonly property var curlBaseCmd: ["curl", "-sS", "--fail", "--connect-timeout", "3", "--max-time", "6", "--limit-rate", "100k", "--compressed"]
-
- property var weatherIcons: ({
- "0": "clear_day",
- "1": "clear_day",
- "2": "partly_cloudy_day",
- "3": "cloud",
- "45": "foggy",
- "48": "foggy",
- "51": "rainy",
- "53": "rainy",
- "55": "rainy",
- "56": "rainy",
- "57": "rainy",
- "61": "rainy",
- "63": "rainy",
- "65": "rainy",
- "66": "rainy",
- "67": "rainy",
- "71": "cloudy_snowing",
- "73": "cloudy_snowing",
- "75": "snowing_heavy",
- "77": "cloudy_snowing",
- "80": "rainy",
- "81": "rainy",
- "82": "rainy",
- "85": "cloudy_snowing",
- "86": "snowing_heavy",
- "95": "thunderstorm",
- "96": "thunderstorm",
- "99": "thunderstorm"
- })
-
- property var nightWeatherIcons: ({
- "0": "clear_night",
- "1": "clear_night",
- "2": "partly_cloudy_night",
- "3": "cloud",
- "45": "foggy",
- "48": "foggy",
- "51": "rainy",
- "53": "rainy",
- "55": "rainy",
- "56": "rainy",
- "57": "rainy",
- "61": "rainy",
- "63": "rainy",
- "65": "rainy",
- "66": "rainy",
- "67": "rainy",
- "71": "cloudy_snowing",
- "73": "cloudy_snowing",
- "75": "snowing_heavy",
- "77": "cloudy_snowing",
- "80": "rainy",
- "81": "rainy",
- "82": "rainy",
- "85": "cloudy_snowing",
- "86": "snowing_heavy",
- "95": "thunderstorm",
- "96": "thunderstorm",
- "99": "thunderstorm"
- })
-
- function getWeatherIcon(code, isDay) {
- if (typeof isDay === "undefined") {
- isDay = weather.isDay;
- }
- const iconMap = isDay ? weatherIcons : nightWeatherIcons;
- return iconMap[String(code)] || "cloud";
- }
-
- function getWeatherCondition(code) {
- const conditions = {
- "0": I18n.tr("Clear Sky"),
- "1": I18n.tr("Clear Sky"),
- "2": I18n.tr("Partly Cloudy"),
- "3": I18n.tr("Overcast"),
- "45": I18n.tr("Fog"),
- "48": I18n.tr("Fog"),
- "51": I18n.tr("Drizzle"),
- "53": I18n.tr("Drizzle"),
- "55": I18n.tr("Drizzle"),
- "56": I18n.tr("Freezing Drizzle"),
- "57": I18n.tr("Freezing Drizzle"),
- "61": I18n.tr("Light Rain"),
- "63": I18n.tr("Rain"),
- "65": I18n.tr("Heavy Rain"),
- "66": I18n.tr("Light Rain"),
- "67": I18n.tr("Heavy Rain"),
- "71": I18n.tr("Light Snow"),
- "73": I18n.tr("Snow"),
- "75": I18n.tr("Heavy Snow"),
- "77": I18n.tr("Snow"),
- "80": I18n.tr("Light Rain"),
- "81": I18n.tr("Rain"),
- "82": I18n.tr("Heavy Rain"),
- "85": I18n.tr("Light Snow Showers"),
- "86": I18n.tr("Heavy Snow Showers"),
- "95": I18n.tr("Thunderstorm"),
- "96": I18n.tr("Thunderstorm with Hail"),
- "99": I18n.tr("Thunderstorm with Hail")
- };
- return conditions[String(code)] || I18n.tr("Unknown");
- }
-
- property var moonPhaseNames: ["moon_new", "moon_waxing_crescent", "moon_first_quarter", "moon_waxing_gibbous", "moon_full", "moon_waning_gibbous", "moon_last_quarter", "moon_waning_crescent"]
-
- function getMoonPhase(date) {
- const phases = moonPhaseNames;
- const iconCount = phases.length;
- const moon = SunCalc.getMoonIllumination(date);
- const index = ((Math.floor(moon.phase * iconCount + 0.5) % iconCount) + iconCount) % iconCount;
-
- return phases[index];
- }
-
- function getMoonAngle(date) {
- if (!location) {
- return;
- }
- const pos = SunCalc.getMoonPosition(date, location.latitude, location.longitude);
- return pos.parralacticAngle;
- }
-
- function getLocation() {
- return location;
- }
-
- function getSunDeclination(date) {
- return SunCalc.sunCoords(SunCalc.toDays(date)).dec * 180 / Math.PI;
- }
-
- function getSunTimes(date) {
- if (!location) {
- return null;
- }
- return SunCalc.getTimes(date, location.latitude, location.longitude, location.elevation);
- }
-
- function getEcliptic(date, points = 60) {
- if (!location) {
- return null;
- }
- const lat = location.latitude;
- const lon = location.longitude;
- const times = SunCalc.getTimes(date, lat, lon);
- const solarNoon = times.solarNoon;
-
- const eclipticPoints = [];
-
- const sunIsNorth = getSunDeclination(date) > lat;
- const transitAzimuth = sunIsNorth ? 0 : Math.PI;
-
- for (let i = 0; i <= points; i++) {
- const t = new Date(solarNoon.getTime() + (i / points) * 24 * 60 * 60 * 1000);
- const pos = SunCalc.getPosition(t, lat, lon);
-
- let h = (((pos.azimuth - transitAzimuth) / (2 * Math.PI)) + 1) % 1;
- h = Math.max(0, Math.min(1, h));
- let v = Math.sin(pos.altitude);
- v = Math.max(-1, Math.min(1, v));
-
- eclipticPoints.push({
- h,
- v
- });
- }
-
- const sortedEntries = eclipticPoints.sort((a, b) => a.h - b.h);
- return sortedEntries;
- }
-
- function getCurrentSunTime(date) {
- const times = getSunTimes(date);
- if (!times) {
- return;
- }
- const dateObj = new Date(date);
-
- const periods = [
- {
- name: I18n.tr("Dawn (Astronomical Twilight)"),
- start: new Date(times.nightEnd),
- end: new Date(times.nauticalDawn)
- },
- {
- name: I18n.tr("Dawn (Nautical Twilight)"),
- start: new Date(times.nauticalDawn),
- end: new Date(times.dawn)
- },
- {
- name: I18n.tr("Dawn (Civil Twilight)"),
- start: new Date(times.dawn),
- end: new Date(times.sunrise)
- },
- {
- name: I18n.tr("Sunrise"),
- start: new Date(times.sunrise),
- end: new Date(times.sunriseEnd)
- },
- {
- name: I18n.tr("Golden Hour"),
- start: new Date(times.sunriseEnd),
- end: new Date(times.goldenHourEnd)
- },
- {
- name: I18n.tr("Morning"),
- start: new Date(times.goldenHourEnd),
- end: new Date(times.solarNoon)
- },
- {
- name: I18n.tr("Afternoon"),
- start: new Date(times.solarNoon),
- end: new Date(times.goldenHour)
- },
- {
- name: I18n.tr("Golden Hour"),
- start: new Date(times.goldenHour),
- end: new Date(times.sunsetStart)
- },
- {
- name: I18n.tr("Sunset"),
- start: new Date(times.sunsetStart),
- end: new Date(times.sunset)
- },
- {
- name: I18n.tr("Dusk (Civil Twighlight)"),
- start: new Date(times.sunset),
- end: new Date(times.dusk)
- },
- {
- name: I18n.tr("Dusk (Nautical Twilight)"),
- start: new Date(times.dusk),
- end: new Date(times.nauticalDusk)
- },
- {
- name: I18n.tr("Dusk (Astronomical Twilight)"),
- start: new Date(times.nauticalDusk),
- end: new Date(times.night)
- },
- ];
-
- const sunrise = new Date(times.nightEnd);
- const sunset = new Date(times.night);
- const dayPercent = dateObj > sunrise && dateObj < sunset ? (dateObj - sunrise) / (sunset - sunrise) : 0;
-
- for (let i = 0; i < periods.length; i++) {
- const {
- name,
- start,
- end
- } = periods[i];
- if (dateObj >= start && dateObj < end) {
- const percent = (dateObj - start) / (end - start);
- return {
- period: name,
- periodIndex: i,
- periodPercent: Math.min(Math.max(percent, 0), 1),
- dayPercent: dayPercent
- };
- }
- }
-
- return {
- period: I18n.tr("Night"),
- periodIndex: 0,
- periodPercent: 0,
- dayPercent: dayPercent
- };
- }
-
- function getSkyArcPosition(date, isSun) {
- if (!location) {
- return null;
- }
- const lat = location.latitude;
- const lon = location.longitude;
-
- const pos = isSun ? SunCalc.getPosition(date, lat, lon) : SunCalc.getMoonPosition(date, lat, lon);
-
- const sunIsNorth = getSunDeclination(date) > lat;
- const transitAzimuth = sunIsNorth ? 0 : Math.PI;
-
- let h = (((pos.azimuth - transitAzimuth) / (2 * Math.PI)) + 1) % 1;
- h = Math.max(0, Math.min(1, h));
- // let v = pos.altitude / (Math.PI/2)
- let v = Math.sin(pos.altitude);
- v = Math.max(-1, Math.min(1, v));
-
- return {
- h,
- v
- };
- }
-
- function formatTemp(celsius, includeUnits = true, unitsShort = true) {
- if (celsius == null) {
- return null;
- }
- const value = SettingsData.useFahrenheit ? Math.round(celsius * (9 / 5) + 32) : celsius;
- const unit = unitsShort ? "°" : (SettingsData.useFahrenheit ? "°F" : "°C");
- return includeUnits ? value + unit : value;
- }
-
- function formatSpeed(kmh, includeUnits = true) {
- if (kmh == null) {
- return null;
- }
- if (SettingsData.useFahrenheit) {
- const value = Math.round(kmh * 0.621371);
- return includeUnits ? value + " mph" : value;
- }
- if (SettingsData.windSpeedUnit === "ms") {
- const value = (kmh / 3.6).toFixed(1);
- return includeUnits ? value + " m/s" : value;
- }
- return includeUnits ? kmh + " km/h" : kmh;
- }
-
- function formatPressure(hpa, includeUnits = true) {
- if (hpa == null) {
- return null;
- }
- const value = SettingsData.useFahrenheit ? (hpa * 0.02953).toFixed(2) : hpa;
- const unit = SettingsData.useFahrenheit ? "inHg" : "hPa";
- return includeUnits ? value + " " + unit : value;
- }
-
- function formatPercent(percent, includeUnits = true) {
- if (percent == null) {
- return null;
- }
- const value = percent;
- const unit = "%";
- return includeUnits ? value + unit : value;
- }
-
- function formatVisibility(distance) {
- if (distance == null) {
- return null;
- }
- var value;
- var unit;
- if (SettingsData.useFahrenheit) {
- value = (distance / 1609.344).toFixed(1);
- unit = "mi";
- if (value < 1) {
- value = Math.round(value * 5280 / 50) * 50;
- unit = "ft";
- }
- } else {
- value = distance;
- unit = "m";
- if (value > 1000) {
- value = (value / 1000).toFixed(1);
- unit = "km";
- }
- }
-
- return value + " " + unit;
- }
-
- function formatTime(isoString) {
- if (!isoString)
- return "--";
-
- try {
- const date = new Date(isoString);
- const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
- return date.toLocaleTimeString(Qt.locale(), format);
- } catch (e) {
- return "--";
- }
- }
-
- function calendarDayDifference(date1, date2) {
- const d1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate());
- const d2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate());
- return Math.floor((d2 - d1) / (1000 * 60 * 60 * 24));
- }
-
- function calendarHourDifference(date1, date2) {
- const d1 = Date.UTC(date1.getFullYear(), date1.getMonth(), date1.getDate(), date1.getHours());
- const d2 = Date.UTC(date2.getFullYear(), date2.getMonth(), date2.getDate(), date2.getHours());
- return Math.floor((d2 - d1) / (1000 * 60 * 60));
- }
-
- function formatForecastDay(isoString, index) {
- if (!isoString)
- return "--";
-
- if (index === 0)
- return I18n.tr("Today");
- if (index === 1)
- return I18n.tr("Tomorrow");
-
- const date = new Date();
- date.setDate(date.getDate() + index);
- const locale = I18n.locale();
- return locale.dayName(date.getDay(), Locale.ShortFormat);
- }
-
- function getWeatherApiUrl() {
- if (!location) {
- return null;
- }
-
- const params = ["latitude=" + location.latitude, "longitude=" + location.longitude, "current=temperature_2m,relative_humidity_2m,apparent_temperature,is_day,precipitation,weather_code,surface_pressure,wind_speed_10m", "daily=sunrise,sunset,temperature_2m_max,temperature_2m_min,weather_code,precipitation_probability_max", "hourly=temperature_2m,weather_code,precipitation_probability,wind_speed_10m,apparent_temperature,relative_humidity_2m,surface_pressure,visibility,cloud_cover", "timezone=auto", "forecast_days=7"];
-
- return "https://api.open-meteo.com/v1/forecast?" + params.join('&');
- }
-
- function getGeocodingUrl(query) {
- return "https://geocoding-api.open-meteo.com/v1/search?name=" + encodeURIComponent(query) + "&count=1&language=en&format=json";
- }
-
- function addRef() {
- refCount++;
-
- if (refCount === 1 && !weather.available && SettingsData.weatherEnabled) {
- fetchWeather();
- }
- }
-
- function removeRef() {
- refCount = Math.max(0, refCount - 1);
- }
-
- function updateLocation() {
- const useAuto = SessionData.isGreeterMode ? GreetdSettings.useAutoLocation : SettingsData.useAutoLocation;
- const coords = SessionData.isGreeterMode ? GreetdSettings.weatherCoordinates : SettingsData.weatherCoordinates;
- const cityName = SessionData.isGreeterMode ? GreetdSettings.weatherLocation : SettingsData.weatherLocation;
-
- if (useAuto) {
- getLocationFromService();
- return;
- }
-
- if (coords) {
- const parts = coords.split(",");
- if (parts.length === 2) {
- const lat = parseFloat(parts[0]);
- const lon = parseFloat(parts[1]);
- if (!isNaN(lat) && !isNaN(lon)) {
- getLocationFromCoords(lat, lon);
- return;
- }
- }
- }
-
- if (cityName)
- getLocationFromCity(cityName);
- }
-
- function getLocationFromCoords(lat, lon) {
- const url = "https://nominatim.openstreetmap.org/reverse?lat=" + lat + "&lon=" + lon + "&format=json&addressdetails=1&accept-language=en";
- reverseGeocodeFetcher.command = lowPriorityCmd.concat(curlBaseCmd).concat(["-H", "User-Agent: DankMaterialShell Weather Widget", url]);
- reverseGeocodeFetcher.running = true;
- }
-
- function getLocationFromCity(city) {
- cityGeocodeFetcher.command = lowPriorityCmd.concat(curlBaseCmd).concat([getGeocodingUrl(city)]);
- cityGeocodeFetcher.running = true;
- }
-
- function getLocationFromService() {
- if (!LocationService.valid)
- return;
- getLocationFromCoords(LocationService.latitude, LocationService.longitude);
- }
-
- function fetchWeather() {
- if (root.refCount === 0 || !SettingsData.weatherEnabled) {
- return;
- }
-
- if (!location) {
- updateLocation();
- return;
- }
-
- if (weatherFetcher.running) {
- return;
- }
-
- const now = Date.now();
- if (now - root.lastFetchTime < root.minFetchInterval) {
- return;
- }
-
- const apiUrl = getWeatherApiUrl();
- if (!apiUrl) {
- return;
- }
-
- root.lastFetchTime = now;
- root.weather.loading = true;
- const weatherCmd = lowPriorityCmd.concat(["curl", "-sS", "--fail", "--connect-timeout", "3", "--max-time", "6", "--limit-rate", "150k", "--compressed"]);
- weatherFetcher.command = weatherCmd.concat([apiUrl]);
- weatherFetcher.running = true;
- }
-
- function forceRefresh() {
- root.lastFetchTime = 0; // Reset throttle
- fetchWeather();
- }
-
- function nextInterval() {
- const jitter = Math.floor(Math.random() * 15000) - 7500;
- return Math.max(60000, root.updateInterval + jitter);
- }
-
- function handleWeatherSuccess() {
- root.retryAttempts = 0;
- root.persistentRetryCount = 0;
- if (persistentRetryTimer.running) {
- persistentRetryTimer.stop();
- }
- if (updateTimer.interval !== root.updateInterval) {
- updateTimer.interval = root.updateInterval;
- }
- }
-
- function handleWeatherFailure() {
- root.retryAttempts++;
- if (root.retryAttempts < root.maxRetryAttempts) {
- retryTimer.start();
- } else {
- root.retryAttempts = 0;
- if (!root.weather.available) {
- root.weather.loading = false;
- }
- const backoffDelay = Math.min(60000 * Math.pow(2, persistentRetryCount), 300000);
- persistentRetryCount++;
- persistentRetryTimer.interval = backoffDelay;
- persistentRetryTimer.start();
- }
- }
-
- Process {
- id: reverseGeocodeFetcher
- running: false
-
- stdout: StdioCollector {
- onStreamFinished: {
- const raw = text.trim();
- if (!raw || raw[0] !== "{") {
- root.handleWeatherFailure();
- return;
- }
-
- try {
- const data = JSON.parse(raw);
- const address = data.address || {};
-
- root.location = {
- city: address.hamlet || address.city || address.town || address.village || I18n.tr("Unknown"),
- country: address.country || I18n.tr("Unknown"),
- latitude: parseFloat(data.lat),
- longitude: parseFloat(data.lon)
- };
-
- fetchWeather();
- } catch (e) {
- root.handleWeatherFailure();
- }
- }
- }
-
- onExited: exitCode => {
- if (exitCode !== 0) {
- root.handleWeatherFailure();
- }
- }
- }
-
- Process {
- id: cityGeocodeFetcher
- running: false
-
- stdout: StdioCollector {
- onStreamFinished: {
- const raw = text.trim();
- if (!raw || raw[0] !== "{") {
- root.handleWeatherFailure();
- return;
- }
-
- try {
- const data = JSON.parse(raw);
- const results = data.results;
-
- if (!results || results.length === 0) {
- throw new Error("No results found");
- }
-
- const result = results[0];
-
- root.location = {
- city: result.name,
- country: result.country,
- latitude: result.latitude,
- longitude: result.longitude,
- elevation: data.elevation
- };
-
- fetchWeather();
- } catch (e) {
- root.handleWeatherFailure();
- }
- }
- }
-
- onExited: exitCode => {
- if (exitCode !== 0) {
- root.handleWeatherFailure();
- }
- }
- }
-
- Process {
- id: weatherFetcher
- running: false
-
- stdout: StdioCollector {
- onStreamFinished: {
- const raw = text.trim();
- if (!raw || raw[0] !== "{") {
- root.handleWeatherFailure();
- return;
- }
-
- try {
- const data = JSON.parse(raw);
-
- if (!data.current || !data.daily || !data.hourly) {
- throw new Error("Required weather data fields missing");
- }
-
- const hourly = data.hourly;
- const hourly_forecast = [];
- if (hourly.time && hourly.time.length > 0) {
- for (let i = 0; i < hourly.time.length; i++) {
- const tempMinC = hourly.temperature_2m_min?.[i] || 0;
- const tempMaxC = hourly.temperature_2m_max?.[i] || 0;
- const tempMinF = tempMinC * 9 / 5 + 32;
- const tempMaxF = tempMaxC * 9 / 5 + 32;
-
- const tempC = hourly.temperature_2m?.[i] || 0;
- const tempF = tempC * 9 / 5 + 32;
- const feelsLikeC = hourly.apparent_temperature?.[i] || tempC;
- const feelsLikeF = feelsLikeC * 9 / 5 + 32;
-
- const sunrise = new Date(data.daily.sunrise?.[Math.floor(i / 24)]);
- const sunset = new Date(data.daily.sunset?.[Math.floor(i / 24)]);
- const time = new Date(hourly.time[i]);
- const isDay = sunrise < time && time < sunset;
-
- hourly_forecast.push({
- "time": formatTime(hourly.time[i]),
- "rawTime": hourly.time[i],
- "temp": Math.round(tempC),
- "tempF": Math.round(tempF),
- "feelsLike": Math.round(feelsLikeC),
- "feelsLikeF": Math.round(feelsLikeF),
- "wCode": hourly.weather_code?.[i] || 0,
- "humidity": Math.round(hourly.relative_humidity_2m?.[i] || 0),
- "wind": Math.round(hourly.wind_speed_10m?.[i] || 0),
- "pressure": Math.round(hourly.surface_pressure?.[i] || 0),
- "precipitationProbability": Math.round(hourly.precipitation_probability?.[i] || 0),
- "visibility": Math.round(hourly.visibility?.[i] || 0),
- "isDay": isDay
- });
- }
- }
-
- const daily = data.daily;
- const forecast = [];
- if (daily.time && daily.time.length > 0) {
- for (let i = 0; i < daily.time.length; i++) {
- const tempMinC = daily.temperature_2m_min?.[i] || 0;
- const tempMaxC = daily.temperature_2m_max?.[i] || 0;
- const tempMinF = (tempMinC * 9 / 5 + 32);
- const tempMaxF = (tempMaxC * 9 / 5 + 32);
-
- forecast.push({
- "day": formatForecastDay(daily.time[i], i),
- "wCode": daily.weather_code?.[i] || 0,
- "tempMin": Math.round(tempMinC),
- "tempMax": Math.round(tempMaxC),
- "tempMinF": Math.round(tempMinF),
- "tempMaxF": Math.round(tempMaxF),
- "precipitationProbability": Math.round(daily.precipitation_probability_max?.[i] || 0),
- "sunrise": daily.sunrise?.[i] ? formatTime(daily.sunrise[i]) : "",
- "sunset": daily.sunset?.[i] ? formatTime(daily.sunset[i]) : "",
- "rawSunrise": daily.sunrise?.[i] || "",
- "rawSunset": daily.sunset?.[i] || ""
- });
- }
- }
-
- const current = data.current;
- const currentUnits = data.current_units || {};
-
- const tempC = current.temperature_2m || 0;
- const tempF = tempC * 9 / 5 + 32;
- const feelsLikeC = current.apparent_temperature || tempC;
- const feelsLikeF = feelsLikeC * 9 / 5 + 32;
-
- root.weather = {
- "available": true,
- "loading": false,
- "temp": Math.round(tempC),
- "tempF": Math.round(tempF),
- "feelsLike": Math.round(feelsLikeC),
- "feelsLikeF": Math.round(feelsLikeF),
- "city": root.location?.city || I18n.tr("Unknown"),
- "country": root.location?.country || I18n.tr("Unknown"),
- "wCode": current.weather_code || 0,
- "humidity": Math.round(current.relative_humidity_2m || 0),
- "wind": Math.round(current.wind_speed_10m || 0),
- "sunrise": formatTime(daily.sunrise?.[0]) || "06:00",
- "sunset": formatTime(daily.sunset?.[0]) || "18:00",
- "rawSunrise": daily.sunrise?.[0] || "",
- "rawSunset": daily.sunset?.[0] || "",
- "uv": 0,
- "pressure": Math.round(current.surface_pressure || 0),
- "precipitationProbability": Math.round(daily.precipitation_probability_max?.[0] || 0),
- "isDay": Boolean(current.is_day),
- "forecast": forecast,
- "hourlyForecast": hourly_forecast
- };
- root.handleWeatherSuccess();
- } catch (e) {
- root.handleWeatherFailure();
- }
- }
- }
-
- onExited: exitCode => {
- if (exitCode !== 0) {
- root.handleWeatherFailure();
- }
- }
- }
-
- Timer {
- id: updateTimer
- interval: nextInterval()
- running: root.refCount > 0 && SettingsData.weatherEnabled && !SessionData.isGreeterMode
- repeat: true
- triggeredOnStart: true
- onTriggered: {
- root.fetchWeather();
- interval = nextInterval();
- }
- }
-
- Timer {
- id: retryTimer
- interval: root.retryDelay
- running: false
- repeat: false
- onTriggered: {
- root.fetchWeather();
- }
- }
-
- Timer {
- id: persistentRetryTimer
- interval: 60000
- running: false
- repeat: false
- onTriggered: {
- if (!root.weather.available) {
- root.weather.loading = true;
- }
- root.fetchWeather();
- }
- }
-
- Connections {
- target: LocationService
-
- function onLocationChanged(data) {
- if (!SettingsData.useAutoLocation)
- return;
- if (data.latitude === 0 && data.longitude === 0)
- return;
- root.getLocationFromCoords(data.latitude, data.longitude);
- }
- }
-
- Component.onCompleted: {
- SettingsData.weatherCoordinatesChanged.connect(() => {
- root.location = null;
- root.weather = {
- "available": false,
- "loading": true,
- "temp": 0,
- "tempF": 0,
- "feelsLike": 0,
- "feelsLikeF": 0,
- "city": "",
- "country": "",
- "wCode": 0,
- "humidity": 0,
- "wind": "",
- "sunrise": "06:00",
- "sunset": "18:00",
- "uv": 0,
- "pressure": 0,
- "precipitationProbability": 0,
- "isDay": true,
- "forecast": []
- };
- root.lastFetchTime = 0;
- root.forceRefresh();
- });
-
- SettingsData.weatherLocationChanged.connect(() => {
- root.location = null;
- root.lastFetchTime = 0;
- root.forceRefresh();
- });
-
- SettingsData.useAutoLocationChanged.connect(() => {
- root.location = null;
- root.weather = {
- "available": false,
- "loading": true,
- "temp": 0,
- "tempF": 0,
- "feelsLike": 0,
- "feelsLikeF": 0,
- "city": "",
- "country": "",
- "wCode": 0,
- "humidity": 0,
- "wind": "",
- "sunrise": "06:00",
- "sunset": "18:00",
- "uv": 0,
- "pressure": 0,
- "precipitationProbability": 0,
- "isDay": true,
- "forecast": []
- };
- root.lastFetchTime = 0;
- root.forceRefresh();
- });
-
- SettingsData.weatherEnabledChanged.connect(() => {
- if (SettingsData.weatherEnabled && root.refCount > 0 && !root.weather.available) {
- root.forceRefresh();
- } else if (!SettingsData.weatherEnabled) {
- updateTimer.stop();
- retryTimer.stop();
- persistentRetryTimer.stop();
- if (weatherFetcher.running) {
- weatherFetcher.running = false;
- }
- }
- });
- }
-}