mirror of
https://github.com/mue/mue.git
synced 2026-07-09 13:35:35 +02:00
Massive Update
Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com> Co-authored-by: Wessel Tip <discord@go2it.eu> Co-authored-by: Isaac Saunders <contact@eartharoid.me>
This commit is contained in:
69
src/App.jsx
69
src/App.jsx
@@ -1,4 +1,3 @@
|
||||
//* Imports
|
||||
import React from 'react';
|
||||
import Background from './components/Background';
|
||||
import Clock from './components/Clock';
|
||||
@@ -7,50 +6,34 @@ import Quote from './components/Quote';
|
||||
import Search from './components/Search';
|
||||
import Credit from './components/Credit';
|
||||
import Navbar from './components/Navbar';
|
||||
import Toast from './components/Toast';
|
||||
import { ToastContainer } from 'react-toastify';
|
||||
import Modal from 'react-modal';
|
||||
import './scss/index.scss';
|
||||
|
||||
import './scss/index.scss';
|
||||
import 'react-toastify/dist/ReactToastify.css';
|
||||
|
||||
const defaultSettings = require('./modules/defaultSettings.json');
|
||||
const Settings = React.lazy(() => import('./components/Settings'));
|
||||
const Update = React.lazy(() => import('./components/Update'));
|
||||
const renderLoader = () => <div></div>;
|
||||
|
||||
//* App
|
||||
export default class App extends React.Component {
|
||||
// Modal stuff
|
||||
export default class App extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
settingsModal: false,
|
||||
this.state = {
|
||||
settingsModal: false,
|
||||
updateModal: false
|
||||
};
|
||||
}
|
||||
|
||||
setDefaultSettings() {
|
||||
localStorage.clear();
|
||||
|
||||
localStorage.setItem('time', true);
|
||||
localStorage.setItem('greeting', true);
|
||||
localStorage.setItem('background', true);
|
||||
localStorage.setItem('quote', true);
|
||||
localStorage.setItem('searchBar', true);
|
||||
localStorage.setItem('blur', 0);
|
||||
localStorage.setItem('copyButton', false);
|
||||
localStorage.setItem('seconds', false);
|
||||
localStorage.setItem('24hour', false);
|
||||
localStorage.setItem('offlineMode', false);
|
||||
localStorage.setItem('webp', false);
|
||||
localStorage.setItem('events', true);
|
||||
localStorage.setItem('customBackgroundColour', '');
|
||||
localStorage.setItem('customBackground', '');
|
||||
localStorage.setItem('greetingName', '');
|
||||
localStorage.setItem('defaultGreetingMessage', true);
|
||||
defaultSettings.forEach(element => localStorage.setItem(element.name, element.value));
|
||||
|
||||
// Set theme depending on user preferred
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true);
|
||||
else localStorage.setItem('darkTheme', false);
|
||||
localStorage.setItem('darkTheme', false);
|
||||
// if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true);
|
||||
//else localStorage.setItem('darkTheme', false);
|
||||
|
||||
// Finally we set this to true so it doesn't run the function on every load
|
||||
localStorage.setItem('firstRun', true);
|
||||
@@ -62,27 +45,31 @@ export default class App extends React.Component {
|
||||
if (!localStorage.getItem('firstRun')) this.setDefaultSettings();
|
||||
|
||||
let modalClassList = 'Modal';
|
||||
const darkTheme = localStorage.getItem('darkTheme');
|
||||
if (darkTheme === 'true') modalClassList = 'Modal dark';
|
||||
|
||||
if (localStorage.getItem('darkTheme') === 'true') modalClassList = 'Modal dark';
|
||||
|
||||
let overlayClassList = 'Overlay';
|
||||
if (localStorage.getItem('animations') === 'true') overlayClassList = 'Overlay modal-animation';
|
||||
|
||||
let language = require(`./translations/${localStorage.getItem('language')}.json`);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div id='backgroundImage'></div>
|
||||
<Background/>
|
||||
<ToastContainer className='toast' position='bottom-right' autoClose={2500} hideProgressBar={false} newestOnTop={true} closeOnClick rtl={false} pauseOnFocusLoss />
|
||||
<div id='center'>
|
||||
<Search/>
|
||||
<Search language={language.search} />
|
||||
<Navbar settingsModalOpen={() => this.setState({ settingsModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} />
|
||||
<Greeting/>
|
||||
<Clock/>
|
||||
<Quote />
|
||||
<Credit/>
|
||||
<Toast/>
|
||||
<Greeting language={language.greeting} />
|
||||
<Clock/>
|
||||
<Quote/>
|
||||
<Credit language={language.credit} />
|
||||
<React.Suspense fallback={renderLoader()}>
|
||||
<Modal isOpen={this.state.settingsModal} className={modalClassList} overlayClassName="Overlay" ariaHideApp={false}>
|
||||
<Settings modalClose={() => this.setState({ settingsModal: false })} setDefaultSettings={() => this.setDefaultSettings()} />
|
||||
<Modal id={'modal'} onRequestClose={() => this.setState({ settingsModal: false })} isOpen={this.state.settingsModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
||||
<Settings language={language.settings} modalClose={() => this.setState({ settingsModal: false })} setDefaultSettings={() => this.setDefaultSettings()} />
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.updateModal} className={modalClassList} overlayClassName="Overlay" ariaHideApp={false}>
|
||||
<Update modalClose={() => this.setState({ updateModal: false })} />
|
||||
<Modal onRequestClose={() => this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
||||
<Update language={language.update} modalClose={() => this.setState({ updateModal: false })} />
|
||||
</Modal>
|
||||
</React.Suspense>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
//* Imports
|
||||
import React from 'react';
|
||||
import supportsWebP from 'supports-webp';
|
||||
import * as Constants from '../modules/constants';
|
||||
|
||||
export default class Background extends React.Component {
|
||||
export default class Background extends React.PureComponent {
|
||||
doOffline() {
|
||||
const photo = Math.floor(Math.random() * (20 - 1 + 1)) + 1; // There are 20 images in the offline-images folder
|
||||
const photo = Math.floor(Math.random() * (Constants.OFFLINE_IMAGES - 1 + 1)) + 1; // There are 20 images in the offline-images folder
|
||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
||||
|
||||
let photographer; // Photographer credit
|
||||
const pixabayNumbers = [2, 3, 9, 11, 13, 14, 15]; // As there are a lot of Pixabay photos, we shorten the code a bit here
|
||||
if (pixabayNumbers.includes(photo)) photographer = 'Pixabay';
|
||||
if ([2, 3, 9, 11, 13, 14, 15].includes(photo)) photographer = 'Pixabay'; // As there are a lot of Pixabay photos, we shorten the code a bit here
|
||||
else switch (photo) {
|
||||
case 1: photographer = 'Tirachard Kumtanom'; break;
|
||||
case 4: photographer = 'Sohail Na'; break;
|
||||
@@ -20,47 +19,62 @@ export default class Background extends React.Component {
|
||||
}
|
||||
|
||||
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(../offline-images/${photo}.jpeg)`); // Set background and blur etc
|
||||
document.getElementById('photographer').innerText = `Photo by ${photographer} (Pexels)`; // Set the credit
|
||||
let credit = document.getElementById('photographer');
|
||||
credit.innerText = `${credit.innerText} ${photographer} (Pexels)`; // Set the credit
|
||||
}
|
||||
|
||||
async setBackground() {
|
||||
const enabled = localStorage.getItem('offlineMode');
|
||||
if (enabled === 'true') return this.doOffline();
|
||||
if (localStorage.getItem('offlineMode')=== 'true') return this.doOffline();
|
||||
|
||||
const colour = localStorage.getItem('customBackgroundColour');
|
||||
if (colour) {
|
||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
||||
document.getElementById('photographer').style.display = 'none';
|
||||
return document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-color: ${colour}`); // Set background and blur etc
|
||||
}
|
||||
|
||||
const custom = localStorage.getItem('customBackground');
|
||||
if (custom) {
|
||||
if (custom !== '') {
|
||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
||||
document.getElementById('photographer').style.display = 'none';
|
||||
return document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${custom})`); // Set background and blur etc
|
||||
}
|
||||
} else {
|
||||
try { // First we try and get an image from the API...
|
||||
let requestURL;
|
||||
const enabled = localStorage.getItem('webp');
|
||||
const backgroundAPI = localStorage.getItem('backgroundAPI');
|
||||
let data;
|
||||
|
||||
try { // First we try and get an image from the API...
|
||||
let requestURL;
|
||||
const enabled = localStorage.getItem('webp');
|
||||
if (await supportsWebP && enabled === 'true') requestURL = 'https://api.muetab.xyz/getImage?webp=true';
|
||||
else requestURL = 'https://api.muetab.xyz/getImage?category=Outdoors';
|
||||
let data = await fetch(requestURL);
|
||||
data = await data.json();
|
||||
switch (backgroundAPI) {
|
||||
case 'mue':
|
||||
if (await supportsWebP && enabled === 'true') requestURL = Constants.API_URL + '/getImage?webp=true';
|
||||
else requestURL = Constants.API_URL + '/getImage?category=Outdoors';
|
||||
break;
|
||||
case 'unsplash':
|
||||
requestURL = 'https://unsplash.muetab.xyz/getImage';
|
||||
break;
|
||||
default:
|
||||
if (await supportsWebP && enabled === 'true') requestURL = Constants.API_URL +'/getImage?webp=true';
|
||||
else requestURL = Constants.API_URL + '/getImage?category=Outdoors';
|
||||
break;
|
||||
}
|
||||
|
||||
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${data.file})`); // Set background and blur etc
|
||||
document.getElementById('photographer').innerText = `Photo by ${data.photographer}`; // Set the credit
|
||||
document.getElementById('location').innerText = `${data.location}`; // Set the location tooltip
|
||||
} catch (e) { // ..and if that fails we load one locally
|
||||
this.doOffline();
|
||||
data = await fetch(requestURL);
|
||||
data = await data.json();
|
||||
|
||||
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${data.file})`); // Set background and blur etc
|
||||
let credit = document.getElementById('photographer');
|
||||
credit.innerText = `${credit.innerText} ${data.photographer}`; // Set the credit
|
||||
document.getElementById('location').innerText = `${data.location}`; // Set the location tooltip
|
||||
} catch (e) { // ..and if that fails we load one locally
|
||||
this.doOffline();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const enabled = localStorage.getItem('background');
|
||||
if (enabled === 'false') {
|
||||
document.getElementById('backgroundCredits').style.display = 'none';
|
||||
return;
|
||||
}
|
||||
if (localStorage.getItem('background') === 'false') return document.getElementById('backgroundCredits').style.display = 'none';
|
||||
if (localStorage.getItem('animations') === 'true') document.getElementById('backgroundImage').classList.add('fade-in');
|
||||
this.setBackground();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +1,61 @@
|
||||
import React from 'react';
|
||||
import Analog from 'react-clock';
|
||||
|
||||
export default class Clock extends React.Component {
|
||||
export default class Clock extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.timer = undefined;
|
||||
this.state = {
|
||||
date: '',
|
||||
time: '',
|
||||
ampm: ''
|
||||
};
|
||||
}
|
||||
|
||||
startTime(time = localStorage.getItem('seconds') === 'true' ? (1000 - Date.now() % 1000) : (60000 - Date.now() % 60000)) {
|
||||
startTime(time = localStorage.getItem('seconds') === 'true' || localStorage.getItem('analog') === 'true' ? (1000 - Date.now() % 1000) : (60000 - Date.now() % 60000)) {
|
||||
this.timer = setTimeout(() => {
|
||||
const now = new Date();
|
||||
let sec = '';
|
||||
|
||||
if (localStorage.getItem('seconds') === 'true') sec = `:${('00' + now.getSeconds()).slice(-2)}`;
|
||||
|
||||
if (localStorage.getItem('24hour') === 'true') {
|
||||
// Analog clock
|
||||
if (localStorage.getItem('analog') === 'true') {
|
||||
this.setState({
|
||||
date: `${('00' + now.getHours()).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`
|
||||
time: now
|
||||
});
|
||||
} else {
|
||||
// 12 hour support
|
||||
let hours = now.getHours();
|
||||
if (hours > 12) hours -= 12;
|
||||
let sec = '';
|
||||
|
||||
this.setState({
|
||||
date: `${('00' + hours).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`,
|
||||
ampm: now.getHours() > 11 ? 'PM' : 'AM'
|
||||
});
|
||||
// Extra 0
|
||||
const zero = localStorage.getItem('zero');
|
||||
|
||||
if (localStorage.getItem('seconds') === 'true') {
|
||||
if (zero === 'false') sec = `:${now.getSeconds()}`;
|
||||
else sec = `:${('00' + now.getSeconds()).slice(-2)}`;
|
||||
}
|
||||
|
||||
if (localStorage.getItem('24hour') === 'true') {
|
||||
let time = '';
|
||||
if (zero === 'false') time = `${now.getHours()}:${now.getMinutes()}${sec}`;
|
||||
else time = `${('00' + now.getHours()).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
|
||||
this.setState({
|
||||
time: time
|
||||
});
|
||||
} else {
|
||||
// 12 hour support
|
||||
let hours = now.getHours();
|
||||
if (hours > 12) hours -= 12;
|
||||
|
||||
// Toggle AM/PM
|
||||
let ampm = now.getHours() > 11 ? 'PM' : 'AM';
|
||||
if (localStorage.getItem('ampm') === 'false') ampm = '';
|
||||
|
||||
let time = '';
|
||||
if (zero === 'false') time = `${hours}:${now.getMinutes()}${sec}`;
|
||||
else time = `${('00' + hours).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
|
||||
this.setState({
|
||||
time: time,
|
||||
ampm: ampm
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.startTime();
|
||||
@@ -38,17 +63,13 @@ export default class Clock extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const enabled = localStorage.getItem('time');
|
||||
if (enabled === 'false') return;
|
||||
if (localStorage.getItem('time') === 'false') return;
|
||||
this.startTime(0);
|
||||
}
|
||||
|
||||
render() {
|
||||
return <h1 className='clock'>
|
||||
{this.state.date}
|
||||
<span className='ampm'>
|
||||
{this.state.ampm}
|
||||
</span>
|
||||
</h1>;
|
||||
let clockHTML = <h1 className='clock'>{this.state.time}<span className='ampm'>{this.state.ampm}</span> </h1>;
|
||||
if (localStorage.getItem('analog') === 'true') clockHTML = <Analog className='analogclock' value={this.state.time}/>;
|
||||
return clockHTML;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
/* eslint-disable */
|
||||
//* Imports
|
||||
/* eslint-disable jsx-a11y/heading-has-content */
|
||||
import RoomIcon from '@material-ui/icons/Room';
|
||||
import React from 'react';
|
||||
|
||||
export default class Credit extends React.Component {
|
||||
export default class Credit extends React.PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<div className='credits'>
|
||||
{/*<h1 id='location'></h1>*/}
|
||||
<h1 id='photographer'/>
|
||||
<h1 id='photographer'>{this.props.language}</h1>
|
||||
<div id='backgroundCredits' className='tooltip'>
|
||||
<RoomIcon className='locationicon'/>
|
||||
<span className='tooltiptext' id='location'/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class Greeting extends React.Component {
|
||||
export default class Greeting extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
@@ -9,8 +9,7 @@ export default class Greeting extends React.Component {
|
||||
}
|
||||
|
||||
doEvents(time, message) {
|
||||
const enabled = localStorage.getItem('events');
|
||||
if (enabled === 'false') return message;
|
||||
if (localStorage.getItem('events') === 'false') return message;
|
||||
|
||||
// Get current month & day
|
||||
const m = time.getMonth();
|
||||
@@ -27,9 +26,9 @@ export default class Greeting extends React.Component {
|
||||
const now = new Date();
|
||||
const hour = now.getHours();
|
||||
|
||||
let message = 'Good evening'; // Set the default greeting string to "Good evening"
|
||||
if (hour < 12) message = 'Good morning'; // If it's before 12am, set the greeting string to "Good morning"
|
||||
else if (hour < 18) message = 'Good afternoon'; // If it's before 6pm, set the greeting string to "Good afternoon"
|
||||
let message = this.props.language.evening; // Set the default greeting string to "Good evening"
|
||||
if (hour < 12) message = this.props.language.morning; // If it's before 12am, set the greeting string to "Good morning"
|
||||
else if (hour < 18) message = this.props.language.afternoon; // If it's before 6pm, set the greeting string to "Good afternoon"
|
||||
|
||||
// Events
|
||||
message = this.doEvents(now, message);
|
||||
@@ -53,8 +52,7 @@ export default class Greeting extends React.Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const enabled = localStorage.getItem('greeting');
|
||||
if (enabled === 'false') return;
|
||||
if (localStorage.getItem('greeting') === 'false') return;
|
||||
this.getGreeting();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
//* Imports
|
||||
import RefreshIcon from '@material-ui/icons/Refresh';
|
||||
import Gear from '@material-ui/icons/Settings';
|
||||
import NewReleases from '@material-ui/icons/NewReleases';
|
||||
import React from 'react';
|
||||
|
||||
export default class Navbar extends React.Component {
|
||||
export default class Navbar extends React.PureComponent {
|
||||
render() {
|
||||
let refreshHTML = <div className='navbar2'><RefreshIcon className='refreshicon' onClick={() => window.location.reload()} /></div>
|
||||
const refresh = localStorage.getItem('refresh');
|
||||
if (refresh === 'false') refreshHTML = '';
|
||||
|
||||
return (
|
||||
<div className='navbar-container'>
|
||||
<div className='navbar1'>
|
||||
<Gear className='settings-icon' onClick={this.props.settingsModalOpen} />
|
||||
</div>
|
||||
<div className='navbar2'>
|
||||
<RefreshIcon className='refreshicon' onClick={() => window.location.reload()} />
|
||||
</div>
|
||||
<div className='navbar3'>
|
||||
{refreshHTML}
|
||||
<div className={refresh === 'false' ? 'navbar2' : 'navbar3'}>
|
||||
<NewReleases className='refreshicon' onClick={this.props.updateModalOpen} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
//* Imports
|
||||
import React from 'react';
|
||||
import Quotes from '@muetab/quotes';
|
||||
import copy from 'copy-text-to-clipboard';
|
||||
import FileCopy from '@material-ui/icons/AttachFile';
|
||||
import FileCopy from '@material-ui/icons/FilterNone';
|
||||
import { toast } from 'react-toastify';
|
||||
import * as Constants from '../modules/constants';
|
||||
|
||||
export default class Quote extends React.Component {
|
||||
export default class Quote extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
@@ -22,11 +23,10 @@ export default class Quote extends React.Component {
|
||||
}
|
||||
|
||||
async getQuote() {
|
||||
const enabled = localStorage.getItem('offlineMode');
|
||||
if (enabled === 'true') return this.doOffline();
|
||||
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
||||
|
||||
try { // First we try and get a quote from the API...
|
||||
let data = await fetch('https://api.muetab.xyz/getQuote');
|
||||
let data = await fetch(Constants.API_URL +'/getQuote');
|
||||
data = await data.json();
|
||||
if (data.statusCode === 429) this.doOffline(); // If we hit the ratelimit, we fallback to local quotes
|
||||
this.setState({
|
||||
@@ -40,25 +40,23 @@ export default class Quote extends React.Component {
|
||||
|
||||
copyQuote() {
|
||||
copy(`${this.state.quote} - ${this.state.author}`);
|
||||
const toast = document.getElementById('toast');
|
||||
toast.className = 'show';
|
||||
setTimeout(() => { toast.className = toast.className.replace('show', ''); }, 3000);
|
||||
toast('Quote copied!');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const enabled = localStorage.getItem('quote');
|
||||
if (enabled === 'false') return;
|
||||
if (localStorage.getItem('quote') === 'false') return;
|
||||
this.getQuote();
|
||||
}
|
||||
|
||||
render() {
|
||||
let copy = <FileCopy className='copyButton' onClick={() => this.copyQuote() }></FileCopy>;
|
||||
const enabled = localStorage.getItem('copyButton');
|
||||
if (enabled === 'false') copy = '';
|
||||
if (localStorage.getItem('copyButton') === 'false') copy = '';
|
||||
|
||||
return [
|
||||
<h1 className='quote'>{`${this.state.quote}`}</h1>,
|
||||
<h1 className='quoteauthor'>{this.state.author} {copy}</h1>,
|
||||
];
|
||||
return (
|
||||
<div>
|
||||
<h1 className='quote'>{`${this.state.quote}`}</h1>
|
||||
<h1 className='quoteauthor'>{this.state.author} {copy}</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,23 @@
|
||||
//* Imports
|
||||
import React from 'react';
|
||||
|
||||
export default class Search extends React.Component {
|
||||
export default class Search extends React.PureComponent {
|
||||
render() {
|
||||
const enabled = localStorage.getItem('searchBar');
|
||||
if (enabled === 'false') return (<div></div>);
|
||||
if (localStorage.getItem('searchBar') === 'false') return <div></div>;
|
||||
|
||||
const searchEngine = localStorage.getItem('searchEngine');
|
||||
let url;
|
||||
|
||||
switch (searchEngine) {
|
||||
switch (localStorage.getItem('searchEngine')) {
|
||||
case 'duckduckgo': url = 'https://duckduckgo.com'; break;
|
||||
case 'google': url = 'https://google.com/search'; break;
|
||||
case 'bing': url = 'https://bing.com/search'; break;
|
||||
default: url = 'https://duckduckgo.com'; break;
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='searchBar' className='searchbar'>
|
||||
return <div id='searchBar' className='searchbar'>
|
||||
<form id='searchBar' className='searchbarform' action={url}>
|
||||
<input type='text' placeholder='Search' name='q' id='searchtext' className='searchtext'/>
|
||||
<input type='text' placeholder={this.props.language} name='q' id='searchtext' className='searchtext'/>
|
||||
<div className='blursearcbBG'/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,11 @@
|
||||
// eslint-disable
|
||||
import React from 'react';
|
||||
import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||
import * as SettingsFunctions from '../modules/settingsFunctions';
|
||||
import Checkbox from './settings/Checkbox';
|
||||
import Slider from './settings/Slider';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
export default class Settings extends React.Component {
|
||||
setItem(key, value) {
|
||||
let old = localStorage.getItem(key);
|
||||
let val = true;
|
||||
|
||||
if (old !== null && !value) {
|
||||
if (old === 'true') val = false;
|
||||
if (old === 'false') val = true;
|
||||
}
|
||||
|
||||
localStorage.setItem(key, val);
|
||||
//document.getElementById(`${key}Status`).innerHTML = val === true ? 'ON' : 'OFF';
|
||||
// console.log(`[DEBUG] setItem(${key}, ${old} -> ${val})`);
|
||||
}
|
||||
|
||||
toggleExtra(element, element2) {
|
||||
(element.style.display === 'none' || !element.style.display) ? element.style.display = 'block' : element.style.display = 'none';
|
||||
(element2.style.transform === 'rotate(-180deg)') ? element2.style.transform = 'rotate(0)' : element2.style.transform = 'rotate(-180deg)';
|
||||
}
|
||||
|
||||
saveStuff() {
|
||||
localStorage.setItem('blur', document.getElementById('blurRange').value); // this is better than inline onChange for performance
|
||||
localStorage.setItem('greetingName', document.getElementById('greetingName').value);
|
||||
localStorage.setItem('customBackground', document.getElementById('customBackground').value);
|
||||
//if (!document.getElementById('customBackgroundColour').enabled === 'false') localStorage.setItem('customBackgroundColour', document.getElementById('customBackgroundColour').value);
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
export default class Settings extends React.PureComponent {
|
||||
resetItem(key) {
|
||||
switch (key) {
|
||||
case 'greetingName': document.getElementById('greetingName').value = ''; break;
|
||||
@@ -43,26 +19,19 @@ export default class Settings extends React.Component {
|
||||
document.getElementById('blurRange').value = 0;
|
||||
document.getElementById('blurAmount').innerText = '0';
|
||||
break;
|
||||
case 'customSearchEngine': document.getElementById('searchEngine').value = 'DuckDuckGo'; break;
|
||||
default: console.log('[ERROR] resetItem requires a key!');
|
||||
}
|
||||
this.showToast();
|
||||
toast('Reset successfully!');
|
||||
}
|
||||
|
||||
showToast() {
|
||||
let toast = document.getElementById('toast');
|
||||
toast.innerText = 'Reset successfully!';
|
||||
toast.className = 'show';
|
||||
setTimeout(() => { toast.className = toast.className.replace('show', ''); }, 3000);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
updateCurrent() {
|
||||
document.getElementById('greetingName').value = localStorage.getItem('greetingName');
|
||||
document.getElementById('customBackground').value = localStorage.getItem('customBackground');
|
||||
/*const hex = localStorage.getItem('customBackgroundColour');
|
||||
if (!hex === '') {
|
||||
document.getElementById('customBackgroundColour').value = hex;
|
||||
document.getElementById('customBackgroundHex').innerText = hex;
|
||||
}*/
|
||||
document.getElementById('backgroundAPI').value = localStorage.getItem('backgroundAPI');
|
||||
document.getElementById('language').value = localStorage.getItem('language');
|
||||
document.getElementById('searchEngine').value = localStorage.getItem('searchEngine');
|
||||
// document.getElementById('backgroundImage').style.backgroundUrl = localStorage.getItem('customBackground');
|
||||
|
||||
for (const key of Object.keys(localStorage)) {
|
||||
let value = localStorage.getItem(key);
|
||||
@@ -80,152 +49,209 @@ export default class Settings extends React.Component {
|
||||
case 'false': value = false; break;
|
||||
default: value = true;
|
||||
}
|
||||
|
||||
tag.checked = value;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('keyup', (event) => {
|
||||
if (event.keyCode === 13) this.saveStuff();
|
||||
});
|
||||
|
||||
const darkTheme = localStorage.getItem('darkTheme');
|
||||
if (darkTheme === 'true') {
|
||||
if (localStorage.getItem('darkTheme') === 'true') {
|
||||
document.getElementById('blurRange').style.background = '#535c68';
|
||||
document.getElementById('customBackground').style.color = 'white';
|
||||
document.getElementById('backgroundAPI').style.color = 'white';
|
||||
document.getElementById('searchEngine').style.color = 'white';
|
||||
document.getElementById('language').style.color = 'white';
|
||||
/*[1, 2, 3, 4, 5].forEach((index) => {
|
||||
console.log(index)
|
||||
document.getElementsByClassName('choices')[index].style.background = 'black';
|
||||
})*/
|
||||
document.getElementById('greetingName').style.color = 'white';
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateCurrent();
|
||||
|
||||
document.getElementById('file-input').onchange = (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (file.type !== 'application/json') return console.error(`expected json, got ${file.type}`);
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
|
||||
reader.onload = (readerEvent) => {
|
||||
const content = JSON.parse(readerEvent.target.result);
|
||||
for (const key of Object.keys(content)) localStorage.setItem(key, content[key]);
|
||||
toast('Imported settings!');
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('bg-input').onchange = (e) => {
|
||||
const allowed = [ 'image/svg+xml', 'image/jpeg', 'image/png', 'image/webp', 'image/webm', 'image/gif' ];
|
||||
const reader = new FileReader();
|
||||
const file = e.target.files[0];
|
||||
|
||||
if (file.size > 2000000) return toast('File is over 2MB', '#ff0000', '#ffffff');
|
||||
if (!allowed.includes(file.type)) return console.error(`expected xml, svg, png or jpeg, got ${file.type}`);
|
||||
|
||||
reader.addEventListener('load', (e) => {
|
||||
localStorage.setItem('customBackground', e.target.result);
|
||||
document.getElementById('customBackground').src = e.target.result;
|
||||
document.getElementById('customBackground').value = e.target.result;
|
||||
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${localStorage.getItem('customBackground')}`);
|
||||
document.getElementById('backgroundImage').style.backgroundImage = `url(${localStorage.getItem('customBackground')})`
|
||||
});
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
/*const hex = localStorage.getItem('customBackgroundColour');
|
||||
if (!hex === '') {
|
||||
document.getElementById('customBackgroundColour').value = hex;
|
||||
document.getElementById('customBackgroundHex').innerText = hex;
|
||||
}*/
|
||||
|
||||
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
|
||||
document.getElementById('center').classList.toggle('backgroundEffects');
|
||||
|
||||
/* document.addEventListener('keyup', (event) => {
|
||||
if (event.keyCode === 13) this.saveStuff();
|
||||
if (event.keyCode === 27) {
|
||||
document.getElementById('root').classList.toggle('backgroundEffects');
|
||||
this.props.modalClose();
|
||||
}
|
||||
});*/
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
|
||||
document.getElementById('center').classList.toggle('backgroundEffects');
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="content">
|
||||
<span className="closeModal" onClick={this.props.modalClose}>×</span>
|
||||
<h1>Settings</h1>
|
||||
<p>Edit different components to make Mue your new tab.</p>
|
||||
// let expandClassList = '';
|
||||
//if (localStorage.getItem('animations') === 'true') expandClassList = 'all 0.5 ease 0s';
|
||||
|
||||
return <div className='content'>
|
||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||
<h1>{this.props.language.title}</h1>
|
||||
<p>{this.props.language.description}</p>
|
||||
<div className='columns'>
|
||||
<div className='group'>
|
||||
<div className='section'>
|
||||
<h4>Time</h4>
|
||||
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[0], document.getElementsByClassName('expandIcons')[0])} />
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={() => this.setItem('time')} id='timeStatus' />
|
||||
<span className="slider round"></span>
|
||||
</label>
|
||||
<li className="extraSettings">
|
||||
<ul>
|
||||
<input name="1" type="checkbox" onClick={() => this.setItem('seconds')} id='secondsStatus' />
|
||||
<label htmlFor="1">Seconds</label>
|
||||
</ul>
|
||||
<ul>
|
||||
<input name="2" type="checkbox" onClick={() => this.setItem('24hour')} id='24hourStatus' />
|
||||
<label htmlFor="2">24 Hour</label>
|
||||
</ul>
|
||||
<h4>{this.props.language.time.title}</h4>
|
||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[0], document.getElementsByClassName('expandIcons')[0])} />
|
||||
<Slider name='time' />
|
||||
<li className='extraSettings'>
|
||||
<Checkbox name='seconds' text={this.props.language.time.seconds} />
|
||||
<Checkbox name='24hour' text={this.props.language.time.twentyfourhour} />
|
||||
<Checkbox name='ampm' text={this.props.language.time.ampm} />
|
||||
<Checkbox name='zero' text={this.props.language.time.zero} />
|
||||
<Checkbox name='analog' text={this.props.language.time.analog} />
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ "lineHeight": "1px" }} className='section'>
|
||||
<h4>Greeting</h4>
|
||||
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[1], document.getElementsByClassName('expandIcons')[1])} />
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={()=> this.setItem('greeting')} id='greetingStatus' />
|
||||
<span className="slider round"></span>
|
||||
</label>
|
||||
<li className="extraSettings">
|
||||
<div className='section'>
|
||||
<h4>{this.props.language.greeting.title}</h4>
|
||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[1], document.getElementsByClassName('expandIcons')[1])} />
|
||||
<Slider name='greeting' />
|
||||
<li className='extraSettings'>
|
||||
<Checkbox name='events' text={this.props.language.greeting.events} />
|
||||
<Checkbox name='defaultGreetingMessage' text={this.props.language.greeting.default} />
|
||||
<ul>
|
||||
<input name="3" type="checkbox" onClick={() => this.setItem('events')} id='eventsStatus' />
|
||||
<label htmlFor="3">Events</label>
|
||||
</ul>
|
||||
<ul>
|
||||
<input name="6" type="checkbox" onClick={() => this.setItem('defaultGreetingMessage')} id='defaultGreetingMessageStatus' />
|
||||
<label htmlFor="6">Default Greeting Message</label>
|
||||
</ul>
|
||||
<ul>
|
||||
<p>Name for greeting <span className="modalLink" onClick={() => this.resetItem('greetingName')}>Reset</span></p>
|
||||
<p>{this.props.language.greeting.name} <span className='modalLink' onClick={() => this.resetItem('greetingName')}>Reset</span></p>
|
||||
<input type='text' id='greetingName'></input>
|
||||
</ul>
|
||||
</li>
|
||||
</div>
|
||||
<div className='section'>
|
||||
<h4>Quote</h4>
|
||||
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[2], document.getElementsByClassName('expandIcons')[2])} />
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={()=> this.setItem('quote')} id='quoteStatus' />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<li className="extraSettings">
|
||||
<ul>
|
||||
<input name="5" type="checkbox" onClick={() => this.setItem('copyButton')} id='copyButtonStatus' />
|
||||
<label htmlFor="5">Copy Button</label>
|
||||
</ul>
|
||||
<h4>{this.props.language.quote.title}</h4>
|
||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[2], document.getElementsByClassName('expandIcons')[2])} />
|
||||
<Slider name='quote' />
|
||||
<li className='extraSettings'>
|
||||
<Checkbox name='copyButton' text={this.props.language.quote.copy} />
|
||||
</li>
|
||||
</div>
|
||||
<div className='section'>
|
||||
<h4>Background</h4>
|
||||
<ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[3], document.getElementsByClassName('expandIcons')[3])} />
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={()=> this.setItem('background')} id='backgroundStatus' />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<li className="extraSettings">
|
||||
<ul>
|
||||
<p>Adjust Blur (<span id='blurAmount'></span>%) <span className="modalLink" onClick={() => this.resetItem('blur')}>Reset</span></p>
|
||||
<h4>{this.props.language.background.title}</h4>
|
||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[3], document.getElementsByClassName('expandIcons')[3])} />
|
||||
<Slider name='background' override='customBackground' />
|
||||
<li className='extraSettings'>
|
||||
<ul>
|
||||
<label htmlFor='8'>{this.props.language.background.API} </label>
|
||||
<label className='dropdown'>
|
||||
<select className='select-css' name='8' id='backgroundAPI' onChange={() => localStorage.setItem('backgroundAPI', document.getElementById('backgroundAPI').value)}>
|
||||
<option value='mue'>Mue</option>
|
||||
<option value='unsplash'>Unsplash</option>
|
||||
{ /* <option value='custom'>Custom</option> */ }
|
||||
</select>
|
||||
</label>
|
||||
</ul>
|
||||
<ul>
|
||||
<input className="range" type="range" min="0" max="100" id='blurRange' onInput={() => document.getElementById('blurAmount').innerText = document.getElementById('blurRange').value} />
|
||||
<p>{this.props.language.background.blur} (<span id='blurAmount'></span>%) <span className='modalLink' onClick={() => this.resetItem('blur')}>Reset</span></p>
|
||||
<input className='range' type='range' min='0' max='100' id='blurRange' onInput={() => document.getElementById('blurAmount').innerText = document.getElementById('blurRange').value} />
|
||||
</ul>
|
||||
<ul>
|
||||
<p>Custom Background URL <span className="modalLink" onClick={() => this.resetItem('customBackground')}>Reset</span></p>
|
||||
<p>{this.props.language.background.customURL} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>Reset</span></p>
|
||||
<input type='text' id='customBackground'></input>
|
||||
</ul>
|
||||
{ /*<ul>
|
||||
<p>Custom Background Colour <span className="modalLink" onClick={() => this.resetItem('customBackgroundColour')}>Reset</span></p>
|
||||
<ul>
|
||||
<p>{this.props.language.background.custombackground} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>Reset</span></p>
|
||||
<button className='uploadbg' onClick={() => document.getElementById('bg-input').click()}>Upload</button>
|
||||
<input id='bg-input' type='file' name='name' className='hidden' />
|
||||
</ul>
|
||||
{ /* <ul>
|
||||
<p>{this.props.language.background.customcolour} <span className='modalLink' onClick={() => this.resetItem('customBackgroundColour')}>Reset</span></p>
|
||||
<input name='colour' type='color' id='customBackgroundColour' onChange={() => document.getElementById('customBackgroundHex').innerText = document.getElementById('customBackgroundColour').value}></input>
|
||||
<label for='colour' id='customBackgroundHex'>#00000</label>
|
||||
</ul> */}
|
||||
<label htmlFor='colour' id='customBackgroundHex'>#00000</label>
|
||||
</ul> */ }
|
||||
</li>
|
||||
</div>
|
||||
<div className='section'>
|
||||
<h4>Search Bar</h4>
|
||||
{/* <ExpandMore className='expandIcons' onClick={() => this.toggleExtra(document.getElementsByClassName('extraSettings')[4], document.getElementsByClassName('expandIcons')[4])} /> */ }
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={() => this.setItem('searchBar')} id='searchBarStatus' />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
{/* <li className="extraSettings">
|
||||
<h4>{this.props.language.searchbar.title}</h4>
|
||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[4], document.getElementsByClassName('expandIcons')[4])} />
|
||||
<Slider name='searchBar' />
|
||||
<li className='extraSettings'>
|
||||
<ul>
|
||||
<label htmlFor="4">Search Engine</label>
|
||||
<select name="4" id='searchBar'>
|
||||
<option value="duckduckgo">DuckDuckGo</option>
|
||||
<option value="google">Google</option>
|
||||
<option value="bing">Bing</option>
|
||||
<option value="custom">Custom</option>
|
||||
</select>
|
||||
<label htmlFor='4'>{this.props.language.searchbar.searchengine} </label>
|
||||
<select className='select-css' name='4' id='searchEngine' onChange={() => SettingsFunctions.setSearchEngine(document.getElementById('searchEngine').value)}>
|
||||
<option value='duckduckgo'>DuckDuckGo</option>
|
||||
<option value='google'>Google</option>
|
||||
<option value='bing'>Bing</option>
|
||||
{ /* <option value='custom'>Custom</option> */ }
|
||||
</select>
|
||||
</ul>
|
||||
</li> */}
|
||||
<ul id='searchEngineInput' style={{ display: 'none' }}>
|
||||
<p>Custom Search URL <span className='modalLink' onClick={() => this.resetItem('customSearchEngine')}>Reset</span></p>
|
||||
<input type='text' id='customSearchEngine'></input>
|
||||
</ul>
|
||||
</li>
|
||||
</div>
|
||||
<div className='section'>
|
||||
<h4>Offline Mode</h4>
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={() => this.setItem('offlineMode')} id='offlineModeStatus' />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<h4>{this.props.language.offline}</h4>
|
||||
<Slider name='offlineMode' />
|
||||
</div>
|
||||
<h3>Experimental</h3>
|
||||
<h3>{this.props.language.experimental.title}</h3>
|
||||
<div className='section'>
|
||||
<h4>Enable WebP</h4>
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={() => this.setItem('webp')} id='webpStatus' />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<h4>{this.props.language.experimental.webp}</h4>
|
||||
<Slider name='webp' />
|
||||
</div>
|
||||
<div className='section'>
|
||||
<h4>Dark Theme</h4>
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={() => this.setItem('darkTheme')} id='darkThemeStatus' />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
<h4>{this.props.language.experimental.dark}</h4>
|
||||
<Slider name='darkTheme' />
|
||||
</div>
|
||||
<button className="apply" onClick={() => this.saveStuff()}>Apply</button>
|
||||
<button className="reset" onClick={() => this.props.setDefaultSettings()}>Reset</button>
|
||||
<div className='section'>
|
||||
<h4>{this.props.language.experimental.animations}</h4>
|
||||
<Slider name='animations' />
|
||||
</div>
|
||||
<div className='section'>
|
||||
<h4 htmlFor='9'>{this.props.language.language} </h4>
|
||||
<select className='select-css' name='9' id='language' onChange={() => localStorage.setItem('language', document.getElementById('language').value)}>
|
||||
<option className='choices' value='en'>English</option>
|
||||
<option className='choices' value='nl'>Dutch</option>
|
||||
<option className='choices' value='fr'>French</option>
|
||||
</select>
|
||||
</div>
|
||||
<button className='apply' onClick={() => SettingsFunctions.saveStuff()}>{this.props.language.apply}</button>
|
||||
<button className='reset' onClick={() => this.props.setDefaultSettings()}>{this.props.language.reset}</button>
|
||||
<button className='export' onClick={() => SettingsFunctions.exportSettings()}>{this.props.language.export}</button>
|
||||
<button className='import' onClick={() => document.getElementById('file-input').click()}>{this.props.language.import}</button>
|
||||
<input id='file-input' type='file' name='name' className='hidden' />
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
//* Imports
|
||||
import React from 'react';
|
||||
import FileCopy from '@material-ui/icons/AttachFile';
|
||||
|
||||
export default class Toast extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div id='toast'>
|
||||
<FileCopy className="copyButton"/>
|
||||
<hr />
|
||||
Quote Copied!
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,33 @@
|
||||
import React from 'react';
|
||||
import * as Constants from '../modules/constants';
|
||||
|
||||
export default class Update extends React.Component {
|
||||
export default class Update extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
title: 'Loading...',
|
||||
date: '',
|
||||
content: 'Loading...'
|
||||
title: this.props.language.title,
|
||||
date: '21/07/2020',
|
||||
content: this.props.language.title
|
||||
};
|
||||
}
|
||||
|
||||
async getUpdate() {
|
||||
const enabled = localStorage.getItem('offlineMode');
|
||||
if (enabled === 'true') return this.setState({
|
||||
title: 'Offline',
|
||||
content: 'Cannot get update logs while in offline mode'
|
||||
if (localStorage.getItem('offlineMode') === 'true') return this.setState({
|
||||
title: this.props.language.offline.title,
|
||||
content: this.props.language.offline.description
|
||||
});
|
||||
|
||||
try { // First we try and get a quote from the API...
|
||||
let data = await fetch('https://api.muetab.xyz/getUpdate');
|
||||
try { // Get update log from the API
|
||||
let data = await fetch(Constants.API_URL + '/getUpdate');
|
||||
data = await data.json();
|
||||
this.setState({
|
||||
title: data.title,
|
||||
content: data.content
|
||||
});
|
||||
} catch (e) {
|
||||
} catch (e) { // If it fails, we send an error
|
||||
this.setState({
|
||||
title: 'Error',
|
||||
content: 'Could not connect to the server!'
|
||||
title: this.props.language.error.title,
|
||||
content: this.props.language.error.description
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -37,10 +37,11 @@ export default class Update extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="content">
|
||||
<span className="closeModal" onClick={this.props.modalClose}>×</span>
|
||||
<h1 dangerouslySetInnerHTML={{__html: this.state.title}}></h1>
|
||||
<p dangerouslySetInnerHTML={{__html: this.state.content}}></p>
|
||||
return <div className='content'>
|
||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||
<h1 style={{ 'marginBottom':'-10px' }} dangerouslySetInnerHTML={{__html: this.state.title}}></h1>
|
||||
<h5 style={{ 'lineHeight':'0px' }}> By Mue • <span dangerouslySetInnerHTML={{__html: this.state.date}}></span></h5>
|
||||
<p style={{ 'padding': '0px 20px 0px 20px' }} dangerouslySetInnerHTML={{__html: this.state.content}}></p>
|
||||
</div>;
|
||||
}
|
||||
}
|
||||
13
src/components/settings/Checkbox.jsx
Normal file
13
src/components/settings/Checkbox.jsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import React from 'react';
|
||||
import * as SettingsFunctions from '../../modules/settingsFunctions';
|
||||
|
||||
export default class Checkbox extends React.PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<ul>
|
||||
<input name={this.props.name} type="checkbox" onClick={() => SettingsFunctions.setItem(this.props.name)} id={this.props.name + 'Status'} />
|
||||
<label htmlFor={this.props.name}>{this.props.text}</label>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
15
src/components/settings/Slider.jsx
Normal file
15
src/components/settings/Slider.jsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import * as SettingsFunctions from '../../modules/settingsFunctions';
|
||||
|
||||
export default class Slider extends React.PureComponent {
|
||||
render() {
|
||||
let setText = this.props.name;
|
||||
if (this.props.override) setText = this.props.override;
|
||||
return (
|
||||
<label className="switch">
|
||||
<input type="checkbox" onClick={() => SettingsFunctions.setItem(setText)} id={this.props.name + 'Status'} />
|
||||
<span className="slider"></span>
|
||||
</label>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
//* Imports
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
//* Render
|
||||
ReactDOM.render(
|
||||
<App/>,
|
||||
document.getElementById('root')
|
||||
|
||||
2
src/modules/constants.js
Normal file
2
src/modules/constants.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const API_URL = 'https://api.muetab.xyz';
|
||||
export const OFFLINE_IMAGES = 20;
|
||||
62
src/modules/defaultSettings.json
Normal file
62
src/modules/defaultSettings.json
Normal file
@@ -0,0 +1,62 @@
|
||||
[
|
||||
{
|
||||
"name": "time",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "greeting",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "background",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "quote",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "searchBar",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "blur",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "events",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "customBackgroundColour",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "customBackground",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "greetingName",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "defaultGreetingMessage",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "language",
|
||||
"value": "en"
|
||||
},
|
||||
{
|
||||
"name": "backgroundAPI",
|
||||
"value": "mue"
|
||||
},
|
||||
{
|
||||
"name": "ampm",
|
||||
"value": true
|
||||
},
|
||||
{
|
||||
"name": "copyButton",
|
||||
"value": false
|
||||
}
|
||||
]
|
||||
60
src/modules/settingsFunctions.js
Normal file
60
src/modules/settingsFunctions.js
Normal file
@@ -0,0 +1,60 @@
|
||||
function saveFile(data, filename = 'file') {
|
||||
if (!data) return console.error('No data');
|
||||
if (typeof data === 'object') data = JSON.stringify(data, undefined, 4);
|
||||
|
||||
const blob = new Blob([data], { type: 'text/json' });
|
||||
let e = document.createEvent('MouseEvents');
|
||||
let a = document.createElement('a');
|
||||
|
||||
a.href = window.URL.createObjectURL(blob);
|
||||
a.download = filename;
|
||||
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
|
||||
|
||||
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
a.dispatchEvent(e);
|
||||
}
|
||||
|
||||
export function exportSettings() {
|
||||
let settings = {};
|
||||
for (const key of Object.keys(localStorage)) settings[key] = localStorage.getItem(key);
|
||||
saveFile(settings, 'mue-settings.json');
|
||||
}
|
||||
|
||||
export function setItem(key, value) {
|
||||
let old = localStorage.getItem(key);
|
||||
let val = true;
|
||||
|
||||
if (old !== null && !value) {
|
||||
if (old === 'true') val = false;
|
||||
if (old === 'false') val = true;
|
||||
}
|
||||
|
||||
localStorage.setItem(key, val);
|
||||
}
|
||||
|
||||
export function toggleExtra(element, element2) {
|
||||
(element.style.display === 'none' || !element.style.display) ? element.style.display = 'block' : element.style.display = 'none';
|
||||
(element2.style.transform === 'rotate(-180deg)') ? element2.style.transform = 'rotate(0)' : element2.style.transform = 'rotate(-180deg)';
|
||||
}
|
||||
|
||||
export function setSearchEngine(input) {
|
||||
const searchEngineInput = document.getElementById('searchEngineInput');
|
||||
if (input === 'custom') {
|
||||
searchEngineInput.enabled = 'false';
|
||||
searchEngineInput.style.display = 'block';
|
||||
} else {
|
||||
searchEngineInput.style.display = 'none';
|
||||
searchEngineInput.enabled = 'true';
|
||||
localStorage.setItem('searchEngine', input);
|
||||
}
|
||||
}
|
||||
|
||||
export function saveStuff() {
|
||||
localStorage.setItem('blur', document.getElementById('blurRange').value); // this is better than inline onChange for performance
|
||||
localStorage.setItem('greetingName', document.getElementById('greetingName').value);
|
||||
localStorage.setItem('customBackground', document.getElementById('customBackground').value);
|
||||
if (!document.getElementById('searchEngineInput').enabled === 'false') {
|
||||
localStorage.setItem('customSearchEngine', document.getElementById('searchEngineInput').value);
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
@@ -57,7 +57,48 @@ body {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
-webkit-animation: fadein 2s;
|
||||
animation: fadein 2s;
|
||||
-moz-animation: fadein 2s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@-moz-keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Lexend Deca';
|
||||
src: url('/./fonts/LexendDeca-Regular.woff2') format('woff2');
|
||||
}
|
||||
|
||||
.backgroundEffects {
|
||||
opacity: .7;
|
||||
transition: ease 0.6s;
|
||||
}
|
||||
|
||||
#searchEngine {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.select-css {
|
||||
background: none;
|
||||
backdrop-filter: blur(10em);
|
||||
height: 34px;
|
||||
width: 100px;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(180deg, #ffb032 0%, #dd3b67 100%);
|
||||
border-left: 10px solid;
|
||||
font-weight: 400;
|
||||
}
|
||||
@@ -7,4 +7,33 @@
|
||||
|
||||
.ampm {
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
.analogclock {
|
||||
font-size: 4em;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
||||
border-radius: 100%;
|
||||
box-shadow: inset 0 0 100px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.react-clock__face {
|
||||
border: none;
|
||||
outline: none;
|
||||
border: 3px #fff solid;
|
||||
transition: 2s;
|
||||
}
|
||||
|
||||
.react-clock__second-hand__body {
|
||||
background: #e84118;
|
||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
||||
transition: 2s;
|
||||
}
|
||||
.react-clock__hand__body {
|
||||
background: #fff;
|
||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
||||
transition: 2s;
|
||||
}
|
||||
.react-clock__mark__body {
|
||||
display: none;
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
position: absolute;
|
||||
bottom: 2px;
|
||||
left: 2px;
|
||||
transition: all 0.5s ease 0s;
|
||||
}
|
||||
|
||||
.credits {
|
||||
@@ -33,7 +34,6 @@
|
||||
left: 0px;
|
||||
position: absolute;
|
||||
text-align: left;
|
||||
min-width: 50px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
@@ -41,26 +41,27 @@
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-bottom: 1px dotted black;
|
||||
bottom: 15px;
|
||||
left: 10px;
|
||||
-webkit-filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4));
|
||||
filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4));
|
||||
|
||||
.tooltiptext {
|
||||
width: 200px;
|
||||
display: inline-block;
|
||||
visibility: hidden;
|
||||
background-color: black;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
font-size: calc(10px + 1.2vmin);
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
padding: 15px 32px;
|
||||
bottom: 40px;
|
||||
left: 60px;
|
||||
margin-left: -60px;
|
||||
opacity: 0;
|
||||
transition: opacity 1s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
.Modal {
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 0 200px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
|
||||
border: none;
|
||||
opacity: 1;
|
||||
z-index: -2;
|
||||
padding: 20px;
|
||||
padding: 25px;
|
||||
cursor: hand;
|
||||
|
||||
transition: 0.6s;
|
||||
transition-timing-function: ease-in;
|
||||
border-radius: 12px;
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
@@ -16,6 +18,7 @@
|
||||
.modalLink {
|
||||
color: #5352ed;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
@@ -25,6 +28,7 @@
|
||||
float: right;
|
||||
font-size: 2em;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: grey;
|
||||
}
|
||||
@@ -37,9 +41,40 @@
|
||||
|
||||
.ReactModal__Html--open,
|
||||
.ReactModal__Body--open {
|
||||
overflow: hidden; /* prevents background page from scrolling when the modal is open */
|
||||
overflow: hidden;
|
||||
/* prevents background page from scrolling when the modal is open */
|
||||
}
|
||||
|
||||
@-webkit-keyframes zoom-in {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.05, 1.05);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoom-in {
|
||||
0% {
|
||||
-webkit-transform: scale(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1.05, 1.05);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.Overlay {
|
||||
position: fixed;
|
||||
z-index: 999999;
|
||||
@@ -55,6 +90,11 @@
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.modal-animation {
|
||||
-webkit-animation: zoom-in 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
animation: zoom-in 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
|
||||
.ReactModal__Content {
|
||||
width: 500px;
|
||||
max-width: 600px;
|
||||
@@ -63,3 +103,50 @@
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-top: -20px;
|
||||
h1 {
|
||||
font-size: 35px;
|
||||
}
|
||||
p {
|
||||
margin-top: -20px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.columns {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.zoom-out {
|
||||
-webkit-animation: zoom-out 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
animation: zoom-out 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes zoom-out {
|
||||
0% {
|
||||
transform: scale(1, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.05, 1.05);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoom-out {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1);
|
||||
}
|
||||
|
||||
50% {
|
||||
-webkit-transform: scale(1.05, 1.05);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: scale(0);
|
||||
}
|
||||
}
|
||||
@@ -5,22 +5,35 @@
|
||||
cursor: pointer;
|
||||
-webkit-filter: drop-shadow(0 0 6px rgba(0,0,0,.3));
|
||||
filter: drop-shadow(0 0 6px rgba(0,0,0,.3));
|
||||
top: 50px;
|
||||
svg {
|
||||
transition: ease 0.2s;
|
||||
}
|
||||
&:hover {
|
||||
svg {
|
||||
transform: scale(1.1);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar1 {
|
||||
@extend %navbar;
|
||||
top: 50px;
|
||||
right: 0px;
|
||||
svg {
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transform: translateZ(0) scale(1.0, 1.0);
|
||||
backface-visibility: hidden;
|
||||
transform: translateZ(0) scale(1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
.navbar2 {
|
||||
@extend %navbar;
|
||||
top: 50px;
|
||||
right: 50px;
|
||||
}
|
||||
|
||||
.navbar3 {
|
||||
@extend %navbar;
|
||||
top: 50px;
|
||||
right: 100px;
|
||||
}
|
||||
@@ -30,7 +30,7 @@
|
||||
float: middle;
|
||||
margin: 0 auto;
|
||||
text-align: right;
|
||||
transform: rotate(45deg);
|
||||
// transform: rotate(45deg);
|
||||
}
|
||||
|
||||
i.material-icons,
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
.searchbar {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
display: block;
|
||||
color: #ffff;
|
||||
font-family: 'Lexend Deca', sans-serif;;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
display: block;
|
||||
color: #ffff;
|
||||
font-family: 'Lexend Deca', sans-serif;;
|
||||
|
||||
input[type=text] {
|
||||
font-size: calc(5px + 1.2vmin);
|
||||
background: transparent;
|
||||
border: 2px solid #ffff;
|
||||
padding: 10px;
|
||||
color: #ffff;
|
||||
position: absolute;
|
||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
input[type=text] {
|
||||
font-size: calc(5px + 1.2vmin);
|
||||
background: transparent;
|
||||
border: 2px solid #ffff;
|
||||
padding: 10px;
|
||||
color: #ffff;
|
||||
position: absolute;
|
||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
}
|
||||
|
||||
.input.searchtext {
|
||||
border: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.searchbarform {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, .25);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, .25);
|
||||
}
|
||||
@@ -14,6 +14,10 @@ $gradient: linear-gradient(90deg, #ffb032 0%, #dd3b67 100%);
|
||||
}
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
@@ -32,8 +36,8 @@ $gradient: linear-gradient(90deg, #ffb032 0%, #dd3b67 100%);
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@@ -56,7 +60,7 @@ input {
|
||||
|
||||
&:checked + .slider {
|
||||
background: $gradient;
|
||||
|
||||
|
||||
&:before {
|
||||
-webkit-transform: translateX(26px);
|
||||
-ms-transform: translateX(26px);
|
||||
@@ -71,7 +75,12 @@ input {
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
background: #555;
|
||||
background: #bdc3c7;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #34495e;
|
||||
}
|
||||
|
||||
h4, .switch, .expandIcons {
|
||||
@@ -89,8 +98,6 @@ h4, #engines {
|
||||
}
|
||||
|
||||
%settingsButton {
|
||||
height: 45px;
|
||||
width: 130px;
|
||||
text-align: center;
|
||||
border: none;
|
||||
transition: 0.25s;
|
||||
@@ -98,12 +105,15 @@ h4, #engines {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
box-shadow: 20px #000;
|
||||
font-size: 1.3em;
|
||||
position: relative;
|
||||
padding: 15px;
|
||||
width: 120px;
|
||||
font-size: 1.1em;
|
||||
font-family: 'Lexend Deca', sans-serif;
|
||||
|
||||
&:hover {
|
||||
transform: translateX(-0.10em);
|
||||
transform: translateY(-0.10em);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:before {
|
||||
@@ -135,10 +145,43 @@ h4, #engines {
|
||||
}
|
||||
}
|
||||
|
||||
.import {
|
||||
float: right;
|
||||
@extend %settingsButton;
|
||||
background-color: #dd3b67;
|
||||
margin-right: 5px;
|
||||
|
||||
&:before {
|
||||
background: $gradient;
|
||||
}
|
||||
}
|
||||
|
||||
.export {
|
||||
float: right;
|
||||
@extend %settingsButton;
|
||||
background-color: #dd3b67;
|
||||
|
||||
&:before {
|
||||
background: $gradient;
|
||||
}
|
||||
}
|
||||
|
||||
.uploadbg {
|
||||
@extend %settingsButton;
|
||||
background-color: #dd3b67;
|
||||
width: auto;
|
||||
height: auto;
|
||||
padding: 5px 18px;
|
||||
|
||||
&:before {
|
||||
background: $gradient;
|
||||
}
|
||||
}
|
||||
|
||||
.reset {
|
||||
@extend %settingsButton;
|
||||
background-color: #ffb032;
|
||||
margin-left: 20px;
|
||||
margin-left: 5px;
|
||||
&:before {
|
||||
background: linear-gradient(90deg, #dd3b67 0%, #ffb032 100%);
|
||||
}
|
||||
@@ -150,7 +193,6 @@ h4, #engines {
|
||||
vertical-align: middle;
|
||||
display: inline-flex;
|
||||
cursor: pointer;
|
||||
transition-duration: 0.5s;
|
||||
}
|
||||
|
||||
.extraSettings {
|
||||
@@ -199,7 +241,7 @@ li {
|
||||
background: $gradient;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
&::-moz-range-thumb {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
@@ -220,7 +262,7 @@ input[type=color] {
|
||||
vertical-align: middle;
|
||||
|
||||
&::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&::-webkit-color-swatch {
|
||||
@@ -231,4 +273,22 @@ input[type=color] {
|
||||
|
||||
input[type=checkbox] {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#customBackgroundHex {
|
||||
font-size: 1.2em;
|
||||
padding-left: 7px;
|
||||
}
|
||||
|
||||
select#language {
|
||||
float: right;
|
||||
background: none;
|
||||
backdrop-filter: blur(10em);
|
||||
height: 34px;
|
||||
width: 100px;
|
||||
border-image-slice: 1;
|
||||
border-image-source: linear-gradient(180deg, #ffb032 0%, #dd3b67 100%);
|
||||
border-left: 10px solid;
|
||||
font-weight: 400;
|
||||
font-family: 'Lexend Deca', sans-serif;
|
||||
}
|
||||
@@ -1,96 +1,29 @@
|
||||
#toast {
|
||||
visibility: hidden;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
bottom: 30px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .2);
|
||||
// backdrop-filter: blur(20px); stupid firefox :(
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
width: auto;
|
||||
bottom: 30px;
|
||||
right: 30px;
|
||||
|
||||
&.show {
|
||||
visibility: visible;
|
||||
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
|
||||
animation: fadein 0.5s, fadeout 0.5s 2.5s;
|
||||
}
|
||||
|
||||
> img {
|
||||
height: 20px;
|
||||
width: auto;
|
||||
float: left;
|
||||
}
|
||||
|
||||
> hr {
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.Toastify__toast-body {
|
||||
font-family: 'Lexend Deca', sans-serif !important;
|
||||
color: #000 !important;
|
||||
font-size: 16px !important;
|
||||
padding: 15px 20px !important;
|
||||
}
|
||||
|
||||
.copyButton, hr {
|
||||
display: inline;
|
||||
vertical-align: middle;
|
||||
.Toastify__toast {
|
||||
border-radius: 12px !important;
|
||||
min-height: auto !important;
|
||||
height: auto !important;
|
||||
width: auto !important;
|
||||
min-width: auto !important;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 20px;
|
||||
width: 1px;
|
||||
margin: 0;
|
||||
margin-left: 10px;
|
||||
.Toastify__close-button {
|
||||
margin-top: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadein {
|
||||
from {
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
bottom: 30px;
|
||||
opacity: 1;
|
||||
}
|
||||
.Toastify__progress-bar--default {
|
||||
height: 3px !important;
|
||||
background: #000 !important;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from {
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
bottom: 30px;
|
||||
opacity: 1;
|
||||
}
|
||||
.Toastify__toast-container {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeout {
|
||||
from {
|
||||
bottom: 30px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeout {
|
||||
from {
|
||||
bottom: 30px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
bottom: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
74
src/translations/en.json
Normal file
74
src/translations/en.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"greeting": {
|
||||
"morning": "Good Morning",
|
||||
"afternoon": "Good Afternoon",
|
||||
"evening": "Good Evening",
|
||||
"christmas": "Merry Christmas",
|
||||
"newyear": "Happy new year",
|
||||
"halloween": "Happy Halloween"
|
||||
},
|
||||
"credit": "Photo by",
|
||||
"search": "Search",
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"description": "Edit different components to make Mue your new tab.",
|
||||
"time": {
|
||||
"title": "Time",
|
||||
"seconds": "Seconds",
|
||||
"twentyfourhour": "24 Hour",
|
||||
"ampm": "AM/PM (12 hour)",
|
||||
"zero": "Extra Zero",
|
||||
"analog": "Analog"
|
||||
},
|
||||
"greeting": {
|
||||
"title": "Greeting",
|
||||
"events": "Events",
|
||||
"default": "Default Greeting Message",
|
||||
"name": "Name for greeting"
|
||||
},
|
||||
"quote": {
|
||||
"title": "Quote",
|
||||
"copy": "Copy Button"
|
||||
},
|
||||
"background": {
|
||||
"title": "Background",
|
||||
"API": "Background API",
|
||||
"blur": "Adjust Blur",
|
||||
"customURL": "Custom Background URL",
|
||||
"custombackground": "Custom Background",
|
||||
"customcolour": "Custom Background Colour"
|
||||
},
|
||||
"searchbar": {
|
||||
"title": "Search Bar",
|
||||
"searchengine": "Search Engine"
|
||||
},
|
||||
"offline": "Offline Mode",
|
||||
"experimental": {
|
||||
"title": "Experimental",
|
||||
"webp": "Enable WebP",
|
||||
"dark": "Dark Theme",
|
||||
"animations": "Animations"
|
||||
},
|
||||
"language": "Language",
|
||||
"apply": "Apply",
|
||||
"reset": "Reset",
|
||||
"import": "Import",
|
||||
"export": "Export"
|
||||
},
|
||||
"update": {
|
||||
"title": "Update",
|
||||
"offline": {
|
||||
"title": "Offline",
|
||||
"description": "Cannot get update logs while in offline mode"
|
||||
},
|
||||
"error": {
|
||||
"title": "Error",
|
||||
"content": "Could not connect to the server"
|
||||
},
|
||||
"loading": "Loading..."
|
||||
},
|
||||
"toasts": {
|
||||
"quote": "Quote Copied!",
|
||||
"reset": "Reset successfully!"
|
||||
}
|
||||
}
|
||||
74
src/translations/fr.json
Normal file
74
src/translations/fr.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"greeting": {
|
||||
"morning": "Good Morning",
|
||||
"afternoon": "Good Afternoon",
|
||||
"evening": "Good Evening",
|
||||
"christmas": "Merry Christmas",
|
||||
"newyear": "Happy new year",
|
||||
"halloween": "Happy Halloween"
|
||||
},
|
||||
"credit": "Photo by",
|
||||
"search": "Search",
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"description": "Edit different components to make Mue your new tab.",
|
||||
"time": {
|
||||
"title": "Time",
|
||||
"seconds": "Seconds",
|
||||
"twentyfourhour": "24 Hour",
|
||||
"ampm": "AM/PM (12 hour)",
|
||||
"zero": "Extra Zero",
|
||||
"analog": "Analog"
|
||||
},
|
||||
"greeting": {
|
||||
"title": "Greeting",
|
||||
"events": "Events",
|
||||
"default": "Default Greeting Message",
|
||||
"name": "Name for greeting"
|
||||
},
|
||||
"quote": {
|
||||
"title": "Quote",
|
||||
"copy": "Copy Button"
|
||||
},
|
||||
"background": {
|
||||
"title": "Background",
|
||||
"API": "Background API",
|
||||
"blur": "Adjust Blur",
|
||||
"customURL": "Custom Background URL",
|
||||
"custombackground": "Custom Background",
|
||||
"customcolour": "Custom Background Colour"
|
||||
},
|
||||
"searchbar": {
|
||||
"title": "Search Bar",
|
||||
"searchengine": "Search Engine"
|
||||
},
|
||||
"offline": "Offline Mode",
|
||||
"experimental": {
|
||||
"title": "Experimental",
|
||||
"webp": "Enable WebP",
|
||||
"dark": "Dark Theme",
|
||||
"animations": "Animations"
|
||||
},
|
||||
"language": "Language",
|
||||
"apply": "Apply",
|
||||
"reset": "Reset",
|
||||
"import": "Import",
|
||||
"export": "Export"
|
||||
},
|
||||
"update": {
|
||||
"title": "Update",
|
||||
"offline": {
|
||||
"title": "Offline",
|
||||
"description": "Cannot get update logs while in offline mode"
|
||||
},
|
||||
"error": {
|
||||
"title": "Error",
|
||||
"content": "Could not connect to the server"
|
||||
},
|
||||
"loading": "Loading..."
|
||||
},
|
||||
"toasts": {
|
||||
"quote": "Quote Copied!",
|
||||
"reset": "Reset successfully!"
|
||||
}
|
||||
}
|
||||
74
src/translations/nl.json
Normal file
74
src/translations/nl.json
Normal file
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"greeting": {
|
||||
"morning": "Good Morning",
|
||||
"afternoon": "Good Afternoon",
|
||||
"evening": "Good Evening",
|
||||
"christmas": "Merry Christmas",
|
||||
"newyear": "Happy new year",
|
||||
"halloween": "Happy Halloween"
|
||||
},
|
||||
"credit": "Photo by",
|
||||
"search": "Search",
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"description": "Edit different components to make Mue your new tab.",
|
||||
"time": {
|
||||
"title": "Time",
|
||||
"seconds": "Seconds",
|
||||
"twentyfourhour": "24 Hour",
|
||||
"ampm": "AM/PM (12 hour)",
|
||||
"zero": "Extra Zero",
|
||||
"analog": "Analog"
|
||||
},
|
||||
"greeting": {
|
||||
"title": "Greeting",
|
||||
"events": "Events",
|
||||
"default": "Default Greeting Message",
|
||||
"name": "Name for greeting"
|
||||
},
|
||||
"quote": {
|
||||
"title": "Quote",
|
||||
"copy": "Copy Button"
|
||||
},
|
||||
"background": {
|
||||
"title": "Background",
|
||||
"API": "Background API",
|
||||
"blur": "Adjust Blur",
|
||||
"customURL": "Custom Background URL",
|
||||
"custombackground": "Custom Background",
|
||||
"customcolour": "Custom Background Colour"
|
||||
},
|
||||
"searchbar": {
|
||||
"title": "Search Bar",
|
||||
"searchengine": "Search Engine"
|
||||
},
|
||||
"offline": "Offline Mode",
|
||||
"experimental": {
|
||||
"title": "Experimental",
|
||||
"webp": "Enable WebP",
|
||||
"dark": "Dark Theme",
|
||||
"animations": "Animations"
|
||||
},
|
||||
"language": "Language",
|
||||
"apply": "Apply",
|
||||
"reset": "Reset",
|
||||
"import": "Import",
|
||||
"export": "Export"
|
||||
},
|
||||
"update": {
|
||||
"title": "Update",
|
||||
"offline": {
|
||||
"title": "Offline",
|
||||
"description": "Cannot get update logs while in offline mode"
|
||||
},
|
||||
"error": {
|
||||
"title": "Error",
|
||||
"content": "Could not connect to the server"
|
||||
},
|
||||
"loading": "Loading..."
|
||||
},
|
||||
"toasts": {
|
||||
"quote": "Quote Copied!",
|
||||
"reset": "Reset successfully!"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user