-
Notifications
You must be signed in to change notification settings - Fork 1
/
presently.js
163 lines (139 loc) · 6.94 KB
/
presently.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
namespace(function() {
// TODOs:
// - OpenSans is failing to load in FF, try downloading from here: https://www.fontsquirrel.com/fonts/open-sans
// - Make sure things fade out, where possible. E.g. errors going away / alerts going away
// - Invest in more "English" strings for network failures (i.e. not "503" or "0", use "API unavailable" or "Network disconnected")
// - When resizing the weather, persist the error (if shown)
// - https://stackoverflow.com/questions/63033412/dark-mode-flickers-a-white-background-for-a-millisecond-on-reload
// - map selector using leaflet.js (I may need to host map images)
// - Fire / smoke API: https://docs.airnowapi.org/
var DAYS = window.localize('days_of_week', 'Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday').split(', ')
var MONTHS = window.localize('months_of_year', 'January, February, March, April, May, June, July, August, September, October, November, December').split(', ')
var previousWidth = window.innerWidth
window.onresize = function() {
if (window.innerWidth < 800 && previousWidth >= 800) {
displayNeedsUpdate = true
// Manually strip the seconds off (we'll do this more carefully once the time reloads)
var time = document.getElementById('time').innerText
document.getElementById('time').innerText = time.substr(0, 5)
} else if (window.innerWidth >= 800 && previousWidth < 800) {
displayNeedsUpdate = true
timeExpires = new Date(0) // Forcibly expire the time to fetch seconds
}
previousWidth = window.innerWidth
}
function onForecastError(error) {
window.getLocal('weatherVeryExpires', function(weatherVeryExpires) {
var now = (new Date()).getTime()
if (weatherVeryExpires && now < weatherVeryExpires) return
// The weather is very expired, discard it and show an error.
window.setLocal('weatherData', null)
document.getElementById('forecast-loading').style.display = 'flex'
document.getElementById('forecast-error').innerText = error
document.getElementById('forecast').style.display = 'none'
})
}
// Default true when JS loads; we need to draw the display at least once.
window.displayNeedsUpdate = true
function updateWeather() {
window.getLocal('weatherVeryExpires', function(weatherVeryExpires) {
window.getLocal('weatherExpires', function(weatherExpires) {
window.getLocal('weatherData', function(weatherData) {
var now = (new Date()).getTime()
// If we need to redraw the display, do so as long as we have weather data that's not very expired.
if (displayNeedsUpdate && weatherData && weatherVeryExpires && now < weatherVeryExpires) {
window.drawWeatherData(weatherData)
displayNeedsUpdate = false
return
}
// If the weather is not expired, exit.
if (weatherExpires && now < weatherExpires) return
// Else, the weather is expired and should be updated.
// We prevent any updates for 1 minute to avoid making excessive network calls.
// If the weather update succeeds, we'll set a later expiration time.
weatherExpires = new Date()
weatherExpires.setMinutes(weatherExpires.getMinutes() + 1)
window.setLocal('weatherExpires', weatherExpires.getTime())
console.log('Fetching new weather data...')
window.requestLocation(onForecastError, function(coords) {
window.weatherApi.getWeather(coords, onForecastError, function(weatherData) {
console.log('Fetched new weather data')
// I'm choosing a time which is *slightly* into the next hour, since the US weather API updates on the hour.
var weatherExpires = new Date()
weatherExpires.setHours(weatherExpires.getHours() + 1, 1, 0, 0)
window.setLocal('weatherExpires', weatherExpires.getTime())
// However, the time at which we stop showing any weather at all should just be 2 hours later.
var weatherVeryExpires = new Date()
weatherVeryExpires.setHours(weatherVeryExpires.getHours() + 2, 0, 0, 0)
window.setLocal('weatherVeryExpires', weatherVeryExpires.getTime())
window.setLocal('weatherData', weatherData)
window.drawWeatherData(weatherData)
displayNeedsUpdate = false
})
})
})
})
})
}
var timeExpires = new Date(0)
function updateTime() {
var now = new Date()
if (now < timeExpires) return
timeExpires = new Date(now)
// Expire the time next second (but clear the milliseconds)
timeExpires.setSeconds(now.getSeconds() + 1, 0)
/* If I ever want an analog clock, this is how to do that:
var second = now.getSeconds() * 6,
var minute = now.getMinutes() * 6 + second / 60,
var hour = ((now.getHours() % 12) / 12) * 360 + 90 + minute / 12;
$('#hour').css('transform', 'rotate(' + hour + 'deg)');
$('#minute').css('transform', 'rotate(' + minute + 'deg)');
$('#second').css('transform', 'rotate(' + second + 'deg)');
*/
var hours = now.getHours()
if (document.getElementById('Hours-12').checked) {
hours = (hours + 11) % 12 + 1 // Convert 0-23 to 1-12
}
var timeString = hours.toString().padStart(2, '0')
timeString += ' ' + now.getMinutes().toString().padStart(2, '0')
// Don't show seconds if the window isn't wide enough
if (window.innerWidth >= 800 && document.getElementById('Seconds-On').checked) {
timeString += ' ' + now.getSeconds().toString().padStart(2, '0')
}
document.getElementById('time').innerText = timeString
var dateString = DAYS[now.getDay()] + ', ' + MONTHS[now.getMonth()] + ' ' + now.getDate()
document.getElementById('date').innerText = dateString
}
function mainLoop() {
updateTime()
updateWeather()
setTimeout(mainLoop, 100)
}
document.addEventListener("keydown", function(event) {
if (String.fromCharCode(event.keyCode) === 'T') {
if (document.getElementById('Temperature-Fahrenheit').checked) {
window.setRemote('settings-Temperature', 'Temperature-Celsius')
document.getElementById('Temperature-Celsius').checked = true
} else {
window.setRemote('settings-Temperature', 'Temperature-Fahrenheit')
document.getElementById('Temperature-Fahrenheit').checked = true
}
displayNeedsUpdate = true
}
});
document.addEventListener('DOMContentLoaded', function() {
window.loadSettings(function() {
// Request the user's location once on page load to populate sunrise/sundown times.
// On success, we also request a repaint, since this will fix any nighttime climacons.
// We need to do this after settings, so that we know which API to call.
window.requestLocation(onForecastError, function(success) {
displayNeedsUpdate = true
})
// If we navigated to ?settings (i.e. from the extension menu), immediately show settings.
if (document.location.search == '?settings') {
window.showSettings()
}
mainLoop()
})
})
})