From 753fa93886916ca022f015a63a7ecbdc0551861c Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Fri, 28 Sep 2018 19:38:49 +0200 Subject: [PATCH 1/2] get precise sunset/sunrise times --- README.md | 2 +- package.json | 1 + src/components/molecules/ThemeSwitch.jsx | 2 +- src/store/countrycode-latlong.json | 242 +++++++++++++++++++++++ src/store/provider.jsx | 111 ++++++++--- 5 files changed, 333 insertions(+), 25 deletions(-) create mode 100644 src/store/countrycode-latlong.json diff --git a/README.md b/README.md index d8ce56f..86677df 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Gatsby automatically creates pages from each item in that file utilizing the [`s ### 💅 Theme switcher -Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on time of day. +Includes a theme switcher which allows user to toggle between a light and a dark theme. Switching between them also happens automatically based on user's local sunset and sunrise times. Uses Cloudflare's geo location HTTP header functionality. If you want to know how, have a look at the respective component under [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx) diff --git a/package.json b/package.json index ebb9c4b..f6d7a1b 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "react-helmet": "^5.2.0", "react-markdown": "^3.6.0", "react-pose": "^3.3.4", + "suncalc": "^1.8.0", "vcf": "^2.0.1" }, "devDependencies": { diff --git a/src/components/molecules/ThemeSwitch.jsx b/src/components/molecules/ThemeSwitch.jsx index 5630a10..1443ccb 100644 --- a/src/components/molecules/ThemeSwitch.jsx +++ b/src/components/molecules/ThemeSwitch.jsx @@ -25,7 +25,7 @@ ThemeToggle.propTypes = { const ThemeToggleInput = ({ dark, toggleDark }) => ( { - this.setState({ dark: !this.state.dark }) - - if (this.store) { - this.store.setItem('dark', !this.state.dark) - } - } + toggleDark: () => this.toggleDark, + location: null } static propTypes = { @@ -20,35 +17,103 @@ export default class AppProvider extends Component { store = typeof localStorage === 'undefined' ? null : localStorage - darkLocalStorageMode = darkLocalStorage => { + // + // Get user location from Cloudflare's geo location HTTP header + // + getCountry = async () => { + let trace = [] + + await fetch('/cdn-cgi/trace?no-cache=1') + .then(data => { + let lines + + data.text().then(text => { + lines = text.split('\n') + + let keyValue + + lines.forEach(line => { + keyValue = line.split('=') + trace[keyValue[0]] = decodeURIComponent(keyValue[1] || '') + + if (keyValue[0] === 'loc' && trace['loc'] !== 'XX') { + this.setState({ location: trace['loc'] }) + } else { + return + } + }) + }) + }) + .catch(() => null) // fail silently + } + + setDark() { + this.setState({ dark: true }) + } + + setLight() { + this.setState({ dark: false }) + } + + darkLocalStorageMode(darkLocalStorage) { if (darkLocalStorage === 'true') { - this.setState({ dark: true }) + this.setDark() } else { - this.setState({ dark: false }) + this.setLight() } } - darkMode = now => { - if (!this.state.dark && (now >= 19 || now <= 7)) { - this.setState({ dark: true }) - } else { - this.setState({ dark: null }) - } - } - - checkDark = () => { + // + // All the checks to see if we should go dark or light + // + darkMode() { const now = new Date().getHours() + + // fallback times, in hours + let sunrise = 7 + let sunset = 19 + + // times based on detected country code + if (this.state.location && this.state.location !== 'XX') { + const country = this.state.location.toLowerCase() + const times = SunCalc.getTimes( + new Date(), + countrycodes[country][0], + countrycodes[country][1] + ) + sunrise = times.sunrise.getHours() + sunset = times.sunset.getHours() + } + + if (!this.state.dark && (now >= sunset || now <= sunrise)) { + this.setDark() + } else { + this.setLight() + } + } + + checkDark() { const darkLocalStorage = this.store.getItem('dark') if (darkLocalStorage) { this.darkLocalStorageMode(darkLocalStorage) } else { - this.darkMode(now) + this.darkMode() + } + } + + toggleDark = () => { + this.setState({ dark: !this.state.dark }) + + if (this.store) { + this.store.setItem('dark', !this.state.dark) } } componentDidMount() { - this.checkDark() + this.getCountry().then(() => { + this.checkDark() + }) } render() { From b24c3a28acd4d037e0510ce2cd99b6e8dd4bcc2d Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Fri, 28 Sep 2018 19:52:09 +0200 Subject: [PATCH 2/2] account for Tor country --- src/store/provider.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store/provider.jsx b/src/store/provider.jsx index be09583..bae29b5 100644 --- a/src/store/provider.jsx +++ b/src/store/provider.jsx @@ -68,13 +68,13 @@ export default class AppProvider extends PureComponent { // darkMode() { const now = new Date().getHours() - + const { location } = this.state // fallback times, in hours let sunrise = 7 let sunset = 19 // times based on detected country code - if (this.state.location && this.state.location !== 'XX') { + if (location && location !== 'XX' && location !== 'T1') { const country = this.state.location.toLowerCase() const times = SunCalc.getTimes( new Date(),