mirror of
https://github.com/mue/mue.git
synced 2026-06-08 14:10:42 +02:00
refactor and fix some things
This commit is contained in:
@@ -32,6 +32,5 @@ Inspired features are fine.
|
||||
### Bug Fixes
|
||||
See the note in general.
|
||||
|
||||
|
||||
## Final Note
|
||||
Contact us before doing anything if you don't want to have to change 1000 things and/or have your pull request closed.
|
||||
@@ -21,11 +21,10 @@
|
||||
"react-beforeunload": "^2.4.0",
|
||||
"react-clock": "^3.0.0",
|
||||
"react-color-gradient-picker": "^0.1.2",
|
||||
"react-date-picker": "^8.0.5",
|
||||
"react-date-picker": "^8.0.6",
|
||||
"react-dom": "17.0.1",
|
||||
"react-modal": "3.12.1",
|
||||
"react-toastify": "6.2.0",
|
||||
"supports-webp": "2.0.1"
|
||||
"react-toastify": "6.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"node-sass": "^4.14.1",
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<svg width="20" height="20" viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="200" cy="200" r="200" fill="url(#paint0_linear)"/>
|
||||
<path d="M167 265.062L294.125 137.938L311 154.812L167 298.812L100.062 231.875L116.938 215L167 265.062Z" fill="white"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="200" y1="0" x2="200" y2="400" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FF5C25"/>
|
||||
<stop offset="1" stop-color="#FF456E"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 490 B |
19
src/App.jsx
19
src/App.jsx
@@ -1,15 +1,8 @@
|
||||
import React from 'react';
|
||||
|
||||
import Background from './components/widgets/background/Background';
|
||||
import Clock from './components/widgets/time/Clock';
|
||||
import Greeting from './components/widgets/greeting/Greeting';
|
||||
import Quote from './components/widgets/quote/Quote';
|
||||
import Search from './components/widgets/search/Search';
|
||||
import Maximise from './components/widgets/background/Maximise';
|
||||
import Favourite from './components/widgets/background/Favourite';
|
||||
import Widgets from './components/widgets/Widgets';
|
||||
import PhotoInformation from './components/widgets/background/PhotoInformation';
|
||||
import Date from './components/widgets/time/Date';
|
||||
|
||||
import Navbar from './components/widgets/navbar/Navbar';
|
||||
|
||||
import SettingsFunctions from './modules/helpers/settings';
|
||||
@@ -38,8 +31,10 @@ export default class App extends React.PureComponent {
|
||||
componentDidMount() {
|
||||
if (!localStorage.getItem('firstRun')) SettingsFunctions.setDefaultSettings();
|
||||
if (localStorage.getItem('showWelcome') === 'true') this.setState({ welcomeModal: true });
|
||||
|
||||
const css = localStorage.getItem('customcss');
|
||||
if (css) document.head.insertAdjacentHTML('beforeend', '<style>' + css + '</style>');
|
||||
|
||||
if (localStorage.getItem('darkTheme') === 'true') document.getElementsByClassName('Toastify')[0].classList.add('dark');
|
||||
}
|
||||
|
||||
@@ -68,15 +63,9 @@ export default class App extends React.PureComponent {
|
||||
<Background/>
|
||||
<ToastContainer position='bottom-right' autoClose={2500} newestOnTop={true} closeOnClick rtl={false} pauseOnFocusLoss />
|
||||
<div id='center'>
|
||||
<Search language={language.search} />
|
||||
<Navbar mainModalOpen={() => this.setState({ mainModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} feedbackModalOpen={() => this.setState({ feedbackModal: true })} language={language} />
|
||||
<Greeting language={language.greeting} />
|
||||
<Clock/>
|
||||
<Date/>
|
||||
<Quote language={language.toasts} languagecode={languagecode} />
|
||||
<Widgets language={language} languagecode={languagecode} />
|
||||
<PhotoInformation language={language} className={tooltipClassList} />
|
||||
<Maximise/>
|
||||
<Favourite/>
|
||||
<React.Suspense fallback={renderLoader()}>
|
||||
<Modal id={'modal'} onRequestClose={() => this.setState({ mainModal: false })} isOpen={this.state.mainModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
||||
<Main language={language} modalClose={() => this.setState({ mainModal: false })} />
|
||||
|
||||
@@ -6,34 +6,24 @@ export default class Update extends React.PureComponent {
|
||||
super(...args);
|
||||
this.state = {
|
||||
title: this.props.language.title,
|
||||
date: '???',
|
||||
date: null,
|
||||
content: this.props.language.title,
|
||||
author: 'Mue',
|
||||
html: this.props.language.loading
|
||||
html: this.props.language.loading,
|
||||
image: null
|
||||
};
|
||||
}
|
||||
|
||||
async getUpdate() {
|
||||
const supportText = `<br/><p>${this.props.language.contact_support}: <a target='_blank' class='modalLink' href='https://muetab.com/contact'>https://muetab.com/contact</a></p>`;
|
||||
|
||||
const removeStuff = () => { // quick code to make update modal a bit better, will replace later
|
||||
document.getElementById('author').innerText = '';
|
||||
const img = document.getElementsByTagName('img')[0];
|
||||
img.parentNode.removeChild(img);
|
||||
}
|
||||
|
||||
if (localStorage.getItem('offlineMode') === 'true') {
|
||||
removeStuff();
|
||||
return this.setState({
|
||||
title: this.props.language.offline.title,
|
||||
html: this.props.language.offline.description
|
||||
});
|
||||
}
|
||||
|
||||
try { // Get update log from the API
|
||||
const data = await (await fetch(Constants.API_URL + '/getUpdate')).json();
|
||||
if (data.statusCode === 500) {
|
||||
removeStuff();
|
||||
if (data.statusCode === 500 || data.title === null) {
|
||||
const supportText = `<br/><p>${this.props.language.contact_support}: <a target='_blank' class='modalLink' href='https://muetab.com/contact'>https://muetab.com/contact</a></p>`;
|
||||
return this.setState({
|
||||
title: this.props.language.error.title,
|
||||
html: this.props.language.error.description + supportText
|
||||
@@ -43,17 +33,10 @@ export default class Update extends React.PureComponent {
|
||||
this.setState({
|
||||
title: data.title,
|
||||
date: data.published,
|
||||
image: data.image,
|
||||
image: data.image || null,
|
||||
author: data.author,
|
||||
html: data.content + `<br/><p>${this.props.language.read_blog}: <a target='_blank' class='modalLink' href='${data.url}'>${data.url}</a></p>`
|
||||
html: data.content
|
||||
});
|
||||
} catch (e) { // If it fails, we send an error
|
||||
removeStuff();
|
||||
this.setState({
|
||||
title: this.props.language.error.title,
|
||||
html: this.props.language.error.description + supportText
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -64,8 +47,8 @@ export default class Update extends React.PureComponent {
|
||||
return <div className='updateContent'>
|
||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||
<h1 style={{ 'marginBottom': '-10px' }}>{this.state.title}</h1>
|
||||
<h5 style={{ 'lineHeight':'0px' }} id='author'> By {this.state.author} • {this.state.date}</h5>
|
||||
<img draggable='false' src={this.state.image} alt='Update'></img>
|
||||
<h5 style={{ 'lineHeight': '0px' }}>{this.state.date}</h5>
|
||||
{this.state.image ? <img draggable='false' src={this.state.image} alt='Update'></img> : null}
|
||||
<p dangerouslySetInnerHTML={{ __html: this.state.html }}></p>
|
||||
</div>;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import React from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import Checkbox from '../Checkbox';
|
||||
import Dropdown from '../Dropdown';
|
||||
import Section from '../Section';
|
||||
import FileUpload from '../FileUpload';
|
||||
|
||||
import { ColorPicker } from 'react-color-gradient-picker';
|
||||
import hexToRgb from '../../../../modules/helpers/background/hexToRgb';
|
||||
import rgbToHex from '../../../../modules/helpers/background/rgbToHex';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
import { Beforeunload } from 'react-beforeunload';
|
||||
|
||||
import 'react-color-gradient-picker/dist/index.css';
|
||||
|
||||
41
src/components/widgets/Widgets.jsx
Normal file
41
src/components/widgets/Widgets.jsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
|
||||
import Clock from './time/Clock';
|
||||
import Greeting from './greeting/Greeting';
|
||||
import Quote from './quote/Quote';
|
||||
import Search from './search/Search';
|
||||
import Maximise from './background/Maximise';
|
||||
import Favourite from './background/Favourite';
|
||||
import Date from './time/Date';
|
||||
|
||||
export default class Widgets extends React.PureComponent {
|
||||
enabled(key) {
|
||||
const old = localStorage.getItem(key);
|
||||
let val = true;
|
||||
|
||||
if (old !== null) {
|
||||
if (old === 'true') val = true;
|
||||
if (old === 'false') val = false;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// Render all the components
|
||||
render() {
|
||||
const { language, languagecode } = this.props;
|
||||
const enabled = this.enabled;
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{enabled('searchBar') ? <Search language={language.search} /> : null}
|
||||
{enabled('greeting') ? <Greeting language={language.greeting} /> : null}
|
||||
{enabled('clock') ? <Clock/> : null}
|
||||
{enabled('date') ? <Date/> : null}
|
||||
{enabled('quote') ? <Quote language={language.toasts} languagecode={languagecode} /> : null}
|
||||
{enabled('view') ? <Maximise/> : null}
|
||||
{enabled('favouriteEnabled') ? <Favourite/> : null}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,16 @@ export default class Favourite extends React.PureComponent {
|
||||
const url = document.getElementById('backgroundImage').style.backgroundImage.replace('url("', '').replace('")', '');
|
||||
const credit = document.getElementById('credit').textContent;
|
||||
const location = document.getElementById('location').textContent;
|
||||
|
||||
localStorage.setItem('favourite', JSON.stringify({ url: url, credit: credit, location: location }));
|
||||
this.setState({ favourited: <StarIcon onClick={() => this.favourite()} /> });
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('favourite')) this.setState({ favourited: <StarIcon onClick={() => this.favourite()} /> });
|
||||
if (localStorage.getItem('favourite')) {
|
||||
this.setState({ favourited: <StarIcon onClick={() => this.favourite()} /> });
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -36,7 +36,7 @@ export default class View extends React.PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
if (localStorage.getItem('view') === 'false' || localStorage.getItem('background') === 'false') return null;
|
||||
if (localStorage.getItem('background') === 'false') return null;
|
||||
return <div className='view'>
|
||||
<FullscreenIcon onClick={() => this.viewStuff()} />
|
||||
</div>
|
||||
|
||||
@@ -7,14 +7,11 @@ import Photographer from '@material-ui/icons/Person';
|
||||
|
||||
export default class PhotoInformation extends React.PureComponent {
|
||||
render() {
|
||||
let classList = 'infoCard';
|
||||
if (this.props.className) classList = this.props.className;
|
||||
|
||||
return (
|
||||
<div className='photoInformation'>
|
||||
<h1 id='photographer'>{this.props.language.credit}</h1>
|
||||
<Info className='photoInformationHover'/>
|
||||
<div className={classList}>
|
||||
<div className={this.props.className || 'infoCard'}>
|
||||
<Info className='infoIcon'/>
|
||||
<h1>{this.props.language.information}</h1>
|
||||
<hr/>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
float: left;
|
||||
margin-right: 1rem;
|
||||
font-size: calc(10px + 2vmin);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
svg,
|
||||
@@ -72,10 +73,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.photoInformationHover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dark hr {
|
||||
background-color: white !important;
|
||||
}
|
||||
@@ -56,7 +56,6 @@ export default class Greeting extends React.PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('greeting') === 'false') return;
|
||||
this.getGreeting();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from 'react';
|
||||
|
||||
import RefreshIcon from '@material-ui/icons/RefreshRounded';
|
||||
import Gear from '@material-ui/icons/SettingsRounded';
|
||||
import NewReleases from '@material-ui/icons/NewReleasesRounded';
|
||||
import NotesIcon from '@material-ui/icons/AssignmentRounded';
|
||||
import Tooltip from '@material-ui/core/Tooltip';
|
||||
import Report from '@material-ui/icons/SmsFailed';
|
||||
|
||||
import * as Constants from '../../../modules/constants';
|
||||
|
||||
import './scss/index.scss';
|
||||
@@ -20,6 +22,7 @@ export default class Navbar extends React.PureComponent {
|
||||
<RefreshIcon className='refreshicon topicons' onClick={() => window.location.reload()} />
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
if (localStorage.getItem('refresh') === 'false') refreshHTML = null;
|
||||
|
||||
// toggle feedback button
|
||||
@@ -28,6 +31,7 @@ export default class Navbar extends React.PureComponent {
|
||||
<Report className='topicons' onClick={this.props.feedbackModalOpen} />
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
if (Constants.BETA_VERSION === false) feedbackHTML = null;
|
||||
|
||||
return (
|
||||
|
||||
@@ -23,12 +23,15 @@ export default class Notes extends React.PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('notesPinned') === 'true') document.getElementById('noteContainer').classList.toggle('visibilityshow');
|
||||
if (localStorage.getItem('notesPinned') === 'true') {
|
||||
document.getElementById('noteContainer').classList.toggle('visibilityshow');
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let classList = 'notescontainer';
|
||||
if (localStorage.getItem('darkTheme') === 'true') classList += ' dark';
|
||||
|
||||
return (
|
||||
<span id='noteContainer' className={classList}>
|
||||
<div className='topbarnotes'>
|
||||
|
||||
@@ -93,15 +93,12 @@ export default class Quote extends React.PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('quote') === 'false') return;
|
||||
if (localStorage.getItem('favouriteQuote')) this.setState({ favourited: <StarIcon className='copyButton' onClick={() => this.favourite()} /> });
|
||||
if (localStorage.getItem('favouriteQuoteEnabled') === 'false') this.setState({ favourited: null });
|
||||
this.getQuote();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (localStorage.getItem('quote') === 'false') return null;
|
||||
|
||||
let copy = <FileCopy className='copyButton' onClick={() => this.copyQuote()}></FileCopy>;
|
||||
if (localStorage.getItem('copyButton') === 'false') copy = null;
|
||||
|
||||
|
||||
@@ -18,13 +18,12 @@ export default class Search extends React.PureComponent {
|
||||
startSpeechRecognition() {
|
||||
const voiceSearch = new window.webkitSpeechRecognition();
|
||||
voiceSearch.start();
|
||||
voiceSearch.onresult = (event) => document.getElementById('searchtext').value = event.results[0][0].transcript;
|
||||
voiceSearch.onend = () => setTimeout(() => window.location.href = this.state.url + `?${this.state.query}=` + document.getElementById('searchtext').value, 1000);
|
||||
const searchText = document.getElementById('searchtext');
|
||||
voiceSearch.onresult = (event) => searchText.value = event.results[0][0].transcript;
|
||||
voiceSearch.onend = () => setTimeout(() => window.location.href = this.state.url + `?${this.state.query}=` + searchText.value, 1000);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (localStorage.getItem('searchBar') === 'false') return null;
|
||||
|
||||
let url;
|
||||
let query = 'q';
|
||||
|
||||
@@ -52,8 +51,8 @@ export default class Search extends React.PureComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<div id='searchBar' className='searchbar'>
|
||||
<form id='searchBar' className='searchbarform' action={url}>
|
||||
<div id='searchBar'>
|
||||
<form action={url}>
|
||||
{microphone}
|
||||
<SearchIcon onClick={() => searchButton()} id='searchButton' />
|
||||
<input type='text' placeholder={this.props.language} name={query} id='searchtext' className='searchtext'/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@import '../../../scss/variables';
|
||||
|
||||
.searchbar {
|
||||
#searchBar {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
|
||||
@@ -22,8 +22,10 @@ export default class Clock extends React.PureComponent {
|
||||
if (localStorage.getItem('percentageComplete') === 'true') return this.setState({ time: (now.getHours() / 24).toFixed(2).replace('0.', '') + '%'});
|
||||
|
||||
// Analog clock
|
||||
if (localStorage.getItem('analog') === 'true') this.setState({ time: now });
|
||||
else {
|
||||
if (localStorage.getItem('analog') === 'true') {
|
||||
require('react-clock/dist/Clock.css');
|
||||
this.setState({ time: now });
|
||||
} else {
|
||||
let time, sec = '';
|
||||
|
||||
// Extra 0
|
||||
|
||||
@@ -11,6 +11,7 @@ export default class DateWidget extends React.PureComponent {
|
||||
|
||||
getDate() {
|
||||
const date = new Date();
|
||||
|
||||
const short = localStorage.getItem('short');
|
||||
const dateFormat = localStorage.getItem('dateFormat');
|
||||
|
||||
@@ -54,7 +55,6 @@ export default class DateWidget extends React.PureComponent {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (localStorage.getItem('date') === 'false') return;
|
||||
this.getDate();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
|
||||
import './scss/index.scss';
|
||||
import 'react-clock/dist/Clock.css';
|
||||
import 'react-toastify/dist/ReactToastify.css'; // the toast css is based on default so we need to import it
|
||||
|
||||
import 'fontsource-lexend-deca/latin-400-normal.css';
|
||||
|
||||
@@ -48,9 +48,11 @@ export default class SettingsFunctions {
|
||||
|
||||
static saveStuff(hexDisabled) {
|
||||
localStorage.setItem('customcss', document.getElementById('customcss').value);
|
||||
|
||||
if (document.getElementById('customBackgroundHex').value !== hexDisabled) {
|
||||
localStorage.setItem('customBackgroundColour', document.getElementById('customBackgroundHex').value);
|
||||
}
|
||||
|
||||
if (document.getElementById('searchEngineInput').enabled === 'true') {
|
||||
const input = document.getElementById('customSearchEngine').value;
|
||||
if (input) {
|
||||
@@ -58,6 +60,7 @@ export default class SettingsFunctions {
|
||||
localStorage.setItem('customSearchEngine', input);
|
||||
}
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
@@ -69,13 +72,10 @@ export default class SettingsFunctions {
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true);
|
||||
else localStorage.setItem('darkTheme', false);
|
||||
|
||||
// Webp support
|
||||
const supportsWebP = require('supports-webp'); // We import it here so it doesn't run the function on each page load
|
||||
if (supportsWebP) localStorage.setItem('supportswebp', 'true');
|
||||
|
||||
// Languages
|
||||
const languages = ['nl', 'no', 'fr', 'ru', 'es'];
|
||||
const browserLanguage = (navigator.languages && navigator.languages[0]) || navigator.language;
|
||||
|
||||
if (languages.includes(browserLanguage)) {
|
||||
localStorage.setItem('language', browserLanguage);
|
||||
document.documentElement.lang = browserLanguage;
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
background: none;
|
||||
border-radius: 24px;
|
||||
transition: ease 0.33s;
|
||||
border: 2px solid black;
|
||||
|
||||
&:hover {
|
||||
background: #2d3436;
|
||||
|
||||
Reference in New Issue
Block a user