mirror of
https://github.com/kremalicious/portfolio.git
synced 2024-11-15 01:25:25 +01:00
Merge pull request #190 from kremalicious/feature/switch-dark-mode-component
feature/switch-dark-mode-component
This commit is contained in:
commit
a3331b0581
@ -80,14 +80,11 @@ If you want to know how, have a look at the respective components:
|
||||
|
||||
### 💅 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 user's local sunset and sunrise times. Uses Cloudflare's geo location HTTP header functionality.
|
||||
|
||||
If a visitor has set the theme manually that selection is remembered in `localStorage`, and is restored on next visit.
|
||||
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 system preferences. If a visitor has set the theme manually that selection is remembered in `localStorage`, and is restored on next visit. All handled by [use-dark-mode](https://github.com/donavon/use-dark-mode)
|
||||
|
||||
If you want to know how, have a look at the respective components:
|
||||
|
||||
- [`src/components/molecules/ThemeSwitch.jsx`](src/components/molecules/ThemeSwitch.jsx)
|
||||
- [`src/hooks/use-dark-mode.jsx`](src/hooks/use-dark-mode.jsx)
|
||||
|
||||
### 🏆 SEO component
|
||||
|
||||
|
@ -71,6 +71,14 @@ module.exports = {
|
||||
theme_color_in_head: false // dynamically set in ThemeSwitch
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: 'gatsby-plugin-use-dark-mode',
|
||||
options: {
|
||||
classNameDark: 'dark',
|
||||
classNameLight: 'light',
|
||||
minify: true
|
||||
}
|
||||
},
|
||||
'gatsby-plugin-react-helmet',
|
||||
'gatsby-transformer-sharp',
|
||||
'gatsby-plugin-sharp',
|
||||
|
46
package-lock.json
generated
46
package-lock.json
generated
@ -3683,6 +3683,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@use-it/event-listener": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@use-it/event-listener/-/event-listener-0.1.3.tgz",
|
||||
"integrity": "sha512-UCHkLOVU+xj3/1R8jXz8GzDTowkzfIDPESOBlVC2ndgwUSBEqiFdwCoUEs2lcGhJOOiEdmWxF+T23C5+60eEew=="
|
||||
},
|
||||
"@webassemblyjs/ast": {
|
||||
"version": "1.8.5",
|
||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
|
||||
@ -11464,6 +11469,15 @@
|
||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-svgr/-/gatsby-plugin-svgr-2.0.2.tgz",
|
||||
"integrity": "sha512-54REIMe79qFBAwpcnWHBkvEE9CKoEVkefF9rDXai0k642r91SZ4UeWFuAmsegPG+sPVub7tHfHu/2LVXK1I9kg=="
|
||||
},
|
||||
"gatsby-plugin-use-dark-mode": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-use-dark-mode/-/gatsby-plugin-use-dark-mode-1.1.2.tgz",
|
||||
"integrity": "sha512-qZEg4XmCgeq4M7ojxMUTFFj951QMGb95pWnxsSvb4nsTWTYSb0qeRE+hR/4rE5GIFnh/w9GrwuyMwStM7o7R6Q==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2",
|
||||
"terser": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"gatsby-plugin-webpack-bundle-analyser-v2": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/gatsby-plugin-webpack-bundle-analyser-v2/-/gatsby-plugin-webpack-bundle-analyser-v2-1.1.8.tgz",
|
||||
@ -23463,11 +23477,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"suncalc": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/suncalc/-/suncalc-1.8.0.tgz",
|
||||
"integrity": "sha1-HZiYEJVjB4dQ9JlKlZ5lTYdqy/U="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
@ -24545,6 +24554,23 @@
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
||||
},
|
||||
"use-dark-mode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/use-dark-mode/-/use-dark-mode-2.3.1.tgz",
|
||||
"integrity": "sha512-hmcdJR96tTustRQdaQwe6jMrZHnmPqXBxgy4jaQ4gsfhwajsCpjECuq9prgDe9XxMx/f9r96o2/md6O4Lwhwjg==",
|
||||
"requires": {
|
||||
"@use-it/event-listener": "^0.1.2",
|
||||
"use-persisted-state": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"use-persisted-state": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/use-persisted-state/-/use-persisted-state-0.3.0.tgz",
|
||||
"integrity": "sha512-UlWEq0JYg7NbvcRBZ1g6Bwe4SEbYfr1wr/D5mrmfCzSxXSwsPRYygGLlsxHcW58Rf7gGwRPBT23sNVvyVn4WYg==",
|
||||
"requires": {
|
||||
"@use-it/event-listener": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"utif": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz",
|
||||
@ -25376,16 +25402,6 @@
|
||||
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
|
||||
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
|
||||
},
|
||||
"why-did-you-update": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/why-did-you-update/-/why-did-you-update-1.0.6.tgz",
|
||||
"integrity": "sha512-XVrdHhdrPBDuSW8b/uH6DCb1/0984qv8KElpE8NZiRvWZX8nw49av577+ZyIrxSNesi6r2cQEhpxQTKFFHTj8A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.11",
|
||||
"react-fast-compare": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
|
@ -36,6 +36,7 @@
|
||||
"gatsby-plugin-sharp": "^2.3.4",
|
||||
"gatsby-plugin-sitemap": "^2.2.22",
|
||||
"gatsby-plugin-svgr": "^2.0.2",
|
||||
"gatsby-plugin-use-dark-mode": "^1.1.2",
|
||||
"gatsby-plugin-webpack-size": "^1.0.0",
|
||||
"gatsby-source-filesystem": "^2.1.39",
|
||||
"gatsby-transformer-json": "^2.2.20",
|
||||
@ -55,7 +56,7 @@
|
||||
"remark-parse": "^7.0.2",
|
||||
"remark-react": "^6.0.0",
|
||||
"shortid": "^2.2.15",
|
||||
"suncalc": "^1.8.0",
|
||||
"use-dark-mode": "^2.3.1",
|
||||
"vcf": "^2.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -92,8 +93,7 @@
|
||||
"slugify": "^1.3.6",
|
||||
"stylelint": "^12.0.0",
|
||||
"stylelint-config-css-modules": "^2.1.0",
|
||||
"stylelint-config-standard": "^19.0.0",
|
||||
"why-did-you-update": "^1.0.6"
|
||||
"stylelint-config-standard": "^19.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
|
@ -11,11 +11,11 @@ import styles from './Layout.module.scss'
|
||||
import { useMeta } from '../hooks/use-meta'
|
||||
|
||||
// https://github.com/welldone-software/why-did-you-render
|
||||
// if (process.env.NODE_ENV !== 'production') {
|
||||
// // eslint-disable-next-line
|
||||
// const whyDidYouRender = require('@welldone-software/why-did-you-render/dist/no-classes-transpile/umd/whyDidYouRender.min.js')
|
||||
// whyDidYouRender(React)
|
||||
// }
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line
|
||||
const whyDidYouRender = require('@welldone-software/why-did-you-render/dist/no-classes-transpile/umd/whyDidYouRender.min.js')
|
||||
whyDidYouRender(React)
|
||||
}
|
||||
|
||||
Layout.propTypes = {
|
||||
children: PropTypes.any.isRequired,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { memo } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
// https://featherstyles.com
|
||||
@ -27,7 +27,7 @@ import {
|
||||
import { ReactComponent as Dribbble } from '../../images/dribbble.svg'
|
||||
import styles from './Icon.module.scss'
|
||||
|
||||
const Icon = ({ name, ...props }) => {
|
||||
const Icon = memo(({ name, ...props }) => {
|
||||
const components = {
|
||||
Dribbble,
|
||||
Email: Mail,
|
||||
@ -63,7 +63,9 @@ const Icon = ({ name, ...props }) => {
|
||||
if (!IconMapped) return null
|
||||
|
||||
return <IconMapped className={styles.icon} {...props} />
|
||||
}
|
||||
})
|
||||
|
||||
Icon.displayName = 'Icon'
|
||||
|
||||
Icon.propTypes = {
|
||||
name: PropTypes.string.isRequired
|
||||
|
@ -1,23 +1,25 @@
|
||||
import React, { memo, useEffect, useState } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Helmet from 'react-helmet'
|
||||
import useDarkMode from '../../hooks/use-dark-mode'
|
||||
import useDarkMode from 'use-dark-mode'
|
||||
import Icon from '../atoms/Icon'
|
||||
import styles from './ThemeSwitch.module.scss'
|
||||
|
||||
const ThemeToggle = ({ dark }) => (
|
||||
const ThemeToggle = memo(({ dark }) => (
|
||||
<span id="toggle" className={styles.checkboxContainer} aria-live="assertive">
|
||||
<Icon name="Sun" className={!dark ? null : 'active'} />
|
||||
<span className={styles.checkboxFake} />
|
||||
<Icon name="Moon" className={dark ? 'active' : null} />
|
||||
</span>
|
||||
)
|
||||
))
|
||||
|
||||
ThemeToggle.displayName = 'ThemeToggle'
|
||||
|
||||
ThemeToggle.propTypes = {
|
||||
dark: PropTypes.bool.isRequired
|
||||
}
|
||||
|
||||
const ThemeToggleInput = ({ dark, toggleDark }) => (
|
||||
const ThemeToggleInput = memo(({ dark, toggleDark }) => (
|
||||
<input
|
||||
onChange={() => toggleDark()}
|
||||
type="checkbox"
|
||||
@ -26,36 +28,52 @@ const ThemeToggleInput = ({ dark, toggleDark }) => (
|
||||
aria-describedby="toggle"
|
||||
checked={dark}
|
||||
/>
|
||||
)
|
||||
))
|
||||
|
||||
ThemeToggleInput.displayName = 'ThemeToggleInput'
|
||||
|
||||
ThemeToggleInput.propTypes = {
|
||||
dark: PropTypes.bool.isRequired,
|
||||
toggleDark: PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
const HeadItems = ({ bodyClass, themeColor }) => (
|
||||
<Helmet>
|
||||
<body className={bodyClass} />
|
||||
<meta name="theme-color" content={themeColor} />
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
</Helmet>
|
||||
)
|
||||
|
||||
HeadItems.propTypes = {
|
||||
bodyClass: PropTypes.string.isRequired,
|
||||
themeColor: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
function ThemeSwitch() {
|
||||
const { darkMode, toggleDark } = useDarkMode()
|
||||
const { value, toggle } = useDarkMode(false, {
|
||||
classNameDark: 'dark',
|
||||
classNameLight: 'light'
|
||||
})
|
||||
const [themeColor, setThemeColor] = useState()
|
||||
const [bodyClass, setBodyClass] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
darkMode ? setThemeColor('#1d2224') : setThemeColor('#e7eef4')
|
||||
}, [darkMode])
|
||||
setBodyClass(value ? 'dark' : null)
|
||||
setThemeColor(value ? '#1d2224' : '#e7eef4')
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<body className={darkMode ? 'dark' : null} />
|
||||
<meta name="theme-color" content={themeColor} />
|
||||
<meta
|
||||
name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent"
|
||||
/>
|
||||
</Helmet>
|
||||
<HeadItems themeColor={themeColor} bodyClass={bodyClass} />
|
||||
<aside className={styles.themeSwitch}>
|
||||
<label className={styles.checkbox}>
|
||||
<span className={styles.label}>Toggle Night Mode</span>
|
||||
<ThemeToggleInput dark={darkMode} toggleDark={toggleDark} />
|
||||
<ThemeToggle dark={darkMode} />
|
||||
<ThemeToggleInput dark={value} toggleDark={toggle} />
|
||||
<ThemeToggle dark={value} />
|
||||
</label>
|
||||
</aside>
|
||||
</>
|
||||
|
@ -1,32 +0,0 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { getLocationTimes } from '../utils/getLocationTimes'
|
||||
import { getCountry } from '../utils/getCountry'
|
||||
|
||||
export default function useDarkMode() {
|
||||
const store = typeof localStorage === 'undefined' ? null : localStorage
|
||||
const darkLocalStorage = store && store.getItem('darkMode')
|
||||
const [darkMode, setDarkMode] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
darkLocalStorage
|
||||
? darkLocalStorage === 'true'
|
||||
? setDarkMode(true)
|
||||
: setDarkMode(false)
|
||||
: checkTimes()
|
||||
|
||||
async function checkTimes() {
|
||||
const geolocation = await getCountry()
|
||||
const { sunset, sunrise } = getLocationTimes(geolocation)
|
||||
const now = new Date().getHours()
|
||||
const weWantItDarkTimes = now >= sunset || now <= sunrise
|
||||
weWantItDarkTimes && setDarkMode(true)
|
||||
}
|
||||
}, [darkLocalStorage, darkMode])
|
||||
|
||||
function toggleDark() {
|
||||
setDarkMode(!darkMode)
|
||||
store && store.setItem('darkMode', !darkMode)
|
||||
}
|
||||
|
||||
return { darkMode, toggleDark }
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
{
|
||||
"ad": ["42.5000", "1.5000"],
|
||||
"ae": ["24.0000", "54.0000"],
|
||||
"af": ["33.0000", "65.0000"],
|
||||
"ag": ["17.0500", "-61.8000"],
|
||||
"ai": ["18.2500", "-63.1667"],
|
||||
"al": ["41.0000", "20.0000"],
|
||||
"am": ["40.0000", "45.0000"],
|
||||
"an": ["12.2500", "-68.7500"],
|
||||
"ao": ["-12.5000", "18.5000"],
|
||||
"ap": ["35.0000", "105.0000"],
|
||||
"aq": ["-90.0000", "0.0000"],
|
||||
"ar": ["-34.0000", "-64.0000"],
|
||||
"as": ["-14.3333", "-170.0000"],
|
||||
"at": ["47.3333", "13.3333"],
|
||||
"au": ["-27.0000", "133.0000"],
|
||||
"aw": ["12.5000", "-69.9667"],
|
||||
"az": ["40.5000", "47.5000"],
|
||||
"ba": ["44.0000", "18.0000"],
|
||||
"bb": ["13.1667", "-59.5333"],
|
||||
"bd": ["24.0000", "90.0000"],
|
||||
"be": ["50.8333", "4.0000"],
|
||||
"bf": ["13.0000", "-2.0000"],
|
||||
"bg": ["43.0000", "25.0000"],
|
||||
"bh": ["26.0000", "50.5500"],
|
||||
"bi": ["-3.5000", "30.0000"],
|
||||
"bj": ["9.5000", "2.2500"],
|
||||
"bm": ["32.3333", "-64.7500"],
|
||||
"bn": ["4.5000", "114.6667"],
|
||||
"bo": ["-17.0000", "-65.0000"],
|
||||
"br": ["-10.0000", "-55.0000"],
|
||||
"bs": ["24.2500", "-76.0000"],
|
||||
"bt": ["27.5000", "90.5000"],
|
||||
"bv": ["-54.4333", "3.4000"],
|
||||
"bw": ["-22.0000", "24.0000"],
|
||||
"by": ["53.0000", "28.0000"],
|
||||
"bz": ["17.2500", "-88.7500"],
|
||||
"ca": ["60.0000", "-95.0000"],
|
||||
"cc": ["-12.5000", "96.8333"],
|
||||
"cd": ["0.0000", "25.0000"],
|
||||
"cf": ["7.0000", "21.0000"],
|
||||
"cg": ["-1.0000", "15.0000"],
|
||||
"ch": ["47.0000", "8.0000"],
|
||||
"ci": ["8.0000", "-5.0000"],
|
||||
"ck": ["-21.2333", "-159.7667"],
|
||||
"cl": ["-30.0000", "-71.0000"],
|
||||
"cm": ["6.0000", "12.0000"],
|
||||
"cn": ["35.0000", "105.0000"],
|
||||
"co": ["4.0000", "-72.0000"],
|
||||
"cr": ["10.0000", "-84.0000"],
|
||||
"cu": ["21.5000", "-80.0000"],
|
||||
"cv": ["16.0000", "-24.0000"],
|
||||
"cx": ["-10.5000", "105.6667"],
|
||||
"cy": ["35.0000", "33.0000"],
|
||||
"cz": ["49.7500", "15.5000"],
|
||||
"de": ["51.0000", "9.0000"],
|
||||
"dj": ["11.5000", "43.0000"],
|
||||
"dk": ["56.0000", "10.0000"],
|
||||
"dm": ["15.4167", "-61.3333"],
|
||||
"do": ["19.0000", "-70.6667"],
|
||||
"dz": ["28.0000", "3.0000"],
|
||||
"ec": ["-2.0000", "-77.5000"],
|
||||
"ee": ["59.0000", "26.0000"],
|
||||
"eg": ["27.0000", "30.0000"],
|
||||
"eh": ["24.5000", "-13.0000"],
|
||||
"er": ["15.0000", "39.0000"],
|
||||
"es": ["40.0000", "-4.0000"],
|
||||
"et": ["8.0000", "38.0000"],
|
||||
"eu": ["47.0000", "8.0000"],
|
||||
"fi": ["64.0000", "26.0000"],
|
||||
"fj": ["-18.0000", "175.0000"],
|
||||
"fk": ["-51.7500", "-59.0000"],
|
||||
"fm": ["6.9167", "158.2500"],
|
||||
"fo": ["62.0000", "-7.0000"],
|
||||
"fr": ["46.0000", "2.0000"],
|
||||
"ga": ["-1.0000", "11.7500"],
|
||||
"gb": ["54.0000", "-2.0000"],
|
||||
"gd": ["12.1167", "-61.6667"],
|
||||
"ge": ["42.0000", "43.5000"],
|
||||
"gf": ["4.0000", "-53.0000"],
|
||||
"gh": ["8.0000", "-2.0000"],
|
||||
"gi": ["36.1833", "-5.3667"],
|
||||
"gl": ["72.0000", "-40.0000"],
|
||||
"gm": ["13.4667", "-16.5667"],
|
||||
"gn": ["11.0000", "-10.0000"],
|
||||
"gp": ["16.2500", "-61.5833"],
|
||||
"gq": ["2.0000", "10.0000"],
|
||||
"gr": ["39.0000", "22.0000"],
|
||||
"gs": ["-54.5000", "-37.0000"],
|
||||
"gt": ["15.5000", "-90.2500"],
|
||||
"gu": ["13.4667", "144.7833"],
|
||||
"gw": ["12.0000", "-15.0000"],
|
||||
"gy": ["5.0000", "-59.0000"],
|
||||
"hk": ["22.2500", "114.1667"],
|
||||
"hm": ["-53.1000", "72.5167"],
|
||||
"hn": ["15.0000", "-86.5000"],
|
||||
"hr": ["45.1667", "15.5000"],
|
||||
"ht": ["19.0000", "-72.4167"],
|
||||
"hu": ["47.0000", "20.0000"],
|
||||
"id": ["-5.0000", "120.0000"],
|
||||
"ie": ["53.0000", "-8.0000"],
|
||||
"il": ["31.5000", "34.7500"],
|
||||
"in": ["20.0000", "77.0000"],
|
||||
"io": ["-6.0000", "71.5000"],
|
||||
"iq": ["33.0000", "44.0000"],
|
||||
"ir": ["32.0000", "53.0000"],
|
||||
"is": ["65.0000", "-18.0000"],
|
||||
"it": ["42.8333", "12.8333"],
|
||||
"jm": ["18.2500", "-77.5000"],
|
||||
"jo": ["31.0000", "36.0000"],
|
||||
"jp": ["36.0000", "138.0000"],
|
||||
"ke": ["1.0000", "38.0000"],
|
||||
"kg": ["41.0000", "75.0000"],
|
||||
"kh": ["13.0000", "105.0000"],
|
||||
"ki": ["1.4167", "173.0000"],
|
||||
"km": ["-12.1667", "44.2500"],
|
||||
"kn": ["17.3333", "-62.7500"],
|
||||
"kp": ["40.0000", "127.0000"],
|
||||
"kr": ["37.0000", "127.5000"],
|
||||
"kw": ["29.3375", "47.6581"],
|
||||
"ky": ["19.5000", "-80.5000"],
|
||||
"kz": ["48.0000", "68.0000"],
|
||||
"la": ["18.0000", "105.0000"],
|
||||
"lb": ["33.8333", "35.8333"],
|
||||
"lc": ["13.8833", "-61.1333"],
|
||||
"li": ["47.1667", "9.5333"],
|
||||
"lk": ["7.0000", "81.0000"],
|
||||
"lr": ["6.5000", "-9.5000"],
|
||||
"ls": ["-29.5000", "28.5000"],
|
||||
"lt": ["56.0000", "24.0000"],
|
||||
"lu": ["49.7500", "6.1667"],
|
||||
"lv": ["57.0000", "25.0000"],
|
||||
"ly": ["25.0000", "17.0000"],
|
||||
"ma": ["32.0000", "-5.0000"],
|
||||
"mc": ["43.7333", "7.4000"],
|
||||
"md": ["47.0000", "29.0000"],
|
||||
"me": ["42.0000", "19.0000"],
|
||||
"mg": ["-20.0000", "47.0000"],
|
||||
"mh": ["9.0000", "168.0000"],
|
||||
"mk": ["41.8333", "22.0000"],
|
||||
"ml": ["17.0000", "-4.0000"],
|
||||
"mm": ["22.0000", "98.0000"],
|
||||
"mn": ["46.0000", "105.0000"],
|
||||
"mo": ["22.1667", "113.5500"],
|
||||
"mp": ["15.2000", "145.7500"],
|
||||
"mq": ["14.6667", "-61.0000"],
|
||||
"mr": ["20.0000", "-12.0000"],
|
||||
"ms": ["16.7500", "-62.2000"],
|
||||
"mt": ["35.8333", "14.5833"],
|
||||
"mu": ["-20.2833", "57.5500"],
|
||||
"mv": ["3.2500", "73.0000"],
|
||||
"mw": ["-13.5000", "34.0000"],
|
||||
"mx": ["23.0000", "-102.0000"],
|
||||
"my": ["2.5000", "112.5000"],
|
||||
"mz": ["-18.2500", "35.0000"],
|
||||
"na": ["-22.0000", "17.0000"],
|
||||
"nc": ["-21.5000", "165.5000"],
|
||||
"ne": ["16.0000", "8.0000"],
|
||||
"nf": ["-29.0333", "167.9500"],
|
||||
"ng": ["10.0000", "8.0000"],
|
||||
"ni": ["13.0000", "-85.0000"],
|
||||
"nl": ["52.5000", "5.7500"],
|
||||
"no": ["62.0000", "10.0000"],
|
||||
"np": ["28.0000", "84.0000"],
|
||||
"nr": ["-0.5333", "166.9167"],
|
||||
"nu": ["-19.0333", "-169.8667"],
|
||||
"nz": ["-41.0000", "174.0000"],
|
||||
"om": ["21.0000", "57.0000"],
|
||||
"pa": ["9.0000", "-80.0000"],
|
||||
"pe": ["-10.0000", "-76.0000"],
|
||||
"pf": ["-15.0000", "-140.0000"],
|
||||
"pg": ["-6.0000", "147.0000"],
|
||||
"ph": ["13.0000", "122.0000"],
|
||||
"pk": ["30.0000", "70.0000"],
|
||||
"pl": ["52.0000", "20.0000"],
|
||||
"pm": ["46.8333", "-56.3333"],
|
||||
"pr": ["18.2500", "-66.5000"],
|
||||
"ps": ["32.0000", "35.2500"],
|
||||
"pt": ["39.5000", "-8.0000"],
|
||||
"pw": ["7.5000", "134.5000"],
|
||||
"py": ["-23.0000", "-58.0000"],
|
||||
"qa": ["25.5000", "51.2500"],
|
||||
"re": ["-21.1000", "55.6000"],
|
||||
"ro": ["46.0000", "25.0000"],
|
||||
"rs": ["44.0000", "21.0000"],
|
||||
"ru": ["60.0000", "100.0000"],
|
||||
"rw": ["-2.0000", "30.0000"],
|
||||
"sa": ["25.0000", "45.0000"],
|
||||
"sb": ["-8.0000", "159.0000"],
|
||||
"sc": ["-4.5833", "55.6667"],
|
||||
"sd": ["15.0000", "30.0000"],
|
||||
"se": ["62.0000", "15.0000"],
|
||||
"sg": ["1.3667", "103.8000"],
|
||||
"sh": ["-15.9333", "-5.7000"],
|
||||
"si": ["46.0000", "15.0000"],
|
||||
"sj": ["78.0000", "20.0000"],
|
||||
"sk": ["48.6667", "19.5000"],
|
||||
"sl": ["8.5000", "-11.5000"],
|
||||
"sm": ["43.7667", "12.4167"],
|
||||
"sn": ["14.0000", "-14.0000"],
|
||||
"so": ["10.0000", "49.0000"],
|
||||
"sr": ["4.0000", "-56.0000"],
|
||||
"st": ["1.0000", "7.0000"],
|
||||
"sv": ["13.8333", "-88.9167"],
|
||||
"sy": ["35.0000", "38.0000"],
|
||||
"sz": ["-26.5000", "31.5000"],
|
||||
"tc": ["21.7500", "-71.5833"],
|
||||
"td": ["15.0000", "19.0000"],
|
||||
"tf": ["-43.0000", "67.0000"],
|
||||
"tg": ["8.0000", "1.1667"],
|
||||
"th": ["15.0000", "100.0000"],
|
||||
"tj": ["39.0000", "71.0000"],
|
||||
"tk": ["-9.0000", "-172.0000"],
|
||||
"tm": ["40.0000", "60.0000"],
|
||||
"tn": ["34.0000", "9.0000"],
|
||||
"to": ["-20.0000", "-175.0000"],
|
||||
"tr": ["39.0000", "35.0000"],
|
||||
"tt": ["11.0000", "-61.0000"],
|
||||
"tv": ["-8.0000", "178.0000"],
|
||||
"tw": ["23.5000", "121.0000"],
|
||||
"tz": ["-6.0000", "35.0000"],
|
||||
"ua": ["49.0000", "32.0000"],
|
||||
"ug": ["1.0000", "32.0000"],
|
||||
"um": ["19.2833", "166.6000"],
|
||||
"us": ["38.0000", "-97.0000"],
|
||||
"uy": ["-33.0000", "-56.0000"],
|
||||
"uz": ["41.0000", "64.0000"],
|
||||
"va": ["41.9000", "12.4500"],
|
||||
"vc": ["13.2500", "-61.2000"],
|
||||
"ve": ["8.0000", "-66.0000"],
|
||||
"vg": ["18.5000", "-64.5000"],
|
||||
"vi": ["18.3333", "-64.8333"],
|
||||
"vn": ["16.0000", "106.0000"],
|
||||
"vu": ["-16.0000", "167.0000"],
|
||||
"wf": ["-13.3000", "-176.2000"],
|
||||
"ws": ["-13.5833", "-172.3333"],
|
||||
"ye": ["15.0000", "48.0000"],
|
||||
"yt": ["-12.8333", "45.1667"],
|
||||
"za": ["-29.0000", "24.0000"],
|
||||
"zm": ["-15.0000", "30.0000"],
|
||||
"zw": ["-20.0000", "30.0000"]
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
//
|
||||
// Get user location from Cloudflare's geo location HTTP header
|
||||
//
|
||||
// @returns country: string
|
||||
//
|
||||
export const getCountry = async () => {
|
||||
try {
|
||||
const data = await fetch('/cdn-cgi/trace?no-cache=1')
|
||||
const text = await data.text().replace(/ /g, '')
|
||||
const lines = text.split('\n')
|
||||
|
||||
let keyValue
|
||||
let trace = []
|
||||
|
||||
await lines.forEach(line => {
|
||||
keyValue = line.split('=')
|
||||
trace[keyValue[0]] = decodeURIComponent(keyValue[1] || '')
|
||||
})
|
||||
|
||||
const country = trace['loc']
|
||||
|
||||
if (country && country !== 'XX') {
|
||||
return country
|
||||
}
|
||||
} catch (error) {
|
||||
return null // fail silently
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import { getCountry } from './getCountry'
|
||||
|
||||
const mockFetch = data =>
|
||||
jest.fn().mockImplementationOnce(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
Id: '123',
|
||||
text: () => data
|
||||
// json: () => data
|
||||
})
|
||||
)
|
||||
|
||||
describe('getCountry', () => {
|
||||
it('fetches and returns correct value', async () => {
|
||||
global.fetch = mockFetch('loc=DE')
|
||||
const country = await getCountry()
|
||||
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1)
|
||||
expect(global.fetch).toHaveBeenCalledWith('/cdn-cgi/trace?no-cache=1')
|
||||
expect(country).toBe('DE')
|
||||
})
|
||||
|
||||
it('returns nothing when XX country', async () => {
|
||||
global.fetch = mockFetch('loc=XX')
|
||||
const country = await getCountry()
|
||||
|
||||
expect(global.fetch).toHaveBeenCalledTimes(1)
|
||||
expect(global.fetch).toHaveBeenCalledWith('/cdn-cgi/trace?no-cache=1')
|
||||
expect(country).toBe(undefined)
|
||||
})
|
||||
})
|
@ -1,25 +0,0 @@
|
||||
import SunCalc from 'suncalc'
|
||||
import countrycodes from './countrycode-latlong.json'
|
||||
|
||||
//
|
||||
// All the checks to see if we should go dark or light
|
||||
//
|
||||
export const getLocationTimes = location => {
|
||||
// fallback times, in hours
|
||||
let sunrise = 7
|
||||
let sunset = 19
|
||||
|
||||
// times based on detected country code
|
||||
if (location && location !== 'XX' && location !== 'T1') {
|
||||
const country = location.toLowerCase()
|
||||
const times = SunCalc.getTimes(
|
||||
new Date(),
|
||||
countrycodes[country][0],
|
||||
countrycodes[country][1]
|
||||
)
|
||||
sunrise = times.sunrise.getHours()
|
||||
sunset = times.sunset.getHours()
|
||||
}
|
||||
|
||||
return { sunrise, sunset }
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
import { getLocationTimes } from './getLocationTimes'
|
||||
|
||||
describe('getLocationTimes', () => {
|
||||
it('returns values', async () => {
|
||||
const { sunset, sunrise } = await getLocationTimes('DE')
|
||||
expect(sunset).toBeDefined()
|
||||
expect(sunrise).toBeDefined()
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user