weather widget
This commit is contained in:
1 parent
44afecd7df
commit
54278273cb
14 files changed
+2688
-50
No files matched your search
@@ -0,0 +1,23 @@
|
||||
import { PopupContent } from '../bar/buttons/Weather.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import PopupWindow from '../misc/PopupWindow.js';
|
||||
import options from '../options.js';
|
||||
|
||||
export default () => PopupWindow({
|
||||
name: 'weather',
|
||||
anchor: ['top'],
|
||||
setup: self => self.hook(options.bar.position, () => {
|
||||
self.anchor = [options.bar.position.value];
|
||||
if (options.bar.position.value === 'top')
|
||||
self.transition = 'slide_down';
|
||||
|
||||
if (options.bar.position.value === 'bottom')
|
||||
self.transition = 'slide_up';
|
||||
}),
|
||||
child: Widget.Box({
|
||||
class_name: 'dashboard',
|
||||
children: [
|
||||
PopupContent(),
|
||||
],
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,433 @@
|
||||
#!/bin/sh
|
||||
|
||||
apiKey=""
|
||||
defaultLocation=""
|
||||
Ags=0
|
||||
Debug=0
|
||||
output=""
|
||||
WindSpeedUnit="kph"
|
||||
DegreeCharacter="°C"
|
||||
HumidityUnit="%"
|
||||
CloudCoverUnit="%"
|
||||
RainUnit=" mm"
|
||||
|
||||
function debug_break() {
|
||||
echo "-----"
|
||||
}
|
||||
|
||||
function get_script_argument_options() {
|
||||
if [[ $firstArgLetter == "a" ]]; then
|
||||
Ags=1
|
||||
fi
|
||||
|
||||
if [[ $firstArgLetter == "d" ]]; then
|
||||
Debug=1
|
||||
fi
|
||||
}
|
||||
|
||||
function get_config_file_data() {
|
||||
if [ -f "$ConfigFile" ]; then
|
||||
readarray -t line < "$ConfigFile"
|
||||
apiKey=${line[0]}
|
||||
defaultLocation=${line[1]}
|
||||
fi
|
||||
|
||||
if [ "$Debug" = "1" ]; then
|
||||
# echo "apiKey: $apiKey"
|
||||
echo "defaultLocation: $defaultLocation"
|
||||
debug_break
|
||||
fi
|
||||
|
||||
if [[ "$apiKey" == "" || "$defaultLocation" == "" ]]; then
|
||||
echo "Wrong Config file."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function check_api_status() {
|
||||
check=$(echo "$response" | grep -c -e '"cod":"40"' || true)
|
||||
check2=$(echo "$response" | grep -c -e '"cod":"30"' || true)
|
||||
sum=$(( check + check2 ))
|
||||
|
||||
if [ $sum -gt 0 ];then
|
||||
exit 99
|
||||
fi
|
||||
}
|
||||
|
||||
function get_api_response() {
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo "API REQUEST TO GET DATA. URL: $URL"
|
||||
fi
|
||||
|
||||
# Make the API request using curl
|
||||
# Check if the request was successful
|
||||
if ! response=$(curl -s "$URL"); then
|
||||
echo "Error making API request"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Save response to cache file
|
||||
echo "$response" > "$CacheFile"
|
||||
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo "$response"
|
||||
debug_break
|
||||
fi
|
||||
|
||||
check_api_status
|
||||
}
|
||||
|
||||
function get_api_response_from_cache_file() {
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo 'DATA FROM CACHE'
|
||||
fi
|
||||
|
||||
response=$(cat "$CacheFile")
|
||||
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo "$response"
|
||||
debug_break
|
||||
fi
|
||||
|
||||
check_api_status
|
||||
}
|
||||
|
||||
function get_response() {
|
||||
# Check if cache file exists and is less than 5 minutes old
|
||||
if [ -f "$CacheFile" ] && [ $(($(date +%s) - $(date -r "$CacheFile" +%s))) -lt 300 ]; then
|
||||
get_api_response_from_cache_file
|
||||
else
|
||||
get_api_response
|
||||
fi
|
||||
}
|
||||
|
||||
function print_weather_output() {
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo "NOW: $nowTemperature"
|
||||
fi
|
||||
|
||||
if [ -z "$output" ]; then
|
||||
echo "No weather data to output."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${output: -1}" = "," ]; then
|
||||
output="${output%,}"
|
||||
fi
|
||||
|
||||
output="[$output]"
|
||||
|
||||
if [ "$Ags" == "1" ]; then
|
||||
ags -r "weather.setTooltip($output)"
|
||||
ags -r "weather.setTemperatureWeather(\"$nowTemperature\")"
|
||||
else
|
||||
echo "$output"
|
||||
fi
|
||||
}
|
||||
|
||||
function get_debug_info_sunset_and_sunrise_hours() {
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo "Now: $CurrentTime"
|
||||
CurrentHour=$(date +"%-H" -d @"$CurrentTime")
|
||||
echo "Current: $CurrentHour"
|
||||
|
||||
echo "SunsetHour: $SunsetHour"
|
||||
echo "Sunrise: $SunriseHour"
|
||||
debug_break
|
||||
fi
|
||||
}
|
||||
|
||||
#sunset information from the Current weather response
|
||||
function get_current_sunset_and_sunrise_hours() {
|
||||
SunsetTime=$(echo "$response" | jq -r .sys.sunset)
|
||||
SunriseTime=$(echo "$response" | jq -r .sys.sunrise)
|
||||
SunsetHour=$(date +"%-H" -d @"$SunsetTime")
|
||||
SunriseHour=$(date +"%-H" -d @"$SunriseTime")
|
||||
|
||||
#current time
|
||||
CurrentTime=$(date +%s)
|
||||
|
||||
get_debug_info_sunset_and_sunrise_hours
|
||||
}
|
||||
|
||||
#sunset information from the weather Forecast response
|
||||
function get_forecast_sunset_and_sunrise_hours() {
|
||||
SunsetTime=$(echo "$response" | jq -r .city.sunset)
|
||||
SunriseTime=$(echo "$response" | jq -r .city.sunrise)
|
||||
SunsetHour=$(date +"%-H" -d @"$SunsetTime")
|
||||
SunriseHour=$(date +"%-H" -d @"$SunriseTime")
|
||||
|
||||
#current time
|
||||
CurrentTime=$(date +%s)
|
||||
|
||||
get_debug_info_sunset_and_sunrise_hours
|
||||
}
|
||||
|
||||
#Updates provided weather icon with night icons and sunset/sunrise icons
|
||||
function get_weather_icon() {
|
||||
icon=$1
|
||||
|
||||
checkNewIcon="True"
|
||||
|
||||
if [[ "$icon" == "☀️" || "$icon" == "🌤" || "$icon" == "⛅" ]]; then
|
||||
if [[ $WeatherHour -eq $SunriseHour ]]; then
|
||||
checkNewIcon="False"
|
||||
icon="🌄"
|
||||
fi
|
||||
|
||||
if [[ $checkNewIcon == "True" && $WeatherHour -eq $SunsetHour ]]; then
|
||||
checkNewIcon="False"
|
||||
icon="🌇"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $checkNewIcon == "True" && ($WeatherHour -ge $SunsetHour || $WeatherHour -le $SunriseHour) ]]; then
|
||||
case $1 in
|
||||
"☀️") icon="🌑" ;;
|
||||
"🌤") icon="🌑" ;;
|
||||
"⛅") icon="" ;;
|
||||
"☁") icon="" ;;
|
||||
"🌦") icon="" ;;
|
||||
"🌧️") icon="" ;;
|
||||
"🌨") icon="" ;;
|
||||
"") icon="" ;;
|
||||
esac
|
||||
|
||||
if [[ "$icon" == "🌑" ]]; then
|
||||
# Generate a random number between 1 and 5
|
||||
random_number=$(( RANDOM % 5 + 1 ))
|
||||
|
||||
# Check the random number and provide different outputs
|
||||
if [ $random_number -eq 1 ]; then
|
||||
icon="🌕"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function get_min_and_max_weather() {
|
||||
# MinTemperature=$(echo "$response" | jq -r .list["$i"].main.temp_min | tr '\n' ' ')
|
||||
# MaxTemperature=$(echo "$response" | jq -r .list["$i"].main.temp_max | tr '\n' ' ')
|
||||
|
||||
# Check if a new day has started
|
||||
Day=$(date +"%Y-%m-%d" -d @"${WeatherDate}")
|
||||
if [[ "$Day" != "$CurrentDay" ]]; then
|
||||
# Reset variables for the new day
|
||||
CurrentDay="$Day"
|
||||
MinTemperature="$Temperature"
|
||||
MaxTemperature="$Temperature"
|
||||
fi
|
||||
|
||||
# Update min and max temperatures
|
||||
if (( $(echo "$Temperature < $MinTemperature" | bc -l) )); then
|
||||
MinTemperature="$Temperature"
|
||||
fi
|
||||
|
||||
if (( $(echo "$Temperature > $MaxTemperature" | bc -l) )); then
|
||||
MaxTemperature="$Temperature"
|
||||
fi
|
||||
|
||||
MinTemp=$(printf '%.*f\n' 0 "$MinTemperature")
|
||||
MaxTemp=$(printf '%.*f\n' 0 "$MaxTemperature")
|
||||
}
|
||||
|
||||
function clear_defaults() {
|
||||
WeatherDate=""
|
||||
WeatherHour=""
|
||||
FormattedDate=""
|
||||
Temperature=""
|
||||
Temperature=""
|
||||
# ShortWeather=""
|
||||
LongWeather=""
|
||||
Humidity=""
|
||||
CloudCover=""
|
||||
WindSpeed=""
|
||||
MinTemperature=""
|
||||
MaxTemperature=""
|
||||
MinTemp=""
|
||||
MaxTemp=""
|
||||
icons=""
|
||||
Rain1h="null"
|
||||
Rain3h="null"
|
||||
}
|
||||
|
||||
function weather_data() {
|
||||
forecast=$1
|
||||
|
||||
if [ "$forecast" = "f" ]; then
|
||||
FormattedDate=$(date -d @"${WeatherDate}" +"%A, %B %d, %Y")
|
||||
# ShortWeather=$(echo "$response" | jq -r .list["$i"].weather[] | jq -r .main | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
LongWeather=$(echo "$response" | jq -r .list["$i"].weather[] | jq -r .description | sed -E 's/\S+/\u&/g' | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
Humidity=$(echo "$response" | jq -r .list["$i"].main.humidity | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
CloudCover=$(echo "$response" | jq -r .list["$i"].clouds.all | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
WindSpeed=$(echo "$response" | jq -r .list["$i"].wind.speed | tr '\n' ' ' | awk '{$1=$1};1' )
|
||||
WindSpeed=$(printf '%.*f\n' 1 "$WindSpeed")
|
||||
|
||||
Rain1h=$(echo "$response" | jq -r .list["$i"] | jq -r '.rain."1h"')
|
||||
Rain3h=$(echo "$response" | jq -r .list["$i"] | jq -r '.rain."3h"')
|
||||
|
||||
icons=$(echo "$response" | jq -r .list["$i"].weather[] | jq -r .icon | tr '\n' ' ' )
|
||||
else
|
||||
#current weather
|
||||
WeatherDate=$(echo "$response" | jq -r .dt | tr '\n' ' ')
|
||||
WeatherHour=$(date +"%-H" -d @"${WeatherDate}")
|
||||
FormattedDate=$(date -d @"${WeatherDate}" +"%A, %B %d, %Y")
|
||||
|
||||
# Extracting and formatting the temperature
|
||||
Temperature=$(echo "$response" | jq -r .main.temp | tr '\n' ' ')
|
||||
# Use bc to format the temperature to 0 decimal places
|
||||
Temperature=$(echo "$Temperature" | bc -l | awk '{printf "%.0f", $1}')
|
||||
|
||||
# ShortWeather=$(echo "$response" | jq -r .weather[0].main | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
LongWeather=$(echo "$response" | jq -r .weather[0].description | sed -E 's/\S+/\u&/g' | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
|
||||
Humidity=$(echo "$response" | jq -r .main.humidity | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
CloudCover=$(echo "$response" | jq -r .clouds.all | tr '\n' ' '| awk '{$1=$1};1' )
|
||||
WindSpeed=$(echo "$response" | jq -r .wind.speed | tr '\n' ' ' | awk '{$1=$1};1' )
|
||||
WindSpeed=$(printf '%.*f\n' 1 "$WindSpeed")
|
||||
|
||||
Rain1h=$(echo "$response" | jq -r '.rain."1h"')
|
||||
Rain3h=$(echo "$response" | jq -r '.rain."3h"')
|
||||
|
||||
MinTemperature=$(echo "$response" | jq -r .main.temp_min | tr '\n' ' ')
|
||||
MaxTemperature=$(echo "$response" | jq -r .main.temp_max | tr '\n' ' ')
|
||||
MinTemp=$(echo "$MinTemperature" | bc -l | awk '{printf "%.0f", $1}')
|
||||
MaxTemp=$(echo "$MaxTemperature" | bc -l | awk '{printf "%.0f", $1}')
|
||||
|
||||
icons=$(echo "$response" | jq -r .weather[0].icon | tr '\n' ' ')
|
||||
fi
|
||||
|
||||
Rain="0"
|
||||
|
||||
if [[ "$Rain3h" != "null" ]]; then
|
||||
Rain="$Rain3h"
|
||||
fi
|
||||
|
||||
if [[ "$Rain1h" != "null" ]]; then
|
||||
Rain="$Rain1h"
|
||||
fi
|
||||
|
||||
iconval=${icons%?}
|
||||
case $iconval in
|
||||
01*) get_weather_icon "☀️";;
|
||||
02*) get_weather_icon "🌤";;
|
||||
03*) get_weather_icon "⛅";;
|
||||
04*) get_weather_icon "☁";;
|
||||
09*) get_weather_icon "🌦";;
|
||||
10*) get_weather_icon "🌧️";;
|
||||
11*) get_weather_icon "🌩";;
|
||||
13*) get_weather_icon "🌨";;
|
||||
50*) get_weather_icon "";;
|
||||
esac
|
||||
|
||||
if [ "$Debug" = "1" ]; then
|
||||
echo "WeatherDate: $FormattedDate, Hour: $WeatherHour"
|
||||
# echo "ShortWeather: $ShortWeather"
|
||||
echo "LongWeather: $LongWeather"
|
||||
echo "Humidity: $Humidity$HumidityUnit"
|
||||
echo "CloudCover: $CloudCover$CloudCoverUnit"
|
||||
echo "WindSpeed: $WindSpeed $WindSpeedUnit"
|
||||
echo "Temperature: $Temperature$DegreeCharacter"
|
||||
echo "icon: $icon"
|
||||
echo "MinTemp: $MinTemp$DegreeCharacter"
|
||||
echo "MaxTemp: $MaxTemp$DegreeCharacter"
|
||||
echo "rain_1h: $Rain1h"
|
||||
echo "rain_3h: $Rain3h"
|
||||
debug_break
|
||||
fi
|
||||
|
||||
if [ "$forecast" != "f" ]; then
|
||||
nowTemperature="$icon $Temperature$DegreeCharacter"
|
||||
fi
|
||||
|
||||
output+="{\"date\":\"$FormattedDate\",\"hour\":\"$WeatherHour\",\"temperature\":\"${Temperature}°C\",\"icon\":\"$icon\",\"wind\":\"$WindSpeed$WindSpeedUnit\",\"rain\":\"$Rain$RainUnit\",\"humidity\":\"$Humidity$HumidityUnit\",\"minTemp\":\"$MinTemp$DegreeCharacter\",\"maxTemp\":\"$MaxTemp$DegreeCharacter\"},"
|
||||
}
|
||||
|
||||
function get_weather_forecast_data() {
|
||||
CurrentDay=""
|
||||
# PreviousDay=""
|
||||
TomorrowDate=$(date -d '+1 day' +"%s")
|
||||
|
||||
clear_defaults
|
||||
|
||||
i=0
|
||||
# NumEntries=$(echo "$response" |jq -r .cnt)
|
||||
# while [ $i -lt $NumEntries ]; do
|
||||
while [ $i -lt 40 ]; do
|
||||
WeatherDate=$(echo "$response" | jq -r .list[$i].dt | tr '\n' ' ')
|
||||
WeatherHour=$(date +"%-H" -d @"${WeatherDate}")
|
||||
CastDate=$(date +"%s" -d @"${WeatherDate}")
|
||||
|
||||
Temperature=$(echo "$response" | jq -r .list[$i].main.temp | tr '\n' ' ')
|
||||
Temperature=$(echo "$Temperature" | bc -l | awk '{printf "%.0f", $1}')
|
||||
|
||||
get_min_and_max_weather
|
||||
|
||||
#show the weather forecast hourly until it reaches tomorrow date, then only 1 hour
|
||||
if [ "$CastDate" -le "$TomorrowDate" ]; then
|
||||
weather_data "f"
|
||||
else
|
||||
if [ "$WeatherHour" -ge "17" ] && [ "$WeatherHour" -le "18" ] ||
|
||||
[ "$WeatherHour" -ge "18" ] && [ "$WeatherHour" -le "19" ]; then
|
||||
|
||||
# if [[ "$CurrentDay" != "$PreviousDay" ]]; then
|
||||
weather_data "f"
|
||||
# fi
|
||||
|
||||
# PreviousDay=$CurrentDay
|
||||
fi
|
||||
fi
|
||||
|
||||
i=$((i + 1))
|
||||
done
|
||||
}
|
||||
|
||||
function call_weather_current_api() {
|
||||
# API endpoint URL Current Weather
|
||||
URL="http://api.openweathermap.org/data/2.5/weather?id=$defaultLocation&units=metric&appid=$apiKey"
|
||||
|
||||
# Current Weather API cache file path based on defaultLocation
|
||||
CacheFile="/tmp/weather_cache_${defaultLocation}_current.json"
|
||||
|
||||
get_response
|
||||
# get_api_response_from_cache_file
|
||||
|
||||
get_current_sunset_and_sunrise_hours
|
||||
weather_data "c"
|
||||
}
|
||||
|
||||
function call_weather_forecast_api() {
|
||||
# API endpoint URL Forecast
|
||||
URL="http://api.openweathermap.org/data/2.5/forecast?id=$defaultLocation&units=metric&appid=$apiKey"
|
||||
|
||||
# Forecast API cache file path based on defaultLocation
|
||||
CacheFile="/tmp/weather_cache_${defaultLocation}_forecast.json"
|
||||
|
||||
get_response
|
||||
# get_api_response_from_cache_file
|
||||
|
||||
#used to retrieve forecast data
|
||||
get_forecast_sunset_and_sunrise_hours
|
||||
get_weather_forecast_data
|
||||
}
|
||||
|
||||
#get this scripts arguments => (ags, debug or none)
|
||||
#checks the first letter of the argument provided to the script
|
||||
if [[ $# -ge 1 ]]; then
|
||||
firstArgLetter="$(echo "$1" | head -c 1)"
|
||||
else
|
||||
firstArgLetter=
|
||||
fi
|
||||
|
||||
get_script_argument_options
|
||||
|
||||
#call to get config file data => (apiKey and defaultLocation)
|
||||
ConfigFile="$HOME/.config/scripts/weather.rc"
|
||||
get_config_file_data
|
||||
|
||||
call_weather_current_api
|
||||
|
||||
call_weather_forecast_api
|
||||
|
||||
#prints out final output / sends over the data
|
||||
print_weather_output
|
||||
@@ -0,0 +1,417 @@
|
||||
@mixin calendar {
|
||||
@include widget;
|
||||
padding: $padding*2 $padding*2 0;
|
||||
|
||||
calendar{
|
||||
// all: unset;
|
||||
.view {
|
||||
all:unset;
|
||||
}
|
||||
|
||||
&.button{
|
||||
@include button($flat: true);
|
||||
}
|
||||
|
||||
&:selected{
|
||||
box-shadow: inset 0 -8px 0 0 transparentize($accent, 0.5),
|
||||
inset 0 0 0 1px $accent;
|
||||
border-radius: $radii*0.6;
|
||||
}
|
||||
|
||||
&.header{
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: transparentize($fg-color, 0.5);
|
||||
}
|
||||
|
||||
&.highlight{
|
||||
background-color: transparent;
|
||||
color: transparentize($accent, 0.5);
|
||||
}
|
||||
|
||||
&:indeterminate {
|
||||
color: transparentize($fg-color, 0.9);
|
||||
}
|
||||
font-size: 1.1em;
|
||||
padding: .2em;
|
||||
color: $fg_color;
|
||||
}
|
||||
}
|
||||
|
||||
window#notification .dashboard,
|
||||
window#weather .weather,
|
||||
window#dashboard .window-content {
|
||||
@include floating-widget;
|
||||
|
||||
.notifications {
|
||||
min-width: $notifications-width;
|
||||
|
||||
.header {
|
||||
margin-bottom: $spacing;
|
||||
margin-right: $spacing;
|
||||
|
||||
> label { margin-left: $radii / 2; }
|
||||
|
||||
button {
|
||||
@include button;
|
||||
padding: $padding/2 $padding;
|
||||
}
|
||||
}
|
||||
|
||||
.notification-scrollable {
|
||||
@include scrollable;
|
||||
}
|
||||
|
||||
.notification-list {
|
||||
//fixes weird spacing bug on notification panel - release4
|
||||
// margin-right: $spacing;
|
||||
}
|
||||
|
||||
.notification {
|
||||
@include notification;
|
||||
|
||||
> box {
|
||||
@include widget;
|
||||
padding: $padding;
|
||||
margin-bottom: $spacing;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
image { font-size: 7em; }
|
||||
label { font-size: 1.2em; }
|
||||
}
|
||||
}
|
||||
|
||||
separator {
|
||||
background-color: $popover-border-color;
|
||||
min-width: 2px;
|
||||
border-radius: $radii;
|
||||
margin-right: $spacing;
|
||||
}
|
||||
|
||||
.datemenu, .system-info {
|
||||
@include spacing;
|
||||
}
|
||||
|
||||
.clock-box {
|
||||
padding: $padding;
|
||||
|
||||
.clock {
|
||||
font-size: 5em;
|
||||
}
|
||||
|
||||
.uptime {
|
||||
color: transparentize($fg-color, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.calendar {
|
||||
@include calendar;
|
||||
}
|
||||
|
||||
//weather popup
|
||||
.weather-info {
|
||||
.weather-icon{
|
||||
font-size: 1.5em;
|
||||
margin-top: 0.3em;
|
||||
margin-bottom: 0.15em;
|
||||
}
|
||||
|
||||
.weather-temperature {
|
||||
all: unset;
|
||||
font-size: 1.2em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// height of the notification popup
|
||||
window#notification .dashboard {
|
||||
min-height: 32em;
|
||||
}
|
||||
|
||||
// weather popup
|
||||
.weather-refresh {
|
||||
all: unset;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.weather-refresh:hover {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.weather-refresh:active {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.weather-refresh:focus {
|
||||
color: $accent;
|
||||
}
|
||||
|
||||
.weather-info {
|
||||
background-color: rgba(81, 164, 231, 0.76);
|
||||
border-radius: 16px;
|
||||
padding: 0.55em;
|
||||
// margin: 0 5px;
|
||||
|
||||
min-width: 5em;
|
||||
min-height: 10em;
|
||||
}
|
||||
|
||||
.weather-temperature {
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
|
||||
.weather-day {
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.weather-day:first-child {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
window#dashboard .dashboard,
|
||||
window#quicksettings .window-content {
|
||||
.circular-progress-box {
|
||||
@include widget;
|
||||
padding: $padding;
|
||||
|
||||
.circular-progress {
|
||||
min-height: $sys-info-size;
|
||||
min-width: $sys-info-size;
|
||||
margin: $padding/2;
|
||||
font-size: $padding;
|
||||
background-color: $bg-color;
|
||||
color: $accent;
|
||||
|
||||
image {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// weather window width of the weather widget
|
||||
window#weather .weather .tooltip {
|
||||
.weather-spacing {
|
||||
padding-left: $spacing;
|
||||
}
|
||||
|
||||
.qsweather-widget {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.qs-weather-box-child {
|
||||
min-width: 5em;
|
||||
|
||||
.weather-icon {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.qs-weather-box-main {
|
||||
min-width: 16.5em;
|
||||
}
|
||||
}
|
||||
|
||||
// shared logic for weather widget, first one only goes to qs
|
||||
window#quicksettings .window-content,
|
||||
window#weather .tooltip {
|
||||
.qsweather-widget {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: $padding / 2;
|
||||
border-radius: $radii;
|
||||
}
|
||||
|
||||
.qs-weather-box-main {
|
||||
margin: 0.5em;
|
||||
|
||||
.weather-icon {
|
||||
font-size: 2.42em;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
.weather-temperature {
|
||||
all: unset;
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
.weather-rain {
|
||||
margin-left: 1.2em;
|
||||
}
|
||||
|
||||
.weather-hour {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.qs-weather-box-child {
|
||||
padding-bottom: 0.7em;
|
||||
|
||||
.weather-icon {
|
||||
margin-top: 0.3em;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.weather-temperature {
|
||||
all: unset;
|
||||
margin-bottom: 0.2em;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// .weather-max {
|
||||
// color: #FF8C00;
|
||||
// }
|
||||
|
||||
// .weather-min {
|
||||
// color: #87ceeb;
|
||||
// }
|
||||
}
|
||||
|
||||
// fix to keep topbar on the correct height - 29 (hyprctl layers), new on release4
|
||||
.weather.panel-button label{
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
$sliderVolumeMinHeight: 2em;
|
||||
$sliderTroughMinWidth: 2em;
|
||||
|
||||
window#dashboard .datemenu .sub-menu {
|
||||
all:unset;
|
||||
|
||||
&:focus,
|
||||
&:hover{
|
||||
color: $accent;
|
||||
}
|
||||
}
|
||||
|
||||
.led-light-color-switcher {
|
||||
.on,
|
||||
.off {
|
||||
min-width: 1.8em;
|
||||
min-height: 3.8em;
|
||||
background-color: #fff;
|
||||
border: 1px solid black;
|
||||
border-radius: 5px;
|
||||
color: black;
|
||||
margin-top: 0.5em;
|
||||
|
||||
&:focus,
|
||||
&:hover{
|
||||
box-shadow: inset 0 0 4px 2px $accent,
|
||||
inset 0 0 0 99px $widget_bg;
|
||||
}
|
||||
}
|
||||
|
||||
.on {
|
||||
box-shadow: inset 0px -20px 2px 2px rgba(0, 0, 0, 0.2);
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.off {
|
||||
box-shadow: inset 0px 20px 2px 2px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.slider {
|
||||
min-width: 21.3em;
|
||||
margin: 0 0.5em;
|
||||
padding: 0;
|
||||
margin-top: 1em;
|
||||
|
||||
slider {
|
||||
all: unset;
|
||||
}
|
||||
|
||||
trough{
|
||||
min-height: $sliderVolumeMinHeight;
|
||||
border-radius: $radii;
|
||||
}
|
||||
|
||||
highlight,
|
||||
progress {
|
||||
background: transparent;
|
||||
border-radius: $radii;
|
||||
min-width: $sliderTroughMinWidth;
|
||||
}
|
||||
}
|
||||
|
||||
.color-temp.slider,
|
||||
.hue.slider,
|
||||
.brightness.slider {
|
||||
highlight,
|
||||
progress {
|
||||
&:focus,
|
||||
&:hover{
|
||||
box-shadow: inset 0 0 3px 3px $accent,
|
||||
inset 0 0 0 99px $widget_bg;
|
||||
|
||||
border: $accent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.color-temp.slider {
|
||||
trough{
|
||||
box-shadow:
|
||||
inset 700px 0 10px rgba(98, 159, 255, 0.8), /* 6500K */
|
||||
inset 600px 0 10px rgba(144, 196, 255, 0.8), /* 6000K */
|
||||
inset 500px 0 10px rgba(200, 232, 255, 0.8), /* 5000K */
|
||||
inset 400px 0 10px rgba(255, 255, 255, 0.8), /* 4000K */
|
||||
inset 300px 0 10px rgba(255, 249, 200, 0.8), /* 3000K */
|
||||
inset 200px 0 10px rgba(255, 232, 156, 0.8), /* 2000K */
|
||||
inset 100px 0 10px rgba(255, 184, 104, 0.8), /* 1700K */
|
||||
;
|
||||
}
|
||||
|
||||
highlight,
|
||||
progress {
|
||||
box-shadow: inset 0px 0px 2px 1px black;
|
||||
}
|
||||
}
|
||||
|
||||
.hue.slider {
|
||||
trough{
|
||||
box-shadow:
|
||||
inset 350px 0 10px rgba(255, 0, 0, 0.8), /* Red */
|
||||
inset 300px 0 10px rgba(255, 0, 255, 0.8), /* Magenta */
|
||||
inset 250px 0 10px rgba(0, 0, 255, 0.8), /* Blue */
|
||||
inset 200px 0 10px rgba(0, 255, 255, 0.8), /* Cyan */
|
||||
inset 150px 0 10px rgba(0, 255, 0, 0.8), /* Green */
|
||||
inset 100px 0 10px rgba(255, 255, 0, 0.8), /* Yellow */
|
||||
inset 50px 0 10px rgba(255, 0, 0, 0.8), /* Red */
|
||||
;
|
||||
}
|
||||
|
||||
highlight,
|
||||
progress {
|
||||
box-shadow: inset 0px 0px 2px 1px black;
|
||||
}
|
||||
}
|
||||
|
||||
.brightness.slider {
|
||||
trough{
|
||||
box-shadow:
|
||||
inset 500px 0 10px rgba(255, 255, 255, 0.5),
|
||||
inset 450px 0 10px rgba(220, 220, 220, 0.5),
|
||||
inset 400px 0 10px rgba(190, 190, 190, 0.5),
|
||||
inset 350px 0 10px rgba(160, 160, 160, 0.5),
|
||||
inset 300px 0 10px rgba(130, 130, 130, 0.5),
|
||||
inset 250px 0 10px rgba(100, 100, 100, 0.5),
|
||||
inset 200px 0 10px rgba(70, 70, 70, 0.5),
|
||||
inset 150px 0 10px rgba(40, 40, 40, 0.5),
|
||||
inset 100px 0 10px rgba(10, 10, 10, 0.5),
|
||||
inset 50px 0 10px rgba(0, 0, 0, 0.5)
|
||||
;
|
||||
|
||||
highlight,
|
||||
progress {
|
||||
box-shadow: inset 0px 0px 2px 1px white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
import Weather from '../../services/weather.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
|
||||
export const TemperatureIndicator = () => Widget.Stack({
|
||||
children: {
|
||||
true: PannelButton(),
|
||||
false: Widget.Label(),
|
||||
},
|
||||
setup: self => self.hook(Weather, () => {
|
||||
self.shown = Weather.temperatureWeather ? true : false;
|
||||
}),
|
||||
});
|
||||
|
||||
export const PannelButton = props => Widget.Button({
|
||||
...props,
|
||||
class_name: 'weather panel-button',
|
||||
child: Temperature(),
|
||||
on_clicked: () => App.toggleWindow('weather'),
|
||||
on_secondary_click: () => Weather.weatherData,
|
||||
setup: self => self
|
||||
.hook(App, (_, win, visible) => {
|
||||
self.toggleClassName('active', win === 'weather' && visible);
|
||||
}),
|
||||
});
|
||||
|
||||
export const Temperature = props => Widget.Label({
|
||||
...props,
|
||||
setup: self => self.hook(Weather, () => {
|
||||
if (Weather.temperatureWeather && self.label !== Weather.temperatureWeather) {
|
||||
self.label = Weather.temperatureWeather.toString()
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
function weatherBackgroundStyle(icon, box) {
|
||||
switch (icon) {
|
||||
case "🌇": {//sunset
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #ff6f61, #ffca58, #f0e68c);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌄": {//sunrise
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #ffcc00, #ff6f61, #ff5e62, #d55f74);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌤": {//few clouds
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #80b3ff, #ffffff, #ffdb4d);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌩": {//thunderstorm
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #0c0e23, #1a1c38, #121320, #0c0e23);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌑": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #2c3e50, #1a2533);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌕": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #001f3f, #002f4f, #003f5f, #004f6f, #005f7f);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "☀️": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #ffeb99, #ffe580, #ffd866, #ffcf4c, #ffc333);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "☁":
|
||||
case "☁️": {//cloudy
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #c4c4c4, #d1d1d1, #dedede, #ebebeb, #f8f8f8);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #1c2331, #212a38, #263141, #2b3749, #303d51);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {//fog
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #d8d8d8, #e2e2e2, #ececec, #f6f6f6, #ffffff);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #1c2331, #1c2331, #1c2331, #293547, #38475f);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "⛈️": {//heavy rain
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #2c3e50, #34495e, #2c3e50, #34495e, #2c3e50);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #050818, #070b1d, #0a0e22, #0d1126, #10152b);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌦️": {//light rain
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #547aad, #6692b8, #78a9c3, #8abfd0, #9cd7dd);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #0e1620, #121c2a, #162133, #18273c, #1c2c46);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "⛅": {//partly cloudy
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #a8c9f0, #c4dfea, #f0f0cc, #ffd700, #f0f0cc, #c4dfea, #a8c9f0);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #040d1c, #081427, #0c1a32, #101f3d, #142348);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌧️": {//rain showers
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #5e7d99, #6a8ba6, #7698b3, #87a5bf, #97b3cb, #a6c0d8, #b4cedf);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #050818, #070b1d, #0a0e22, #0d1126, #10152b);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌨": {//snow
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #d0e6ec, #e0f0f5, #f0f5f9, #f5fafd, #ffffff);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #0e1620, #162133, #1c263f, #232c4c, #293259);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "🌨️": {//sleet
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #d0e6ec, #e0f0f5, #f0f5f9, #ffffff, #f0f5f9, #e0f0f5, #d0e6ec);
|
||||
color: #000000;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
case "": {
|
||||
box.setCss(`
|
||||
background: linear-gradient(to bottom, #050818, #08142a, #0c1d3b, #101f47, #142556);
|
||||
color: #ffffff;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
box.setCss(`
|
||||
background: red;
|
||||
color: blue;
|
||||
`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const WeatherInfo = (weatherData) => Widget.Box({
|
||||
class_name: 'weather-info',
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Label({ label: weatherData.date.substring(0, 3).toUpperCase(), }),
|
||||
Widget.Label({ label: weatherData.hour + 'h', }),
|
||||
Widget.Label({ label: weatherData.icon, class_name: 'weather-icon', }),
|
||||
Widget.Label({ label: weatherData.temperature, class_name: 'weather-temperature' }),
|
||||
Widget.Box({ vexpand: true }),
|
||||
weatherData.rain !== '0 mm' ? Widget.Label({ label: weatherData.rain, }) : null,
|
||||
// Widget.Label({ label: " " + weatherData.wind, }),
|
||||
// Widget.Label({ label: weatherData.humidity, }),
|
||||
Widget.Label({ label: '↑ ' + weatherData.maxTemp, class_name: 'weather-max', }),
|
||||
Widget.Label({ label: '↓ ' + weatherData.minTemp, class_name: 'weather-min', }),
|
||||
],
|
||||
setup: self => self.hook(Weather, () => {
|
||||
weatherBackgroundStyle(weatherData.icon, self)
|
||||
}),
|
||||
});
|
||||
|
||||
function getMostCommon(arr){
|
||||
return arr.sort((a,b) =>
|
||||
arr.filter(v => v===a).length
|
||||
- arr.filter(v => v===b).length
|
||||
).pop();
|
||||
}
|
||||
|
||||
export const WeatherBoxChild = (w) => Widget.Box({
|
||||
class_name: 'qs-weather-box-child',
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Label({ label: w.hour + 'h', class_name: 'weather-hour', }),
|
||||
Widget.Label({ label: w.icon, class_name: 'weather-icon', }),
|
||||
Widget.Label({ label: w.temperature, class_name: 'weather-temperature' }),
|
||||
Widget.Box({ vexpand: true }),
|
||||
w.rain !== '0 mm' ? Widget.Label({ label: w.rain, class_name: 'weather-rain', }) : null,
|
||||
Widget.Label({ label: " " + Math.round(w.wind.replace(/kph$/, '')) + ' kph', class_name: 'weather-wind', }),
|
||||
],
|
||||
});
|
||||
|
||||
export const WeatherBoxChildWrapper = (w, temperatureDataPerDay, totalWeatherForecastDataArray) => Widget.Box({
|
||||
class_name: 'qs-weather-box-child-wrapper',
|
||||
hexpand: true,
|
||||
setup: self => self.hook(Weather, () => {
|
||||
let useTotalInstead = false;
|
||||
|
||||
if (totalWeatherForecastDataArray.length) {
|
||||
useTotalInstead = true;
|
||||
|
||||
totalWeatherForecastDataArray.forEach(totalEl => {
|
||||
self.add(
|
||||
WeatherBoxChild(totalEl),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
if (false === useTotalInstead && w && temperatureDataPerDay && temperatureDataPerDay[w.date.substring(0, 3).toUpperCase()].data.length) {
|
||||
temperatureDataPerDay[w.date.substring(0, 3).toUpperCase()].data.forEach(el => {
|
||||
self.add(
|
||||
WeatherBoxChild(el),
|
||||
)
|
||||
})
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
export const WeatherMainWidget = (widgetIcon, widgetDate, rain, temperatureDataPerDay, w, totalWeatherForecastDataArray = []) => Widget.Box({
|
||||
class_name: 'qsweather-widget',
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Box({
|
||||
class_name: 'qs-weather-box-main',
|
||||
children: [
|
||||
Widget.Label({ label: widgetIcon, class_name: 'weather-icon', }),
|
||||
rain != 0 ? Widget.Label({ label: rain + 'mm', class_name: 'weather-rain', }): null,
|
||||
Widget.Box({ hexpand: true }),
|
||||
Widget.Label({ label: '↑ ' + temperatureDataPerDay[widgetDate.substring(0, 3).toUpperCase()].maxTemp + ' ', class_name: 'weather-max', }),
|
||||
Widget.Label({ label: '↓ ' + temperatureDataPerDay[widgetDate.substring(0, 3).toUpperCase()].minTemp + ' ', class_name: 'weather-min', }),
|
||||
Widget.Label({ label: widgetDate.substring(0, 3).toUpperCase(), class_name: 'weather-hour', }),
|
||||
]
|
||||
}),
|
||||
WeatherBoxChildWrapper(w, temperatureDataPerDay, totalWeatherForecastDataArray)
|
||||
|
||||
],
|
||||
setup: self => self.hook(Weather, () => {
|
||||
weatherBackgroundStyle(widgetIcon, self);
|
||||
}),
|
||||
});
|
||||
|
||||
export const Tooltip = (total = null) => Widget.Box({
|
||||
setup: self => self.hook(Weather, () => {
|
||||
let tooltip = Weather.tooltip;
|
||||
|
||||
if (tooltip) {
|
||||
self.get_children().forEach(ch => ch.destroy());
|
||||
|
||||
let prevDayName = null;
|
||||
let temperatureDataPerDay = {};
|
||||
let weatherStatusIconArray = [];
|
||||
let weatherForecastDataArray = [];
|
||||
let totalWeatherForecastDataArray = [];
|
||||
|
||||
let totalWeatherForecastsCounter = total;
|
||||
let forecastWidgetsNumber = 0;
|
||||
|
||||
tooltip.forEach(w => {
|
||||
if (w.date !== prevDayName) {
|
||||
weatherStatusIconArray = [];
|
||||
prevDayName = w.date;
|
||||
forecastWidgetsNumber = 0;
|
||||
weatherForecastDataArray = [];
|
||||
}
|
||||
|
||||
// used to retrieve min/max temp per day
|
||||
const date = w.date.substring(0, 3).toUpperCase();
|
||||
const temperature = parseInt(w.temperature);
|
||||
|
||||
const rain = w.rain.replace(/ mm$/, '');
|
||||
forecastWidgetsNumber = forecastWidgetsNumber + 1;
|
||||
|
||||
weatherForecastDataArray.push(w);
|
||||
|
||||
if (total && totalWeatherForecastsCounter && totalWeatherForecastsCounter > 0) {
|
||||
totalWeatherForecastDataArray.push(w);
|
||||
totalWeatherForecastsCounter = totalWeatherForecastsCounter - 1;
|
||||
}
|
||||
|
||||
// If the date is not already in the object, initialize it
|
||||
if (!temperatureDataPerDay[date]) {
|
||||
temperatureDataPerDay[date] = {
|
||||
minTemp: temperature,
|
||||
maxTemp: temperature,
|
||||
rain: rain,
|
||||
icons: [],
|
||||
widgetsNumber: forecastWidgetsNumber,
|
||||
data: weatherForecastDataArray,
|
||||
};
|
||||
} else {
|
||||
// Update min and max temperatures if necessary
|
||||
temperatureDataPerDay[date].minTemp = Math.min(temperatureDataPerDay[date].minTemp, temperature);
|
||||
temperatureDataPerDay[date].maxTemp = Math.max(temperatureDataPerDay[date].maxTemp, temperature);
|
||||
temperatureDataPerDay[date].rain = Math.max(temperatureDataPerDay[date].rain, rain);
|
||||
temperatureDataPerDay[date].icons = weatherStatusIconArray;
|
||||
temperatureDataPerDay[date].widgetsNumber = forecastWidgetsNumber;
|
||||
temperatureDataPerDay[date].data = weatherForecastDataArray;
|
||||
}
|
||||
|
||||
// add icon to the array in between somewhat sunny hours, used to later get most common icon for main widget days
|
||||
if (w.hour >= 7 && w.hour <= 19) {
|
||||
weatherStatusIconArray.push(w.icon);
|
||||
}
|
||||
});
|
||||
|
||||
// clear for next loop
|
||||
prevDayName = null;
|
||||
|
||||
let widgetIcon = null;
|
||||
let widgetDate = null;
|
||||
|
||||
let w = null;
|
||||
for (let i = 0; i < tooltip.length; i++) {
|
||||
w = tooltip[i];
|
||||
|
||||
// console.log('loop ' + w.date + ' h ' + w.hour + ' i ' + w.icon )
|
||||
|
||||
// used to limit forecast to specified amount (if total variable is provided, it will display that amount of forecast widgets on a main one)
|
||||
if (total && total >= 0) {
|
||||
|
||||
if (!widgetIcon) {
|
||||
widgetIcon = w.icon;
|
||||
}
|
||||
|
||||
if (!widgetDate) {
|
||||
widgetDate = w.date;
|
||||
}
|
||||
|
||||
const rain = temperatureDataPerDay[widgetDate.substring(0, 3).toUpperCase()].rain;
|
||||
|
||||
self.add(
|
||||
WeatherMainWidget(widgetIcon, widgetDate, rain, temperatureDataPerDay, w, totalWeatherForecastDataArray)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
// if provided date differs to previous day name, by default prevDayName is null
|
||||
if (w.date !== prevDayName && i > 0) {
|
||||
// adds spacing to the widgets
|
||||
self.add(
|
||||
Widget.Box({
|
||||
children: [
|
||||
Widget.Label({ label: ' ', class_name: 'weather-spacing' }),
|
||||
],
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
// logic that determines if the widget contains just 1 forecast widget, if so it will display it in a smaller widget - like the one for the forecast days
|
||||
if (temperatureDataPerDay[w.date.substring(0, 3).toUpperCase()].widgetsNumber === 1) {
|
||||
prevDayName = w.date;
|
||||
|
||||
self.add(WeatherInfo(w));
|
||||
continue;
|
||||
}
|
||||
|
||||
// this one creates main one - wide weather widget that contains smaller forecast widgets
|
||||
if (w.date !== prevDayName) {
|
||||
const rain = temperatureDataPerDay[w.date.substring(0, 3).toUpperCase()].rain;
|
||||
let icon = getMostCommon(temperatureDataPerDay[w.date.substring(0, 3).toUpperCase()].icons);
|
||||
widgetDate = w.date;
|
||||
|
||||
if (!icon) {
|
||||
icon = w.icon;
|
||||
}
|
||||
|
||||
widgetIcon = icon;
|
||||
|
||||
self.add(
|
||||
WeatherMainWidget(widgetIcon, widgetDate, rain, temperatureDataPerDay, w)
|
||||
);
|
||||
}
|
||||
|
||||
prevDayName = w.date;
|
||||
};
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
export const ResetTimer = props => Widget.Label({
|
||||
...props,
|
||||
setup: self => {
|
||||
self.poll(600000, (self) => {
|
||||
Weather.weatherData
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export const Forecast = () => Widget.Box({
|
||||
class_name: 'datemenu',
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Box({
|
||||
class_name: 'tooltip',
|
||||
children: [
|
||||
ResetTimer(),
|
||||
Tooltip(),
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
export const PopupContent = () => Widget.Box({
|
||||
class_name: 'weather',
|
||||
vexpand: false,
|
||||
children: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Forecast(),
|
||||
// RefreshButton({ class_name: 'header panel-button', }),
|
||||
]
|
||||
})
|
||||
]
|
||||
});
|
||||
|
||||
export const RefreshButton = props => Widget.Button({
|
||||
...props,
|
||||
class_name: 'weather-refresh',
|
||||
child: Widget.Icon({
|
||||
icon: 'view-refresh-symbolic',
|
||||
hpack: 'end',
|
||||
}),
|
||||
on_clicked: () => {
|
||||
Weather.weatherData
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
class Weather extends Service {
|
||||
static { Service.register(this); }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._temperatureWeather = null;
|
||||
this._tooltip = null;
|
||||
}
|
||||
|
||||
get weatherData() {
|
||||
Utils.execAsync(['bash', '-c', "openweathermap ags"]).catch(print);
|
||||
}
|
||||
|
||||
get temperatureWeather() {
|
||||
return this._temperatureWeather;
|
||||
}
|
||||
setTemperatureWeather(temp) {
|
||||
this._temperatureWeather = temp;
|
||||
this.emit('changed');
|
||||
}
|
||||
|
||||
get tooltip() {
|
||||
return this._tooltip;
|
||||
}
|
||||
setTooltip(text) { this._tooltip = text }
|
||||
}
|
||||
|
||||
export default new Weather();
|
||||
Reference in new issue
Block a user