diff --git a/.config/ags/data/weather.js b/.config/ags/data/weather.js new file mode 100644 index 000000000..57c34fb1b --- /dev/null +++ b/.config/ags/data/weather.js @@ -0,0 +1,94 @@ +export const WWO_CODE = { + "113": "Sunny", + "116": "PartlyCloudy", + "119": "Cloudy", + "122": "VeryCloudy", + "143": "Fog", + "176": "LightShowers", + "179": "LightSleetShowers", + "182": "LightSleet", + "185": "LightSleet", + "200": "ThunderyShowers", + "227": "LightSnow", + "230": "HeavySnow", + "248": "Fog", + "260": "Fog", + "263": "LightShowers", + "266": "LightRain", + "281": "LightSleet", + "284": "LightSleet", + "293": "LightRain", + "296": "LightRain", + "299": "HeavyShowers", + "302": "HeavyRain", + "305": "HeavyShowers", + "308": "HeavyRain", + "311": "LightSleet", + "314": "LightSleet", + "317": "LightSleet", + "320": "LightSnow", + "323": "LightSnowShowers", + "326": "LightSnowShowers", + "329": "HeavySnow", + "332": "HeavySnow", + "335": "HeavySnowShowers", + "338": "HeavySnow", + "350": "LightSleet", + "353": "LightShowers", + "356": "HeavyShowers", + "359": "HeavyRain", + "362": "LightSleetShowers", + "365": "LightSleetShowers", + "368": "LightSnowShowers", + "371": "HeavySnowShowers", + "374": "LightSleetShowers", + "377": "LightSleet", + "386": "ThunderyShowers", + "389": "ThunderyHeavyRain", + "392": "ThunderySnowShowers", + "395": "HeavySnowShowers", +} + +export const WEATHER_SYMBOL = { + "Unknown": "air", + "Cloudy": "cloud", + "Fog": "foggy", + "HeavyRain": "rainy", + "HeavyShowers": "rainy", + "HeavySnow": "snowing", + "HeavySnowShowers": "snowing", + "LightRain": "rainy", + "LightShowers": "rainy", + "LightSleet": "rainy", + "LightSleetShowers": "rainy", + "LightSnow": "cloudy_snowing", + "LightSnowShowers": "cloudy_snowing", + "PartlyCloudy": "partly_cloudy_day", + "Sunny": "clear_day", + "ThunderyHeavyRain": "thunderstorm", + "ThunderyShowers": "thunderstorm", + "ThunderySnowShowers": "thunderstorm", + "VeryCloudy": "cloud", +} + +export const NIGHT_WEATHER_SYMBOL = { + "Unknown": "air", + "Cloudy": "cloud", + "Fog": "foggy", + "HeavyRain": "rainy", + "HeavyShowers": "rainy", + "HeavySnow": "snowing", + "HeavySnowShowers": "snowing", + "LightRain": "rainy", + "LightShowers": "rainy", + "LightSleet": "rainy", + "LightSleetShowers": "rainy", + "LightSnow": "cloudy_snowing", + "LightSnowShowers": "cloudy_snowing", + "PartlyCloudy": "partly_cloudy_night", + "Sunny": "clear_night", + "ThunderyHeavyRain": "thunderstorm", + "ThunderyShowers": "thunderstorm", + "ThunderySnowShowers": "thunderstorm", + "VeryCloudy": "cloud", +} \ No newline at end of file diff --git a/.config/ags/widgets/bar/system.js b/.config/ags/widgets/bar/system.js index 2807b1d9b..a842f9518 100644 --- a/.config/ags/widgets/bar/system.js +++ b/.config/ags/widgets/bar/system.js @@ -8,8 +8,11 @@ const { GLib } = imports.gi; import Battery from 'resource:///com/github/Aylur/ags/service/battery.js'; import { MaterialIcon } from '../../lib/materialicon.js'; import { AnimatedCircProg } from "../../lib/animatedcircularprogress.js"; +import { WWO_CODE, WEATHER_SYMBOL, NIGHT_WEATHER_SYMBOL } from '../../data/weather.js'; const BATTERY_LOW = 20; +const WEATHER_CACHE_FOLDER = `${GLib.get_user_cache_dir()}/ags/weather`; +Utils.exec(`mkdir -p ${WEATHER_CACHE_FOLDER}`); const BatBatteryProgress = () => { const _updateProgress = (circprog) => { // Set circular progress value @@ -90,7 +93,7 @@ const BarBattery = () => Box({ transitionDuration: 150, revealChild: false, transition: 'slide_right', - child: MaterialIcon('bolt', 'norm', {tooltipText: "Charging"}), + child: MaterialIcon('bolt', 'norm', { tooltipText: "Charging" }), setup: (self) => self.hook(Battery, revealer => { self.revealChild = Battery.charging; }), @@ -130,6 +133,73 @@ const BarGroup = ({ child }) => Widget.Box({ }), ] }); +const BatteryModule = () => Stack({ + transition: 'slide_up_down', + transitionDuration: 150, + items: [ + ['laptop', Box({ + className: 'spacing-h-5', children: [ + BarGroup({ child: Utilities() }), + BarGroup({ child: BarBattery() }), + ] + })], + ['desktop', BarGroup({ + child: Box({ + hexpand: true, + hpack: 'center', + className: 'spacing-h-5', + children: [ + MaterialIcon('device_thermostat', 'small'), + Label({ + label: 'Weather', + }) + ], + setup: (self) => self.poll(900000, async (self) => { + const WEATHER_CACHE_PATH = WEATHER_CACHE_FOLDER + '/wttr.in.txt'; + Utils.execAsync('curl ipinfo.io') + .then(output => { + return JSON.parse(output)['city'].toLowerCase(); + }) + .then((city) => execAsync(`curl https://wttr.in/${city}?format=j1`) + .then(output => { + console.log(`curl https://wttr.in/${city}?format=j1`); + const weather = JSON.parse(output); + Utils.writeFile(JSON.stringify(weather), WEATHER_CACHE_PATH) + .catch(print); + const weatherCode = weather.current_condition[0].weatherCode; + const weatherDesc = weather.current_condition[0].weatherDesc[0].value; + const temperature = weather.current_condition[0].temp_C; + const feelsLike = weather.current_condition[0].FeelsLikeC; + const weatherSymbol = WEATHER_SYMBOL[WWO_CODE[weatherCode]]; + self.children[0].label = weatherSymbol; + self.children[1].label = `${temperature}℃ • Feels like ${feelsLike}℃`; + self.tooltipText = weatherDesc; + }).catch((err) => { + try { // Read from cache + const weather = JSON.parse( + Utils.readFile(WEATHER_CACHE_PATH) + ); + const weatherCode = weather.current_condition[0].weatherCode; + const weatherDesc = weather.current_condition[0].weatherDesc[0].value; + const temperature = weather.current_condition[0].temp_C; + const feelsLike = weather.current_condition[0].FeelsLikeC; + const weatherSymbol = WEATHER_SYMBOL[WWO_CODE[weatherCode]]; + self.children[0].label = weatherSymbol; + self.children[1].label = `${temperature}℃ • Feels like ${feelsLike}℃`; + self.tooltipText = weatherDesc; + } catch (err) { + print(err); + } + })); + }), + }) + })], + ], + setup: (stack) => Utils.timeout(10, () => { + if (!Battery.available) stack.shown = 'desktop'; + else stack.shown = 'laptop'; + }) +}) const switchToRelativeWorkspace = async (self, num) => { try { @@ -140,6 +210,7 @@ const switchToRelativeWorkspace = async (self, num) => { } } + export default () => Widget.EventBox({ onScrollUp: (self) => switchToRelativeWorkspace(self, -1), onScrollDown: (self) => switchToRelativeWorkspace(self, +1), @@ -148,30 +219,7 @@ export default () => Widget.EventBox({ className: 'spacing-h-5', children: [ BarGroup({ child: BarClock() }), - Stack({ - transition: 'slide_up_down', - transitionDuration: 150, - items: [ - ['laptop', Box({ - className: 'spacing-h-5', children: [ - BarGroup({ child: Utilities() }), - BarGroup({ child: BarBattery() }), - ] - })], - ['desktop', Box({ - className: 'spacing-h-5', - children: [ - Label({ - label: 'Weather', - }) - ] - })], - ], - setup: (stack) => Utils.timeout(10, () => { - if (!Battery.available) stack.shown = 'desktop'; - else stack.shown = 'laptop'; - }) - }) + BatteryModule(), ] }) });