mirror of
https://github.com/mue/mue.git
synced 2026-07-13 04:02:32 +02:00
4.0
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:
92
src/components/widgets/Background.jsx
Normal file
92
src/components/widgets/Background.jsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import React from 'react';
|
||||
import supportsWebP from 'supports-webp';
|
||||
import * as Constants from '../../modules/constants';
|
||||
|
||||
export default class Background extends React.PureComponent {
|
||||
doOffline() {
|
||||
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
|
||||
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;
|
||||
case 7: photographer = 'Miriam Espacio'; break;
|
||||
case 10: photographer = 'NO NAME'; break;
|
||||
case 20: photographer = 'Fabian Wiktor'; break;
|
||||
default: photographer = 'Unknown'; break;
|
||||
}
|
||||
|
||||
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(../offline-images/${photo}.jpeg)`); // Set background and blur etc
|
||||
let credit = document.getElementById('photographer');
|
||||
credit.innerText = `${credit.innerText} ${photographer} (Pexels)`; // Set the credit
|
||||
}
|
||||
|
||||
async setBackground() {
|
||||
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
||||
|
||||
const photoPack = JSON.parse(localStorage.getItem('photo_packs'));
|
||||
if (photoPack) {
|
||||
let background = photoPack[Math.floor(Math.random() * photoPack.length)];
|
||||
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(${background.url.default})`); // Set background and blur etc
|
||||
}
|
||||
|
||||
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 !== '') {
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
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();
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div id='backgroundImage'></div>;
|
||||
}
|
||||
}
|
||||
75
src/components/widgets/Clock.jsx
Normal file
75
src/components/widgets/Clock.jsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import React from 'react';
|
||||
import Analog from 'react-clock';
|
||||
|
||||
export default class Clock extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
|
||||
this.timer = undefined;
|
||||
this.state = {
|
||||
time: '',
|
||||
ampm: ''
|
||||
};
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
// Analog clock
|
||||
if (localStorage.getItem('analog') === 'true') {
|
||||
this.setState({
|
||||
time: now
|
||||
});
|
||||
} else {
|
||||
let sec = '';
|
||||
|
||||
// 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();
|
||||
}, time);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('time') === 'false') return;
|
||||
this.startTime(0);
|
||||
}
|
||||
|
||||
render() {
|
||||
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} renderHourMarks={false} renderMinuteMarks={false} />;
|
||||
return clockHTML;
|
||||
}
|
||||
}
|
||||
64
src/components/widgets/Greeting.jsx
Normal file
64
src/components/widgets/Greeting.jsx
Normal file
@@ -0,0 +1,64 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class Greeting extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
greeting: ''
|
||||
};
|
||||
}
|
||||
|
||||
doEvents(time, message) {
|
||||
if (localStorage.getItem('events') === 'false') return message;
|
||||
|
||||
// Get current month & day
|
||||
const m = time.getMonth();
|
||||
const d = time.getDate();
|
||||
|
||||
if (m === 11 && d === 25) message = 'Merry Christmas'; // If it's December 25th, set the greeting string to "Merry Christmas"
|
||||
else if (m === 0 && d === 1) message = 'Happy new year'; // If the date is January 1st, set the greeting string to "Happy new year"
|
||||
else if (m === 9 && d === 31) message = 'Happy Halloween'; // If it's October 31st, set the greeting string to "Happy Halloween"
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
getGreeting() {
|
||||
const now = new Date();
|
||||
const hour = now.getHours();
|
||||
|
||||
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);
|
||||
let custom = localStorage.getItem('defaultGreetingMessage');
|
||||
if (custom === 'false') message = '';
|
||||
|
||||
// Name
|
||||
let name = '';
|
||||
const data = localStorage.getItem('greetingName');
|
||||
|
||||
if (typeof data === 'string') {
|
||||
if (data.replace(/\s/g, '').length > 0) name = `, ${data.trim()}`;
|
||||
}
|
||||
|
||||
if (custom === 'false') name = name.replace(',', '');
|
||||
|
||||
// Set the state to the greeting string
|
||||
this.setState({
|
||||
greeting: `${message}${name}`
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('greeting') === 'false') return;
|
||||
this.getGreeting();
|
||||
}
|
||||
|
||||
render() {
|
||||
return <h1 className='greeting'>
|
||||
{this.state.greeting}
|
||||
</h1>;
|
||||
}
|
||||
}
|
||||
70
src/components/widgets/Quote.jsx
Normal file
70
src/components/widgets/Quote.jsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import React from 'react';
|
||||
import Quotes from '@muetab/quotes';
|
||||
import FileCopy from '@material-ui/icons/FilterNone';
|
||||
import { toast } from 'react-toastify';
|
||||
import * as Constants from '../../modules/constants';
|
||||
|
||||
export default class Quote extends React.PureComponent {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.state = {
|
||||
quote: '',
|
||||
author: ''
|
||||
};
|
||||
}
|
||||
|
||||
doOffline() {
|
||||
const quote = Quotes.random(); // Get a random quote from our local package
|
||||
this.setState({
|
||||
quote: '"' + quote.quote + '"',
|
||||
author: quote.author
|
||||
}); // Set the quote
|
||||
}
|
||||
|
||||
async getQuote() {
|
||||
const quotePack = JSON.parse(localStorage.getItem('quote_packs'));
|
||||
if (quotePack) {
|
||||
const data = quotePack[Math.floor(Math.random() * quotePack.length)]
|
||||
return this.setState({
|
||||
quote: '"' + data.quote + '"',
|
||||
author: data.author
|
||||
});
|
||||
}
|
||||
|
||||
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
||||
|
||||
try { // First we try and get a quote from the API...
|
||||
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({
|
||||
quote: '"' + data.quote + '"',
|
||||
author: data.author
|
||||
});
|
||||
} catch (e) { // ..and if that fails we load one locally
|
||||
this.doOffline();
|
||||
}
|
||||
}
|
||||
|
||||
copyQuote() {
|
||||
navigator.clipboard.writeText(`${this.state.quote} - ${this.state.author}`);
|
||||
toast(this.props.language.quote);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('quote') === 'false') return;
|
||||
this.getQuote();
|
||||
}
|
||||
|
||||
render() {
|
||||
let copy = <FileCopy className='copyButton' onClick={() => this.copyQuote() }></FileCopy>;
|
||||
if (localStorage.getItem('copyButton') === 'false') copy = '';
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1 className='quote'>{`${this.state.quote}`}</h1>
|
||||
<h1 className='quoteauthor'>{this.state.author} {copy}</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
38
src/components/widgets/Search.jsx
Normal file
38
src/components/widgets/Search.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import React from 'react';
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
|
||||
export default class Search extends React.PureComponent {
|
||||
render() {
|
||||
if (localStorage.getItem('searchBar') === 'false') return <div></div>;
|
||||
|
||||
let url;
|
||||
let query = 'q';
|
||||
|
||||
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;
|
||||
case 'yahoo': url ='https://search.yahoo.com/search'; break;
|
||||
case 'ecosia': url = 'https://ecosia.org/search'; break;
|
||||
case 'yandex': url = 'https://yandex.ru/search'; query = 'text'; break;
|
||||
case 'qwant': url = 'https://www.qwant.com/'; break;
|
||||
case 'ask': url = 'https://ask.com/web'; break;
|
||||
case 'startpage': url = 'https://www.startpage.com/sp/search'; break;
|
||||
default: url = 'https://duckduckgo.com'; break;
|
||||
}
|
||||
|
||||
const searchButton = () => {
|
||||
let value = document.getElementById('searchtext').value;
|
||||
if (!value) value = 'mue fast';
|
||||
window.location.href = url + '?q=' + value;
|
||||
}
|
||||
|
||||
return <div id='searchBar' className='searchbar'>
|
||||
<form id='searchBar' className='searchbarform' action={url}>
|
||||
<SearchIcon onClick={() => searchButton()} />
|
||||
<input type='text' placeholder={this.props.language} name={query} id='searchtext' className='searchtext'/>
|
||||
<div className='blursearcbBG'/>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user