-
Notifications
You must be signed in to change notification settings - Fork 55
/
index.js
148 lines (114 loc) · 4.94 KB
/
index.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
const {ipcRenderer, shell} = require('electron')
let previousWeather = undefined
let voice = undefined
document.addEventListener('click', (event) => {
if (event.target.href) {
// Open links in external browser
shell.openExternal(event.target.href)
event.preventDefault()
} else if (event.target.classList.contains('js-refresh-action')) {
updateWeather()
} else if (event.target.classList.contains('js-quit-action')) {
window.close()
}
})
const getGeoLocation = () => {
return new Promise((resolve, reject) => {
navigator.geolocation.getCurrentPosition(resolve, reject)
})
}
const getWeather = (position) => {
// FIXME replace with your own API key
// Register for one at https://developer.forecast.io/register
const apiKey = '781969e20c5d295ae9bd8da62df0d3f7'
const location = `${position.coords.latitude},${position.coords.longitude}`
console.log(`Getting weather for ${location}`)
const url = `https://api.forecast.io/forecast/${apiKey}/${location}`
return window.fetch(url).then((response) => {
return response.json()
})
}
const updateView = (weather) => {
const currently = weather.currently
document.querySelector('.js-summary').textContent = currently.summary
document.querySelector('.js-update-time').textContent = `at ${new Date(currently.time).toLocaleTimeString()}`
document.querySelector('.js-temperature').textContent = `${Math.round(currently.temperature)}° F`
document.querySelector('.js-apparent').textContent = `${Math.round(currently.apparentTemperature)}° F`
document.querySelector('.js-wind').textContent = `${Math.round(currently.windSpeed)} mph`
document.querySelector('.js-wind-direction').textContent = getWindDirection(currently.windBearing)
document.querySelector('.js-dewpoint').textContent = `${Math.round(currently.dewPoint)}° F`
document.querySelector('.js-humidity').textContent = `${Math.round(currently.humidity * 100)}%`
document.querySelector('.js-visibility').textContent = `${Math.round(currently.windSpeed)} miles`
document.querySelector('.js-cloud-cover').textContent = `${Math.round(currently.cloudCover * 100)}%`
document.querySelector('.js-precipitation-chance').textContent = `${Math.round(currently.precipProbability * 100)}%`
document.querySelector('.js-precipitation-rate').textContent = currently.precipIntensity
}
const getWindDirection = (direction) => {
if (direction < 45) return 'NNE'
if (direction === 45) return 'NE'
if (direction < 90) return 'ENE'
if (direction === 90) return 'E'
if (direction < 135) return 'ESE'
if (direction === 135) return 'SE'
if (direction < 180) return 'SSE'
if (direction === 180) return 'S'
if (direction < 225) return 'SSW'
if (direction === 225) return 'SW'
if (direction < 270) return 'WSW'
if (direction === 270) return 'W'
if (direction < 315) return 'WNW'
if (direction === 315) return 'NW'
if (direction < 360) return 'NNW'
return 'N'
}
const isWeatherIdeal = (weather) => {
// Precipipation is never ideal...
if (weather.currently.precipIntensity !== 0) return false
// Ideal weather is within 3 degress of the ideal temperature
const idealTemperature = 70
const feelsLikeTemperature = weather.currently.apparentTemperature
return Math.abs(idealTemperature - feelsLikeTemperature) <= 3
}
const sendNotification = (weather) => {
if (!isWeatherIdeal(weather)) return
// Show notification if it is the first time checking the weather or if it was
// previously not ideal but is now ideal
if (previousWeather == null || !isWeatherIdeal(previousWeather)) {
const summary = weather.currently.summary.toLowerCase()
const feelsLike = Math.round(weather.currently.apparentTemperature)
let notification = new Notification('Go outside', {
body: `The weather is ${summary} and feels like ${feelsLike}° F`
})
// Show window when notification is clicked
notification.onclick = () => {
ipcRenderer.send('show-window')
}
speakTheGoodNews(weather)
}
}
const speakTheGoodNews = (weather) => {
const summary = weather.currently.summary.toLowerCase()
const feelsLike = Math.round(weather.currently.apparentTemperature)
const utterance = new SpeechSynthesisUtterance(`Go outside! The weather is ${summary} and feels like ${feelsLike} degrees.`)
utterance.voice = voice
speechSynthesis.speak(utterance)
}
speechSynthesis.onvoiceschanged = () => {
voice = speechSynthesis.getVoices().find((voice) => voice.name === 'Good News')
}
const updateWeather = () => {
getGeoLocation().then(getWeather).then((weather) => {
// Use local time
weather.currently.time = Date.now()
console.log('Got weather', weather)
ipcRenderer.send('weather-updated', weather)
updateView(weather)
sendNotification(weather)
previousWeather = weather
})
}
// Refresh weather every 10 minutes
const tenMinutes = 10 * 60 * 1000
setInterval(updateWeather, tenMinutes)
// Update initial weather when loaded
document.addEventListener('DOMContentLoaded', updateWeather)