@@ -171,14 +171,16 @@ local function worker(user_args)
171
171
local api_key = args .api_key
172
172
local font_name = args .font_name or beautiful .font :gsub (" %s%d+$" , " " )
173
173
local units = args .units or ' metric'
174
+ local time_format_12h = args .time_format_12h
174
175
local both_units_widget = args .both_units_widget or false
175
176
local icon_pack_name = args .icons or ' weather-underground-icons'
176
177
local icons_extension = args .icons_extension or ' .png'
177
- local show_forecast = args .show_forecast or false
178
+ local show_daily_forecast = args .show_daily_forecast or false
179
+ local show_hourly_forecast = args .show_hourly_forecast or false
178
180
local timeout = args .timeout or 120
179
181
180
182
local ICONS_DIR = WIDGET_DIR .. ' /icons/' .. icon_pack_name .. ' /'
181
- -- Forecast endpoint includes current. I could map show_forecast to days here.
183
+ -- Forecast endpoint includes current. I could map show_daily_forecast to days here.
182
184
-- Currently overfetching but only showing when opting in.
183
185
local weather_api =
184
186
(' https://api.weatherapi.com/v1/forecast.json' ..
@@ -304,7 +306,7 @@ local function worker(user_args)
304
306
end
305
307
}
306
308
307
- local forecast_widget = {
309
+ local daily_forecast_widget = {
308
310
forced_width = 300 ,
309
311
layout = wibox .layout .flex .horizontal ,
310
312
update = function (self , forecast )
@@ -364,6 +366,181 @@ local function worker(user_args)
364
366
end
365
367
}
366
368
369
+ local hourly_forecast_graph = wibox .widget {
370
+ step_width = 12 ,
371
+ color = ' #EBCB8B' ,
372
+ background_color = beautiful .bg_normal ,
373
+ forced_height = 100 ,
374
+ forced_width = 300 ,
375
+ widget = wibox .widget .graph ,
376
+ set_max_value = function (self , new_max_value )
377
+ self .max_value = new_max_value
378
+ end ,
379
+ set_min_value = function (self , new_min_value )
380
+ self .min_value = new_min_value
381
+ end ,
382
+ }
383
+
384
+ local hourly_forecast_negative_graph = wibox .widget {
385
+ step_width = 12 ,
386
+ color = ' #5E81AC' ,
387
+ background_color = beautiful .bg_normal ,
388
+ forced_height = 100 ,
389
+ forced_width = 300 ,
390
+ widget = wibox .widget .graph ,
391
+ set_max_value = function (self , new_max_value )
392
+ self .max_value = new_max_value
393
+ end ,
394
+ set_min_value = function (self , new_min_value )
395
+ self .min_value = new_min_value
396
+ end ,
397
+ }
398
+
399
+ local hourly_forecast_widget = {
400
+ layout = wibox .layout .fixed .vertical ,
401
+ update = function (self , hourly )
402
+ local hours_below = {
403
+ id = ' hours' ,
404
+ forced_width = 300 ,
405
+ layout = wibox .layout .flex .horizontal
406
+ }
407
+ local temp_below = {
408
+ id = ' temp' ,
409
+ forced_width = 300 ,
410
+ layout = wibox .layout .flex .horizontal
411
+ }
412
+
413
+ local max_temp = - 1000
414
+ local min_temp = 1000
415
+ local values = {}
416
+
417
+ -- Yeah, this looks weird. I would expect to have to use ipairs
418
+ for i , hour in pairs (hourly ) do
419
+ if i > 25 then
420
+ break
421
+ end
422
+
423
+ values [i ] = hour .temp_c
424
+
425
+ if max_temp < hour .temp_c then
426
+ max_temp = hour .temp_c
427
+ end
428
+
429
+ if min_temp > hour .temp_c then
430
+ min_temp = hour .temp_c
431
+ end
432
+
433
+ if (i - 1 ) % 5 == 0 then
434
+ table.insert (hours_below , wibox .widget {
435
+ text = os.date (time_format_12h and ' %I%p' or ' %H:00' , tonumber (hour .time_epoch )),
436
+ align = ' center' ,
437
+ font = font_name .. ' 9' ,
438
+ widget = wibox .widget .textbox
439
+ })
440
+
441
+ table.insert (temp_below , wibox .widget {
442
+ markup = ' <span foreground=""'
443
+ .. (tonumber (hour .temp_c ) > 0 and ' #2E3440' or ' #ECEFF4' ) .. ' ">'
444
+ .. string.format (' %.0f' , hour .temp_c ) .. ' °' .. ' </span>' ,
445
+ align = ' center' ,
446
+ font = font_name .. ' 9' ,
447
+ widget = wibox .widget .textbox
448
+ })
449
+ end
450
+ end
451
+
452
+ hourly_forecast_graph :set_max_value (math.max (max_temp , math.abs (min_temp )))
453
+ hourly_forecast_graph :set_min_value (min_temp > 0 and min_temp * 0.7 or 0 ) -- move graph a bit up
454
+
455
+ hourly_forecast_negative_graph :set_max_value (math.abs (min_temp ))
456
+ hourly_forecast_negative_graph :set_min_value (max_temp < 0 and math.abs (max_temp ) * 0.7 or 0 )
457
+
458
+ for _ , value in ipairs (values ) do
459
+ if value >= 0 then
460
+ hourly_forecast_graph :add_value (value )
461
+ hourly_forecast_negative_graph :add_value (0 )
462
+ else
463
+ hourly_forecast_graph :add_value (0 )
464
+ hourly_forecast_negative_graph :add_value (math.abs (value ))
465
+ end
466
+ end
467
+
468
+ local count = # self
469
+ for i = 0 , count do
470
+ self [i ] = nil
471
+ end
472
+
473
+ -- all temperatures are positive
474
+ if min_temp > 0 then
475
+ table.insert (self , wibox .widget {
476
+ {
477
+ hourly_forecast_graph ,
478
+ reflection = { horizontal = true },
479
+ widget = wibox .container .mirror
480
+ },
481
+ {
482
+ temp_below ,
483
+ valign = ' bottom' ,
484
+ widget = wibox .container .place
485
+ },
486
+ id = ' graph' ,
487
+ layout = wibox .layout .stack
488
+ })
489
+ table.insert (self , hours_below )
490
+
491
+ -- all temperatures are negative
492
+ elseif max_temp < 0 then
493
+ table.insert (self , hours_below )
494
+ table.insert (self , wibox .widget {
495
+ {
496
+ hourly_forecast_negative_graph ,
497
+ reflection = { horizontal = true , vertical = true },
498
+ widget = wibox .container .mirror
499
+ },
500
+ {
501
+ temp_below ,
502
+ valign = ' top' ,
503
+ widget = wibox .container .place
504
+ },
505
+ id = ' graph' ,
506
+ layout = wibox .layout .stack
507
+ })
508
+
509
+ -- mixed temperatures
510
+ else
511
+ table.insert (self , wibox .widget {
512
+ {
513
+ hourly_forecast_graph ,
514
+ reflection = { horizontal = true },
515
+ widget = wibox .container .mirror
516
+ },
517
+ {
518
+ temp_below ,
519
+ valign = ' bottom' ,
520
+ widget = wibox .container .place
521
+ },
522
+ id = ' graph' ,
523
+ layout = wibox .layout .stack
524
+ })
525
+
526
+ table.insert (self , wibox .widget {
527
+ {
528
+ hourly_forecast_negative_graph ,
529
+ reflection = { horizontal = true , vertical = true },
530
+ widget = wibox .container .mirror
531
+ },
532
+ {
533
+ temp_below ,
534
+ valign = ' top' ,
535
+ widget = wibox .container .place
536
+ },
537
+ id = ' graph' ,
538
+ layout = wibox .layout .stack
539
+ })
540
+ end
541
+ end
542
+ }
543
+
367
544
local function update_widget (widget , stdout , stderr )
368
545
if stderr ~= ' ' then
369
546
if not warning_shown then
@@ -411,9 +588,14 @@ local function worker(user_args)
411
588
}
412
589
413
590
414
- if show_forecast then
415
- forecast_widget :update (result .forecast .forecastday )
416
- table.insert (final_widget , forecast_widget )
591
+ if show_hourly_forecast then
592
+ hourly_forecast_widget :update (result .forecast .forecastday [1 ].hour )
593
+ table.insert (final_widget , hourly_forecast_widget )
594
+ end
595
+
596
+ if show_daily_forecast then
597
+ daily_forecast_widget :update (result .forecast .forecastday )
598
+ table.insert (final_widget , daily_forecast_widget )
417
599
end
418
600
419
601
weather_popup :setup ({
0 commit comments