diff --git a/src/App.jsx b/src/App.jsx index 517c2a09..8a0b3c1e 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -2,7 +2,6 @@ import React from 'react'; import Background from './components/widgets/background/Background'; import Widgets from './components/widgets/Widgets'; -import PhotoInformation from './components/widgets/background/PhotoInformation'; import Navbar from './components/widgets/navbar/Navbar'; import SettingsFunctions from './modules/helpers/settings'; @@ -23,7 +22,9 @@ export default class App extends React.PureComponent { mainModal: false, updateModal: false, welcomeModal: false, - feedbackModal: false + feedbackModal: false, + toastDisplayTime: localStorage.getItem('toastDisplayTime') || 2500, + overlayClassList: (localStorage.getItem('animations') === 'true') ? 'Overlay modal-animation' : 'Overlay' }; } @@ -40,6 +41,20 @@ export default class App extends React.PureComponent { SettingsFunctions.loadSettings(); + // dark theme support for modals and info card + let modalClassList = 'Modal'; + let tooltipClassList = 'infoCard'; + + if ((localStorage.getItem('brightnessTime') && new Date().getHours() > 18) || localStorage.getItem('darkTheme') === 'true') { + modalClassList += ' dark'; + tooltipClassList += ' dark'; + } + + this.setState({ + modalClassList: modalClassList, + tooltipClassList: tooltipClassList + }); + // These lines of code prevent double clicking the page or pressing CTRL + A from highlighting the page document.addEventListener('mousedown', (event) => { if (event.detail > 1) { @@ -69,34 +84,21 @@ export default class App extends React.PureComponent { } render() { - // dark theme support for modals and info card - let modalClassList = 'Modal'; - let tooltipClassList = 'infoCard'; - - if ((localStorage.getItem('brightnessTime') && new Date().getHours() > 18) || localStorage.getItem('darkTheme') === 'true') { - modalClassList += ' dark'; - tooltipClassList += ' dark'; - } - - const overlayClassList = (localStorage.getItem('animations') === 'true') ? 'Overlay modal-animation' : 'Overlay'; - const toastDisplayTime = localStorage.getItem('toastDisplayTime') || 2500; - return ( - - + +
this.setState({ [modal]: true })}/> - - this.setState({ mainModal: false })} isOpen={this.state.mainModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> + this.setState({ mainModal: false })} isOpen={this.state.mainModal} className={this.state.modalClassList} overlayClassName={this.state.overlayClassList} ariaHideApp={false}>
this.setState({ mainModal: false })} /> - this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> + this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={this.state.modalClassList} overlayClassName={this.state.overlayClassList} ariaHideApp={false}> this.setState({ updateModal: false })} /> - this.closeWelcome()} isOpen={this.state.welcomeModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> + this.closeWelcome()} isOpen={this.state.welcomeModal} className={this.state.modalClassList} overlayClassName={this.state.overlayClassList} ariaHideApp={false}> this.closeWelcome()} /> {/* this.setState({ feedbackModal: false })} isOpen={this.state.feedbackModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}> diff --git a/src/components/widgets/background/Background.jsx b/src/components/widgets/background/Background.jsx index 3b877dfc..cade42ba 100644 --- a/src/components/widgets/background/Background.jsx +++ b/src/components/widgets/background/Background.jsx @@ -1,10 +1,29 @@ import React from 'react'; +import PhotoInformation from './PhotoInformation'; + import * as Constants from '../../../modules/constants'; import './scss/index.scss'; export default class Background extends React.PureComponent { + constructor(...args) { + super(...args); + this.state = { + style: '', + url: '', + video: false, + photoInfo: { + hidden: false, + credit: '', + location: 'N/A', + camera: 'N/A', + resolution: 'N/A' + } + }; + this.language = window.language.widgets.background; + } + gradientStyleBuilder(gradientSettings) { const { type, angle, gradient } = gradientSettings; let style = `background: ${gradient[0].colour};`; @@ -13,55 +32,32 @@ export default class Background extends React.PureComponent { const stepStyles = gradient.map(g => ` ${g.colour} ${g.stop}%`).join(); style += ` background: ${type}-gradient(${(type === 'linear' ? (`${angle}deg,`) : '')}${stepStyles})`; } - return style; + this.setState({ + style: style + }); } - // Sets the attributes of the background image - setBackground(url, colour, credit) { - let gradientSettings = ''; - try { - gradientSettings = JSON.parse(colour); - } catch (e) { - const hexColorRegex = /#[0-9a-fA-F]{6}/s; - if (hexColorRegex.exec(colour)) { - // Colour use to be simply a hex colour or a NULL value before it was a JSON object. This automatically upgrades the hex colour value to the new standard. (NULL would not trigger an exception) - gradientSettings = { "type": "linear", "angle": "180", "gradient": [{ "colour": colour, "stop": 0 }] }; - localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings)); - } - } - - const background = typeof gradientSettings === 'object' && gradientSettings !== null ? this.gradientStyleBuilder(gradientSettings) : `background-image: url(${url})`; - + setBackground() { // Brightness let brightness = localStorage.getItem('brightness'); if (localStorage.getItem('brightnessTime') && new Date().getHours() > 18) { brightness = 75; } - document.querySelector('#backgroundImage').setAttribute( - 'style', - `${background}; -webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${brightness}%);` - ); - - // Hide the credit - if (credit === 'false' && document.querySelector('#credits')) { - document.querySelector('#credits').style.display = 'none'; + if (this.state.url !== '') { + document.querySelector('#backgroundImage').setAttribute( + 'style', + `background-image: url(${this.state.url}); -webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${brightness}%);` + ); + } else { + document.querySelector('#backgroundImage').setAttribute( + 'style', + `${this.state.style}; -webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${brightness}%);` + ); } } - setCredit(photographer, unsplash, url) { - let credit = photographer; - if (unsplash){ - credit = `${photographer} on Unsplash`; - } - - document.querySelector('#photographer').insertAdjacentHTML('beforeend', ` ${credit}`); // Append credit - document.getElementById('credit').textContent = credit; - document.getElementById('photographerCard').textContent = credit; - } - - // Handles setting the background if the user is offline - doOffline() { + offlineBackground() { const offlineImages = require('./offline_images.json'); // Get all photographers from the keys in offlineImages.json @@ -74,126 +70,139 @@ export default class Background extends React.PureComponent { Math.floor(Math.random() * offlineImages[photographer].photo.length) ]; - const url = `./offline-images/${randomImage}.jpg`; - - this.setBackground(url); - this.setCredit(photographer); - - // Hide the location icon - //document.querySelector('#backgroundCredits').style.display = 'none'; + this.setState({ + url: `./offline-images/${randomImage}.jpg`, + photoInfo: { + hidden: true, + credit: photographer + } + }); } - async determineMode() { - const offlineMode = localStorage.getItem('offlineMode'); - - const photoPack = JSON.parse(localStorage.getItem('photo_packs')); - - const customBackgroundColour = localStorage.getItem('customBackgroundColour'); - const customBackground = localStorage.getItem('customBackground'); + // Main background getting function + async getBackground() { + if (localStorage.getItem('offlineMode') === 'true') { + return this.offlineBackground(); + } + // favourite button const favourited = JSON.parse(localStorage.getItem('favourite')); - if (favourited) { - if (offlineMode === 'true') { - return this.doOffline(); - } + return this.setState({ + url: favourited.url, + photoInfo: { + credit: favourited.credit, + location: favourited.location + } + }); + } - this.setBackground(favourited.url, null, 'true'); - this.setCredit(favourited.credit); - document.getElementById('location').textContent = favourited.location; - } else if (photoPack) { - if (offlineMode === 'true') { - return this.doOffline(); - } - - const randomPhoto = photoPack[Math.floor(Math.random() * photoPack.length)]; - - this.setBackground(randomPhoto.url.default, null, randomPhoto.photographer); - this.setCredit(randomPhoto.photographer); - document.getElementById('location').textContent = randomPhoto.location; - } else if (customBackgroundColour !== 'Disabled' && customBackgroundColour !== '') { - this.setBackground(null, customBackgroundColour, 'false'); - } else if (customBackground !== '') { - if (customBackground.includes('.mp4') || customBackground.includes('.webm') || customBackground.includes('.ogg')) { - document.getElementById('backgroundImage').innerHTML = ` - `; - } else { - // Local - this.setBackground(customBackground, null, 'false'); - } - // Online - } else { - if (offlineMode === 'true') { - return this.doOffline(); - } - - // First we try and get an image from the API... + // background colour + const customBackgroundColour = localStorage.getItem('customBackgroundColour'); + if (customBackgroundColour !== 'Disabled' && customBackgroundColour !== '') { + let gradientSettings = ''; try { - let requestURL; - - switch (localStorage.getItem('backgroundAPI')) { - case 'unsplash': - requestURL = `${Constants.UNSPLASH_URL}/getImage`; - break; - // Defaults to Mue - default: - requestURL = `${Constants.API_URL}/getImage?category=Outdoors`; - break; - } - - // Fetch JSON data from requestURL - const data = await (await fetch(requestURL)).json(); - - // If we hit the rate limit, fallback to local images - if (data.statusCode === 429) { - this.doOffline(); - // Otherwise, set the background and credit from remote data - } else { - this.setBackground(data.file); - - if (localStorage.getItem('backgroundAPI') === 'unsplash') { - return this.setCredit(data.photographer, 'unsplash', data.photographer_page); - } - - this.setCredit(data.photographer); - document.getElementById('camera').textContent = data.camera || 'N/A'; - document.getElementById('resolution').textContent = data.resolution || 'N/A'; - } - - if (data.location.replace(/[null]+/g, '') === ' ') { - return document.querySelector('#backgroundCredits').style.display = 'none'; - } - - // Set the location tooltip - document.getElementById('location').innerText = `${data.location.replace('null', '')}`; - // ..and if that fails we load one locally + gradientSettings = JSON.parse(colour); } catch (e) { - this.doOffline(); + const hexColorRegex = /#[0-9a-fA-F]{6}/s; + if (hexColorRegex.exec(colour)) { + // Colour use to be simply a hex colour or a NULL value before it was a JSON object. This automatically upgrades the hex colour value to the new standard. (NULL would not trigger an exception) + gradientSettings = { "type": "linear", "angle": "180", "gradient": [{ "colour": colour, "stop": 0 }] }; + localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings)); + } + } + + if (typeof gradientSettings === 'object' && gradientSettings !== null) { + return this.gradientStyleBuilder(gradientSettings); } } + + // custom user background + const customBackground = localStorage.getItem('customBackground'); + if (customBackground !== '') { + // video background + if (customBackground.includes('.mp4') || customBackground.includes('.webm') || customBackground.includes('.ogg')) { + return this.setState({ + url: customBackground, + video: true, + photoInfo: { + hidden: true + } + }); + // normal background + } else { + return this.setState({ + url: customBackground, + photoInfo: { + hidden: true + } + }); + } + } + + // photo pack + const photoPack = JSON.parse(localStorage.getItem('photo_packs')); + if (photoPack) { + const randomPhoto = photoPack[Math.floor(Math.random() * photoPack.length)]; + return this.setState({ + url: randomPhoto.url.default, + photoInfo: { + credit: randomPhoto.photographer + } + }); + } + + // API background + const backgroundAPI = localStorage.getItem('backgroundAPI'); + + let requestURL, data; + switch (backgroundAPI) { + case 'unsplash': + requestURL = `${Constants.UNSPLASH_URL}/getImage`; + break; + // Defaults to Mue + default: + requestURL = `${Constants.API_URL}/getImage?category=Outdoors`; + break; + } + + try { + data = await (await fetch(requestURL)).json(); + } catch (e) { + // if requesting to the API fails, we get an offline image + return this.offlineBackground(); + } + + this.setState({ + url: data.file, + photoInfo: { + credit: (backgroundAPI !== 'unsplash') ? data.photographer : data.photographer + ' on Unsplash', + location: (data.location.replace(/[null]+/g, '') !== ' ') ? data.location : 'N/A', + camera: data.camera || 'N/A', + resolution: data.resolution || 'N/A' + } + }); } componentDidMount() { - // Hide the credit if (localStorage.getItem('background') === 'false') { - return document.querySelector('.photoInformation').style.display = 'none'; + return; } - const backgroundColour = localStorage.getItem('customBackgroundColour'); - if (backgroundColour !== 'Disabled' && backgroundColour !== '') { - document.querySelector('.photoInformation').style.display = 'none'; - } + this.getBackground(); + } - if (localStorage.getItem('animations') === 'true') { - document.querySelector('#backgroundImage').classList.add('fade-in'); - } - - this.determineMode(); + // only set once we've got the info + componentDidUpdate() { + this.setBackground(); } render() { - return
; + return ( + +
+ + + ); } } diff --git a/src/components/widgets/background/PhotoInformation.jsx b/src/components/widgets/background/PhotoInformation.jsx index 5601fd1d..6d99232d 100644 --- a/src/components/widgets/background/PhotoInformation.jsx +++ b/src/components/widgets/background/PhotoInformation.jsx @@ -1,4 +1,5 @@ import React from 'react'; + import Info from '@material-ui/icons/Info'; import Location from '@material-ui/icons/LocationOn'; import Camera from '@material-ui/icons/PhotoCamera'; @@ -10,22 +11,21 @@ export default function PhotoInformation(props) { return (
-

{language.credit}

+

{language.credit} {props.info.credit}

{language.information}


- + {props.info.location} - + {props.info.camera} - + {props.info.resolution} - + {props.info.credit.split(' on Unsplash')[0]}
-
); } diff --git a/src/components/widgets/background/scss/_photoinformation.scss b/src/components/widgets/background/scss/_photoinformation.scss index 341f2323..d1afb10c 100644 --- a/src/components/widgets/background/scss/_photoinformation.scss +++ b/src/components/widgets/background/scss/_photoinformation.scss @@ -4,6 +4,7 @@ left: 1rem; font-size: calc(10px + 0.1vmin) !important; text-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + z-index: 99; svg { float: left;