Merge commit 'eeaf6784858888bce73c0d7750aba9720d6cf1aa'

This commit is contained in:
MrOnosa
2020-10-19 15:17:35 -05:00
60 changed files with 465 additions and 389 deletions

View File

@@ -2,7 +2,7 @@
All contributions are welcome! However, there are some things you need to take note of before starting your contribution to the Mue project.
## General
Test *everything*. That's right - make sure every feature still works depending on the change you just implemented. If it's a translation, check if all strings are translated.
Test *everything*. That's right - make sure every feature still works depending on the change you just implemented. If it's a translation, check if all strings are translated.
A bug fix? See if it has fixed the issue fully on both Chromium and Firefox. For features, make sure that everything else still works fine and is compatible with what you
implemented.
@@ -21,7 +21,7 @@ We prefer it if you implement features from our [projects board](https://github.
issue or our Discord server (see README for invite). Here's a quick list of things to look out for:
* External APIs - Please refrain from requesting to servers not on the ``muetab.xyz``, ``derpyenterprises.org`` or ``duckduckgo.com`` domains. Whenever possible, try to create
a "proxy" API service for requests to go through. Pull requests involving paid APIs or heavily limited free plans will be denied.
* Clones - Please don't go blatantly copying features from the alternative extensions out there unless you have written permission from the original author of the project.
* Clones - Please don't go blatantly copying features from the alternative extensions out there unless you have written permission from the original author of the project.
Inspired features are fine.
* Removed Features - If a feature has been removed by us don't add it back again without asking us about it first for the reasons as to why it was removed in the first place.

View File

@@ -1,7 +1,7 @@
<img src="https://raw.githubusercontent.com/mue/branding/master/logo/logo_round.png" align="left" width="180px" height="180px"/>
<img align="left" width="0" height="192px" hspace="10"/>
> <a href="https://muetab.xyz/">Mue</a>
> <a href="https://muetab.com/">Mue</a>
[![License](https://img.shields.io/badge/license-BSD%203-blue?style=flat-square)](/LICENSE) [![Discord](https://img.shields.io/discord/659129207208804381?label=discord&color=7289DA&style=flat-square)](https://discord.gg/zv8C9F8) [![Code Size]( https://img.shields.io/github/languages/code-size/mue/mue?color=green&label=size&style=flat-square)]()
<br>
@@ -44,10 +44,10 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
* Marketplace - download custom photo packs, quote packs, preset settings and themes made by the community!
### Planned Features
Please see our [roadmap](https://github.com/mue/mue/projects/2)
Please see our [roadmap](https://github.com/mue/mue/projects)
## Installation
*A demo of the tab can be found [here](https://demo.muetab.xyz)*
*A demo of the tab can be found [here](https://demo.muetab.com)*
### Chrome
[![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
<br>
@@ -132,11 +132,11 @@ Please see our [roadmap](https://github.com/mue/mue/projects/2)
### Translators
[Wessel Tip](https://github.com/Wessel) - Dutch
[Alex Sparkes](https://github.com/alexsparkes) - French
[Alex Sparkes](https://github.com/alexsparkes), [Maxime](https://github.com/exiam) - French
[Anders](https://github.com/FuryingFox) - Norwegian
[MrZillaGold](https://github.com/MrZillaGold) - Russian
[Pronin Egor](https://github.com/MrZillaGold) - Russian
### Other
[Pexels](https://pexels.com) - Stock photos used for offline mode

View File

@@ -3,7 +3,7 @@
"offline_enabled": true,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
"version": "4.1.1",
"version": "4.2.1",
"browser_action": {
"default_icon": "icons/128x128.png"
},

View File

@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
"version": "4.1.1",
"version": "4.2.1",
"browser_action": {
"default_icon": "icons/128x128.png"
},

View File

@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "Mue",
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
"version": "4.1.1",
"version": "4.2.0",
"browser_action": {
"default_icon": "icons/128x128.png"
},

View File

@@ -13,18 +13,18 @@
"homepage": "https://muetab.xyz",
"bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D",
"license": "BSD-3-Clause",
"version": "4.1.1",
"version": "4.2.1",
"dependencies": {
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/core": "4.11.0",
"@material-ui/icons": "4.9.1",
"@muetab/quotes": "^1.0.0",
"react": "^16.13.1",
"lodash.merge": "4.6.2",
"react": "16.14.0",
"react-clock": "^2.4.0",
"react-dom": "^16.13.1",
"react-modal": "^3.11.2",
"react-toastify": "^6.0.8",
"supports-webp": "^2.0.1",
"lodash.merge": "4.6.2"
"react-dom": "16.14.0",
"react-modal": "3.11.2",
"react-toastify": "6.0.9",
"supports-webp": "2.0.1"
},
"devDependencies": {
"react-scripts": "3.4.3",

View File

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 128 KiB

View File

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 200 KiB

View File

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 146 KiB

View File

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 230 KiB

View File

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 737 KiB

After

Width:  |  Height:  |  Size: 737 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 390 KiB

After

Width:  |  Height:  |  Size: 390 KiB

View File

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 225 KiB

View File

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 251 KiB

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

Before

Width:  |  Height:  |  Size: 300 KiB

After

Width:  |  Height:  |  Size: 300 KiB

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

Before

Width:  |  Height:  |  Size: 290 KiB

After

Width:  |  Height:  |  Size: 290 KiB

View File

Before

Width:  |  Height:  |  Size: 324 KiB

After

Width:  |  Height:  |  Size: 324 KiB

View File

Before

Width:  |  Height:  |  Size: 264 KiB

After

Width:  |  Height:  |  Size: 264 KiB

View File

Before

Width:  |  Height:  |  Size: 495 KiB

After

Width:  |  Height:  |  Size: 495 KiB

View File

Before

Width:  |  Height:  |  Size: 472 KiB

After

Width:  |  Height:  |  Size: 472 KiB

View File

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 280 KiB

View File

@@ -16,11 +16,9 @@ import Modal from 'react-modal';
import merge from 'lodash.merge';
import RoomIcon from '@material-ui/icons/Room';
// Modals are lazy loaded as a user won't use them every time they open a tab
const Settings = React.lazy(() => import('./components/modals/Settings'));
// Modals are lazy loaded as the user won't use them every time they open a tab
const MainModal = React.lazy(() => import('./components/modals/MainModal'));
const Update = React.lazy(() => import('./components/modals/Update'));
const Marketplace = React.lazy(() => import('./components/modals/Marketplace'));
const Addons = React.lazy(() => import('./components/modals/Addons'));
//const Welcome = React.lazy(() => import('./components/modals/Welcome'));
const renderLoader = () => <div></div>;
@@ -28,12 +26,8 @@ export default class App extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
settingsModal: false,
updateModal: false,
marketplaceModal: false,
addonsModal: false,
quickAccessmodal: false,
welcomeModal: false
mainModal: false,
updateModal: false
};
}
@@ -41,7 +35,12 @@ export default class App extends React.PureComponent {
render() {
if (!localStorage.getItem('firstRun')) SettingsFunctions.setDefaultSettings();
const modalClassList = (localStorage.getItem('darkTheme') === 'true') ? 'Modal dark' : 'Modal'; // Modal features
let modalClassList = 'Modal'; // Modal features
let tooltipClassList = 'tooltiptext';
if ((localStorage.getItem('brightnessTime') && new Date().getHours() > 18) || localStorage.getItem('darkTheme') === 'true') {
modalClassList = 'Modal dark';
tooltipClassList = 'tooltiptext dark';
}
const overlayClassList = (localStorage.getItem('animations') === 'true') ? 'Overlay modal-animation' : 'Overlay';
const en = require('./translations/en.json'); // User language
@@ -58,10 +57,10 @@ export default class App extends React.PureComponent {
return (
<React.Fragment>
<Background/>
<ToastContainer className='toast' position='bottom-right' autoClose={2500} hideProgressBar={false} newestOnTop={true} closeOnClick rtl={false} pauseOnFocusLoss />
<ToastContainer position='bottom-right' autoClose={2500} newestOnTop={true} closeOnClick rtl={false} pauseOnFocusLoss />
<div id='center'>
<Search language={language.search} />
<Navbar settingsModalOpen={() => this.setState({ settingsModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} />
<Navbar settingsModalOpen={() => this.setState({ mainModal: true })} updateModalOpen={() => this.setState({ updateModal: true })} />
<Greeting language={language.greeting} />
<Clock/>
<Quote language={language.toasts}/>
@@ -70,46 +69,22 @@ export default class App extends React.PureComponent {
<span id='credit' style={{'display': 'none'}}></span>
<div id='backgroundCredits' className='tooltip'>
<RoomIcon className='locationicon'/>
<span className='tooltiptext' id='location'/>
<span className={tooltipClassList} id='location'/>
</div>
</div>
<Maximise/>
<Favourite/>
<React.Suspense fallback={renderLoader()}>
<Modal id={'modal'} onRequestClose={() => this.setState({ settingsModal: false })} isOpen={this.state.settingsModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
<Settings
language={language.settings}
modalLanguage={language.modals}
modalClose={() => this.setState({ settingsModal: false })}
setDefaultSettings={() => SettingsFunctions.setDefaultSettings()}
openMarketplace={() => this.setState({ marketplaceModal: true, settingsModal: false })}
openAddons={() => this.setState({ settingsModal: false, addonsModal: true })}
toastLanguage={language.toasts} />
<Modal id={'modal'} onRequestClose={() => this.setState({ mainModal: false })} isOpen={this.state.mainModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
<MainModal
language={language}
modalClose={() => this.setState({ mainsModal: false })} />
</Modal>
<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>
<Modal onRequestClose={() => this.setState({ marketplaceModal: false })} isOpen={this.state.marketplaceModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
<Marketplace
language={language.marketplace}
modalLanguage={language.modals}
modalClose={() => this.setState({ marketplaceModal: false })}
openSettings={() => this.setState({ marketplaceModal: false, settingsModal: true })}
openAddons={() => this.setState({ marketplaceModal: false, addonsModal: true })}
toastLanguage={language.toasts} />
</Modal>
<Modal onRequestClose={() => this.setState({ addonsModal: false })} isOpen={this.state.addonsModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
<Addons
language={language.addons}
marketplaceLanguage={language.marketplace}
modalLanguage={language.modals}
modalClose={() => this.setState({ addonsModal: false })}
openSettings={() => this.setState({ addonsModal: false, settingsModal: true })}
openMarketplace={() => this.setState({ addonsModal: false, marketplaceModal: true })}
toastLanguage={language.toasts} />
</Modal>
{/* <Modal onRequestClose={() => this.setState({ welcomeModal: false })} isOpen={this.state.welcomeModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
<Welcome modalClose={() => this.setState({ welcomeModal: false })} />
</Modal> */ }

View File

@@ -0,0 +1,74 @@
import React from 'react';
import Settings from './tabs/Settings';
import Addons from './tabs/Addons';
import Marketplace from './tabs/Marketplace';
export default class MainModal extends React.PureComponent {
constructor(...args) {
super(...args);
this.state = {
tab: <Settings language={this.props.language.settings} toastLanguage={this.props.toastLanguage} />,
settingsActive: 'active',
addonsActive: '',
marketplaceActive: ''
};
}
componentDidMount() {
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
}
componentWillUnmount() {
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
}
changeEnabled(input) {
switch (input) {
case 'addons':
this.setState({
tab: <Addons language={this.props.language.addons} marketplaceLanguage={this.props.language.marketplace} toastLanguage={this.props.language.toasts} openMarketplace={() => this.changeEnabled('marketplace')}/>,
addonsActive: 'active',
settingsActive: '',
marketplaceActive: ''
});
break;
case 'settings':
this.setState({
tab: <Settings language={this.props.language.settings} toastLanguage={this.props.language.toasts}/>,
settingsActive: 'active',
addonsActive: '',
marketplaceActive: ''
});
break;
case 'marketplace':
this.setState({
tab: <Marketplace language={this.props.language.marketplace} toastLanguage={this.props.language.toasts} updateLanguage={this.props.language.update}/>,
marketplaceActive: 'active',
addonsActive: '',
settingsActive: ''
});
break;
default:
break;
}
}
render() {
return (
<div className='content'>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<h1>{this.props.language.modals.title}</h1>
<div className='tab'>
<button className='tablinks' id={this.state.marketplaceActive} onClick={() => this.changeEnabled('marketplace')}>{this.props.language.modals.marketplace}</button>
<button className='tablinks' id={this.state.addonsActive} onClick={() => this.changeEnabled('addons')}>{this.props.language.modals.addons}</button>
<button className='tablinks' id={this.state.settingsActive} onClick={() => this.changeEnabled('settings')}>{this.props.language.modals.settings}</button>
</div>
<br/>
{this.state.tab}
</div>
)
}
}

View File

@@ -2,8 +2,10 @@ import React from 'react';
export default class Items extends React.PureComponent {
render() {
if (this.props.items.length === 0) return null;
let seeMoreHTML;
if (this.props.seeMoreFunction) seeMoreHTML = <button className='addToMue seemore' onClick={this.props.seeMoreFunction}>{this.props.seeMoreTitle}</button>;
if (this.props.seeMoreFunction && this.props.items.length === 3) seeMoreHTML = <button className='addToMue seemore' onClick={this.props.seeMoreFunction}>{this.props.seeMoreTitle}</button>;
return (
<div>
@@ -11,7 +13,7 @@ export default class Items extends React.PureComponent {
<h1>{this.props.title}</h1>
<div className='items'>
{this.props.items.map((item) =>
<div className='item' onClick={() => this.props.toggleFunction(item.name)}>
<div className='item' onClick={() => this.props.toggleFunction(item.name)} key={item.name}>
<img alt='icon' draggable={false} src={'https://external-content.duckduckgo.com/iu/?u=' + item.icon_url} />
<div className='details'>
<h4>{item.display_name}</h4>

View File

@@ -17,11 +17,14 @@ export default class Checkbox extends React.PureComponent {
}
render() {
let text = this.props.text;
if (this.props.newFeature) text = <span>{this.props.text} <span className='newFeature'> NEW</span></span>;
return (
<React.Fragment>
<FormControlLabel
control={<CheckboxUI name='checkedB' color='primary' checked={this.state.checked} onChange={() => this.handleChange(this.props.name)} />}
label={this.props.text}
label={text}
/>
<br/>
</React.Fragment>

View File

@@ -22,7 +22,7 @@ export default class Section extends React.PureComponent {
}
render() {
let extraHTML, expandMore, slider;
let extraHTML, expandMore, slider, noDropdown;
if (this.props.children) {
extraHTML = <li className='extraSettings'>{this.props.children}</li>
expandMore = <ExpandMore
@@ -33,10 +33,11 @@ export default class Section extends React.PureComponent {
}
if (this.props.slider !== false) slider = <Slider name={this.props.name} />;
if (this.props.noDropdown) noDropdown = 'nodropdown';
return (
<div className='section'>
<h4 onClick={() => this.toggleSection()}>{this.props.title}</h4>
<h4 className={noDropdown} onClick={() => this.toggleSection()}>{this.props.title}</h4>
{expandMore}
{slider}
<div style={{display: this.state.display}}>

View File

@@ -1,8 +1,10 @@
import React from 'react';
import { toast } from 'react-toastify';
import Checkbox from '../Checkbox';
import Section from '../Section';
export default class BackgroundSettings extends React.PureComponent {
DefaultGradientSettings = { "angle": "180", "gradient": [{ "colour": "Disabled", "stop": 0 }], "type": "linear" };
DefaultGradientSettings = { "angle": "180", "gradient": [{ "colour": this.props.language.background.disabled, "stop": 0 }], "type": "linear" };
constructor(...args) {
super(...args);
@@ -117,14 +119,14 @@ export default class BackgroundSettings extends React.PureComponent {
}
currentGradientSettings = () => {
if (typeof this.state.gradientSettings === 'object' && this.state.gradientSettings.gradient.every(g => g.colour !== 'Disabled')) {
if (typeof this.state.gradientSettings === 'object' && this.state.gradientSettings.gradient.every(g => g.colour !== this.props.language.background.disabled)) {
const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
return JSON.stringify({
...this.state.gradientSettings,
gradient: [...this.state.gradientSettings.gradient.map(g => { return { ...g, stop: clampNumber(+g.stop, 0, 100) } })].sort((a, b) => (a.stop > b.stop) ? 1 : -1)
});
}
return 'Disabled';
return this.props.language.background.disabled;
}
render() {
@@ -145,44 +147,51 @@ export default class BackgroundSettings extends React.PureComponent {
colourSettings = (
<div>
{gradientInputs}
{this.state.gradientSettings.gradient[0].colour !== 'Disabled' ? (<button type="button" className="add" onClick={this.addColour}>{this.props.language.background.addColour}</button>) : null}
{this.state.gradientSettings.gradient[0].colour !== this.props.language.background.disabled ? (<button type="button" className="add" onClick={this.addColour}>{this.props.language.background.addcolour}</button>) : null}
</div>);
}
return (
<div>
<ul>
<label htmlFor='backgroundapi'>{this.props.language.background.API} </label>
<label className='dropdown'>
<select className='select-css' name='backgroundapi' id='backgroundAPI' onChange={() => localStorage.setItem('backgroundAPI', document.getElementById('backgroundAPI').value)}>
<option className='choices' value='mue'>Mue</option>
<option className='choices' value='unsplash'>Unsplash</option>
</select>
</label>
</ul>
<ul>
<p>{this.props.language.background.blur} ({this.state.blur}%) <span className='modalLink' onClick={() => this.resetItem('blur')}>{this.props.language.reset}</span></p>
<input className='range' type='range' min='0' max='100' id='blurRange' value={this.state.blur} onChange={(event) => this.setState({ blur: event.target.value })} />
</ul>
<ul>
<p>{this.props.language.background.brightness} ({this.state.brightness}%) <span className='modalLink' onClick={() => this.resetItem('brightness')}>{this.props.language.reset}</span></p>
<input className='range' type='range' min='0' max='100' id='brightnessRange' value={this.state.brightness} onChange={(event) => this.setState({ brightness: event.target.value })} />
</ul>
<ul>
<p>{this.props.language.background.customURL} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>{this.props.language.reset}</span></p>
<input type='text' id='customBackground'></input>
</ul>
<ul>
<p>{this.props.language.background.custombackground} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>{this.props.language.reset}</span></p>
<button className='uploadbg' onClick={() => document.getElementById('bg-input').click()}>{this.props.language.background.upload}</button>
<input id='bg-input' type='file' name='name' className='hidden' accept='image/jpeg, image/png, image/webp, image/webm, image/gif' />
</ul>
<ul>
<p>{this.props.language.background.customcolour} <span className='modalLink' onClick={() => this.resetItem('customBackgroundColour')}>{this.props.language.reset}</span></p>
<input id='customBackgroundHex' type='hidden' value={this.currentGradientSettings()} />
{colourSettings}
</ul>
</div>
<React.Fragment>
<Section title={this.props.language.background.title} name='background'>
<ul>
<Checkbox name='view' text={this.props.language.background.view} />
<Checkbox name='favouriteEnabled' text={this.props.language.background.favourite} />
<Checkbox name='refresh' text={this.props.language.background.refresh} />
</ul>
<ul>
<label htmlFor='backgroundapi'>{this.props.language.background.API} </label>
<label className='dropdown'>
<select className='select-css' name='backgroundapi' id='backgroundAPI' onChange={() => localStorage.setItem('backgroundAPI', document.getElementById('backgroundAPI').value)}>
<option className='choices' value='mue'>Mue</option>
<option className='choices' value='unsplash'>Unsplash</option>
</select>
</label>
</ul>
<ul>
<p>{this.props.language.background.blur} ({this.state.blur}%) <span className='modalLink' onClick={() => this.resetItem('blur')}>{this.props.language.reset}</span></p>
<input className='range' type='range' min='0' max='100' id='blurRange' value={this.state.blur} onChange={(event) => this.setState({ blur: event.target.value })} />
</ul>
<ul>
<p>{this.props.language.background.brightness} ({this.state.brightness}%) <span className='modalLink' onClick={() => this.resetItem('brightness')}>{this.props.language.reset}</span></p>
<input className='range' type='range' min='0' max='100' id='brightnessRange' value={this.state.brightness} onChange={(event) => this.setState({ brightness: event.target.value })} />
</ul>
<ul>
<p>{this.props.language.background.customURL} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>{this.props.language.reset}</span></p>
<input type='text' id='customBackground'></input>
</ul>
<ul>
<p>{this.props.language.background.custombackground} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>{this.props.language.reset}</span></p>
<button className='uploadbg' onClick={() => document.getElementById('bg-input').click()}>{this.props.language.background.upload}</button>
<input id='bg-input' type='file' name='name' className='hidden' accept='image/jpeg, image/png, image/webp, image/webm, image/gif' />
</ul>
<ul>
<p>{this.props.language.background.customcolour} <span className='modalLink' onClick={() => this.resetItem('customBackgroundColour')}>{this.props.language.reset}</span></p>
<input id='customBackgroundHex' type='hidden' value={this.currentGradientSettings()} />
{colourSettings}
</ul>
</Section>
</React.Fragment>
);
}
}

View File

@@ -4,7 +4,7 @@ export default class LanguageSettings extends React.PureComponent {
render() {
return (
<div className='section'>
<h4 htmlFor='language'>{this.props.language.language}</h4>
<h4 htmlFor='language' className='nodropdown'>{this.props.language.language}</h4>
<select className='select-css' name='language' id='language' onChange={() => localStorage.setItem('language', document.getElementById('language').value)}>
<option className='choices' value='en'>English</option>
<option className='choices' value='nl'>Nederlands</option>

View File

@@ -1,6 +1,7 @@
import React from 'react';
import SettingsFunctions from '../../../../modules/settingsFunctions';
import { toast } from 'react-toastify';
import Section from '../Section';
const searchEngines = require('../../../../modules/searchEngines.json');
@@ -24,21 +25,23 @@ export default class SearchSettings extends React.PureComponent {
render() {
return (
<div>
<ul>
<label htmlFor='searchEngine'>{this.props.language.searchbar.searchengine} </label>
<select className='select-css' name='searchEngine' id='searchEngine' onChange={() => SettingsFunctions.setSearchEngine(document.getElementById('searchEngine').value)}>
{searchEngines.map((engine) =>
<option key={engine.name} className='choices' value={engine.settingsName}>{engine.name}</option>
)}
<option className='choices' value='custom'>Custom</option>
</select>
</ul>
<ul id='searchEngineInput' style={{ display: 'none' }}>
<p style={{"marginTop": "0px"}}>{this.props.language.searchbar.custom} <span className='modalLink' onClick={() => this.resetSearch()}>{this.props.language.reset}</span></p>
<input type='text' id='customSearchEngine'></input>
</ul>
</div>
<React.Fragment>
<Section title={this.props.language.searchbar.title} name='searchBar'>
<ul>
<label htmlFor='searchEngine'>{this.props.language.searchbar.searchengine} </label>
<select className='select-css' name='searchEngine' id='searchEngine' onChange={() => SettingsFunctions.setSearchEngine(document.getElementById('searchEngine').value)}>
{searchEngines.map((engine) =>
<option key={engine.name} className='choices' value={engine.settingsName}>{engine.name}</option>
)}
<option className='choices' value='custom'>Custom</option>
</select>
</ul>
<ul id='searchEngineInput' style={{ display: 'none' }}>
<p style={{"marginTop": "0px"}}>{this.props.language.searchbar.custom} <span className='modalLink' onClick={() => this.resetSearch()}>{this.props.language.reset}</span></p>
<input type='text' id='customSearchEngine'></input>
</ul>
</Section>
</React.Fragment>
);
}
}

View File

@@ -1,8 +1,8 @@
import React from 'react';
import LocalMallIcon from '@material-ui/icons/LocalMall';
import { toast } from 'react-toastify';
import Item from './marketplace/Item';
import MarketplaceFunctions from '../../modules/marketplaceFunctions';
import Item from '../marketplace/Item';
import MarketplaceFunctions from '../../../modules/marketplaceFunctions';
export default class Addons extends React.PureComponent {
constructor(...args) {
@@ -136,16 +136,9 @@ export default class Addons extends React.PureComponent {
};
};
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
this.setState({ installed: JSON.parse(localStorage.getItem('installed')) });
}
componentWillUnmount() {
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
}
render() {
let content = <div className='items'>
{this.state.installed.map((item) =>
@@ -169,21 +162,16 @@ export default class Addons extends React.PureComponent {
</div>;
}
return <div className='content'>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<h1>{this.props.modalLanguage.title}</h1>
<div className='tab'>
<button className='tablinks' onClick={this.props.openMarketplace}>{this.props.modalLanguage.marketplace}</button>
<button className='tablinks' id='active'>{this.props.modalLanguage.addons}</button>
<button className='tablinks' onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
</div>
<div id='marketplace'>
<input id='file-input' type='file' name='name' className='hidden' />
<button className='addToMue sideload' onClick={() => document.getElementById('file-input').click()}>{this.props.language.sideload}</button>
<h1>{this.props.language.added}</h1>
{content}
</div>
<Item button={this.state.button} data={this.state.item_data} function={() => this.toggle()} language={this.props.marketplaceLanguage.product} />
</div>;
return (
<div>
<div id='marketplace'>
<input id='file-input' type='file' name='name' className='hidden' />
<button className='addToMue sideload' onClick={() => document.getElementById('file-input').click()}>{this.props.language.sideload}</button>
<h1>{this.props.language.added}</h1>
{content}
</div>
<Item button={this.state.button} data={this.state.item_data} function={() => this.toggle()} language={this.props.marketplaceLanguage.product} />
</div>
);
}
}

View File

@@ -2,10 +2,10 @@ import React from 'react';
import WifiOffIcon from '@material-ui/icons/WifiOff';
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
import { toast } from 'react-toastify';
import Item from './marketplace/Item';
import MarketplaceFunctions from '../../modules/marketplaceFunctions';
import * as Constants from '../../modules/constants';
import Items from './marketplace/Items';
import Item from '../marketplace/Item';
import MarketplaceFunctions from '../../../modules/marketplaceFunctions';
import * as Constants from '../../../modules/constants';
import Items from '../marketplace/Items';
export default class Marketplace extends React.PureComponent {
constructor(...args) {
@@ -35,22 +35,12 @@ export default class Marketplace extends React.PureComponent {
}
}
this.offlineHTML = <div className='content'>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<h1>{this.props.modalLanguage.title}</h1>
<div className='tab'>
<button className='tablinks' id='active'>{this.props.modalLanguage.marketplace}</button>
<button className='tablinks' onClick={this.props.openAddons}>{this.props.modalLanguage.addons}</button>
<button className='tablinks'
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
</div>
<div id='marketplace'>
this.offlineHTML = <div id='marketplace'>
<div className='emptyMessage' style={{'marginTop': '20px', 'transform': 'translateY(80%)'}}>
<WifiOffIcon />
<h1>{this.props.language.offline.title}</h1>
<p className='description'>{this.props.language.offline.description}</p>
</div>
</div>
</div>;
}
@@ -161,51 +151,29 @@ export default class Marketplace extends React.PureComponent {
}
componentDidMount() {
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
if (navigator.onLine === false) return;
this.getItems();
}
componentWillUnmount() {
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
}
render() {
if (navigator.onLine === false) return this.offlineHTML;
if (this.state.done === false) {
return <div className='content'>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<h1>{this.props.modalLanguage.title}</h1>
<div className='tab'>
<button className='tablinks' id='active'>{this.props.modalLanguage.marketplace}</button>
<button className='tablinks' onClick={this.props.openAddons}>{this.props.modalLanguage.addons}</button>
<button className='tablinks'
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
</div>
<div id='marketplace'>
return (
<div id='marketplace'>
<div className='emptyMessage' style={{'marginTop': '20px', 'transform': 'translateY(80%)'}}>
<h1>Loading...</h1>
<h1>{this.props.updateLanguage.loading}</h1>
</div>
</div>
</div>;
</div>
)
}
return <div className='content'>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<h1>{this.props.modalLanguage.title}</h1>
<div className='tab'>
<button className='tablinks' id='active'>{this.props.modalLanguage.marketplace}</button>
<button className='tablinks' onClick={this.props.openAddons}>{this.props.modalLanguage.addons}</button>
<button className='tablinks'
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
</div>
<div id='marketplace'>
return (
<div>
<div id='marketplace'>
<div className='featured' style={{backgroundColor: this.state.featured.colour}}>
<p>{this.state.featured.title}</p>
<h1>{this.state.featured.name}</h1>
<button className='addToMue' onClick={() => window.location.href = this.state.featured.buttonLink}>{this.state.featured.buttonText}</button>
<p>{this.state.featured.title}</p>
<h1>{this.state.featured.name}</h1>
<button className='addToMue' onClick={() => window.location.href = this.state.featured.buttonLink}>{this.state.featured.buttonText}</button>
</div>
<Items
title={this.props.language.photo_packs}
@@ -225,12 +193,12 @@ export default class Marketplace extends React.PureComponent {
items={this.state.quote_packs.slice(0, 3)}
toggleFunction={(input) => this.toggle('item', 'quote_packs', input)}
seeMoreFunction={() => this.toggle('seemore', 'quote_packs')} />
<Items
{/* <Items
title={this.props.language.themes}
seeMoreTitle={this.props.language.see_more}
items={this.state.themes.slice(0, 3)}
toggleFunction={(input) => this.toggle('item', 'theme', input)}
seeMoreFunction={() => this.toggle('seemore', 'themes')} />
seeMoreFunction={() => this.toggle('seemore', 'themes')} /> */ }
</div>
<Item
button={this.state.button}
@@ -247,6 +215,7 @@ export default class Marketplace extends React.PureComponent {
items={this.state.see_more}
/>
</div>
</div>;
</div>
)
}
}

View File

@@ -1,13 +1,12 @@
import React from 'react';
import SettingsFunctions from '../../modules/settingsFunctions';
import Checkbox from './settings/Checkbox';
import Slider from './settings/Slider';
import Section from './settings/Section';
import SettingsFunctions from '../../../modules/settingsFunctions';
import Checkbox from '../settings/Checkbox';
import Section from '../settings/Section';
import { toast } from 'react-toastify';
import BackgroundSettings from './settings/sections/BackgroundSettings';
import SearchSettings from './settings/sections/SearchSettings';
import LanguageSettings from './settings/sections/LanguageSettings';
import BackgroundSettings from '../settings/sections/BackgroundSettings';
import SearchSettings from '../settings/sections/SearchSettings';
import LanguageSettings from '../settings/sections/LanguageSettings';
export default class Settings extends React.PureComponent {
resetGreeting() {
@@ -15,20 +14,17 @@ export default class Settings extends React.PureComponent {
toast(this.props.toastLanguage.reset);
}
updateCurrent() {
componentDidMount() {
// Settings
document.getElementById('greetingName').value = localStorage.getItem('greetingName');
document.getElementById('language').value = localStorage.getItem('language');
if (localStorage.getItem('darkTheme') === 'true') {
if (document.getElementById('modal').classList.contains('dark')) { // Dark theme support for dropdowns
const choices = document.getElementsByClassName('choices');
for (let i = 0; i < choices.length; i++) choices[i].style.backgroundColor = '#2f3542';
}
}
componentDidMount() {
this.updateCurrent();
document.getElementById('file-input').onchange = (e) => {
document.getElementById('file-input').onchange = (e) => { // import settings
const file = e.target.files[0];
if (file.type !== 'application/json') return console.error(`expected json, got ${file.type}`);
@@ -41,28 +37,10 @@ export default class Settings extends React.PureComponent {
toast(this.props.toastLanguage.imported);
};
};
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
document.getElementById('center').classList.toggle('backgroundEffects');
}
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}>&times;</span>
<h1>{this.props.modalLanguage.title}</h1>
<div className='tab'>
<button className='tablinks' onClick={this.props.openMarketplace}>{this.props.modalLanguage.marketplace}</button>
<button className='tablinks' onClick={this.props.openAddons}>{this.props.modalLanguage.addons}</button>
<button className='tablinks' id='active'>{this.props.modalLanguage.settings}</button>
</div>
<br/>
<div className='columns'>
<Section title={this.props.language.time.title} name='time'>
<Checkbox name='seconds' text={this.props.language.time.seconds} />
@@ -71,6 +49,7 @@ export default class Settings extends React.PureComponent {
<Checkbox name='zero' text={this.props.language.time.zero} />
<Checkbox name='analog' text={this.props.language.time.analog} />
</Section>
<Section title={this.props.language.greeting.title} name='greeting'>
<Checkbox name='events' text={this.props.language.greeting.events} />
<Checkbox name='defaultGreetingMessage' text={this.props.language.greeting.default} />
@@ -79,40 +58,35 @@ export default class Settings extends React.PureComponent {
<input type='text' id='greetingName'></input>
</ul>
</Section>
<Section title={this.props.language.quote.title} name='quote'>
<Checkbox name='copyButton' text={this.props.language.quote.copy} />
<Checkbox name='tweetButton' text={this.props.language.quote.tweet} />
<Checkbox name='favouriteQuoteEnabled' text={this.props.language.quote.favourite} />
</Section>
<Section title={this.props.language.background.title} name='background'>
<BackgroundSettings language={this.props.language} toastLanguage={this.props.toastLanguage} />
</Section>
<Section title={this.props.language.searchbar.title} name='searchBar'>
<SearchSettings language={this.props.language} toastLanguage={this.props.toastLanguage} />
</Section>
<div className='section'>
<h4 className='nodropdown'>{this.props.language.offline}</h4>
<Slider name='offlineMode'/>
</div>
<div className='section'>
<h4 className='nodropdown'>{this.props.language.experimental.dark}</h4>
<Slider name='darkTheme'/>
</div>
<BackgroundSettings language={this.props.language} toastLanguage={this.props.toastLanguage} />
<SearchSettings language={this.props.language} toastLanguage={this.props.toastLanguage} />
<Section title={this.props.language.offline} name='offlineMode' noDropdown={true} />
<Section title={this.props.language.dark} name='darkTheme' noDropdown={true} />
<Section title={this.props.language.experimental.title} name='experimental' slider={false}>
<Checkbox name='webp' text={this.props.language.experimental.webp} />
<Checkbox name='animations' text={this.props.language.experimental.animations} />
<Checkbox name='view' text={this.props.language.experimental.view} />
<Checkbox name='favouriteEnabled' text={this.props.language.experimental.favourite} />
<Checkbox name='refresh' text={this.props.language.experimental.refresh} />
<Checkbox name='voiceSearch' text={this.props.language.experimental.voicesearch} newFeature={true} />
<Checkbox name='brightnessTime' text={this.props.language.experimental.nightmode} newFeature={true} />
</Section>
<LanguageSettings language={this.props.language} />
<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='apply' onClick={() => SettingsFunctions.saveStuff(this.props.language.background.disabled)}>{this.props.language.apply}</button>
<button className='reset' onClick={() => SettingsFunctions.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' accept='application/json' />
</div>
</div>
);
}
}

View File

@@ -25,12 +25,13 @@ export default class Background extends React.PureComponent {
localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings));
}
}
const background = typeof gradientSettings === 'object' && gradientSettings !== null ? this.gradientStyleBuilder(gradientSettings) : `background-image: url(${url});`;
const background = typeof gradientSettings === 'object' && gradientSettings !== null ? this.gradientStyleBuilder(gradientSettings) : `background-image: url(${url})`;
let brightness = localStorage.getItem('brightness');
if (localStorage.getItem('brightnessTime') && new Date().getHours() > 18) brightness = 75;
document.querySelector('#backgroundImage').setAttribute(
'style',
`${background};
-webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${localStorage.getItem('brightness')}%);`
`${background}; -webkit-filter: blur(${localStorage.getItem('blur')}px) brightness(${brightness}%);`
);
if (credit === 'false') document.querySelector('#credits').style.display = 'none'; // Hide the credit
@@ -40,6 +41,7 @@ export default class Background extends React.PureComponent {
let credit = photographer;
if (unsplash) credit = `<a href='${url}' class='creditlink'>${photographer}</a> on <a href='https://unsplash.com/?utm_source=mue&utm_medium=referral' class='creditlink'>Unsplash</a>`;
document.querySelector('#photographer').insertAdjacentHTML("beforeend", ` ${credit}`); // Append credit
document.getElementById('credit').textContent = credit;
}
doOffline() { // Handles setting the background if the user is offline
@@ -49,7 +51,7 @@ export default class Background extends React.PureComponent {
const randomImage = offlineImages[photographer].photo[
Math.floor(Math.random() * offlineImages[photographer].photo.length)
]; // Select a random image
const url = `../offline-images/${randomImage}.jpeg`;
const url = `../offline-images/${randomImage}.jpg`;
this.setBackground(url);
this.setCredit(photographer);

View File

@@ -65,8 +65,11 @@ export default class Clock extends React.PureComponent {
}
render() {
if (localStorage.getItem('time') === 'false') return null;
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;
}
}

View File

@@ -28,7 +28,7 @@ export default class Favourite extends React.PureComponent {
}
render() {
if (localStorage.getItem('favouriteEnabled') === 'false') return null;
if (localStorage.getItem('favouriteEnabled') === 'false' || localStorage.getItem('background') === 'false' || localStorage.getItem('customBackgroundColour') || localStorage.getItem('customBackground')) return null;
return <div className='favourite'>
{this.state.favourited}
</div>

View File

@@ -6,7 +6,7 @@ export default class Greeting extends React.PureComponent {
this.state = {
greeting: ''
};
}
}
doEvents(time, message) {
if (localStorage.getItem('events') === 'false') return message;
@@ -15,9 +15,9 @@ export default class Greeting extends React.PureComponent {
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"
if (m === 11 && d === 25) message = this.props.language.christmas; // If it's December 25th, set the greeting string to "Merry Christmas"
else if (m === 0 && d === 1) message = this.props.language.newyear; // If the date is January 1st, set the greeting string to "Happy new year"
else if (m === 9 && d === 31) message = this.props.language.halloween; // If it's October 31st, set the greeting string to "Happy Halloween"
return message;
}

View File

@@ -12,9 +12,7 @@ export default class View extends React.PureComponent {
setAttribute(blur, brightness) {
document.querySelector('#backgroundImage').setAttribute(
'style',
`background-image: url(${document.getElementById('backgroundImage').style.backgroundImage.replace('url("', '').replace('")', '')});
-webkit-filter: blur(${blur});
-webkit-filter: brightness(${brightness}%);`
`background-image: url(${document.getElementById('backgroundImage').style.backgroundImage.replace('url("', '').replace('")', '')}); -webkit-filter: blur(${blur}); -webkit-filter: brightness(${brightness}%);`
);
}
@@ -27,6 +25,7 @@ export default class View extends React.PureComponent {
return;
}
});
if (this.state.hidden === false) {
this.setState({ hidden: true });
this.setAttribute(0, 100);
@@ -37,7 +36,7 @@ export default class View extends React.PureComponent {
}
render() {
if (localStorage.getItem('view') === 'false') return null;
if (localStorage.getItem('view') === 'false' || localStorage.getItem('background') === 'false') return null;
return <div className='view'>
<FullscreenIcon id='viewButton' onClick={() => this.viewStuff()} />
</div>

View File

@@ -4,13 +4,16 @@ import FileCopy from '@material-ui/icons/FilterNone';
import { toast } from 'react-toastify';
import * as Constants from '../../modules/constants';
import TwitterIcon from '@material-ui/icons/Twitter';
import StarIcon from '@material-ui/icons/Star';
import StarIcon2 from '@material-ui/icons/StarBorder';
export default class Quote extends React.PureComponent {
constructor(...args) {
super(...args);
this.state = {
quote: '',
author: ''
author: '',
favourited: <StarIcon2 className='copyButton' onClick={() => this.favourite()} />
};
}
@@ -51,6 +54,12 @@ export default class Quote extends React.PureComponent {
}
}
const favouriteQuote = localStorage.getItem('favouriteQuote');
if (favouriteQuote) return this.setState({
quote: favouriteQuote.split(' - ')[0],
author: favouriteQuote.split(' - ')[1]
});
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
try { // First we try and get a quote from the API...
@@ -70,20 +79,36 @@ export default class Quote extends React.PureComponent {
toast(this.props.language.quote);
}
favourite() {
if (localStorage.getItem('favouriteQuote')) {
localStorage.removeItem('favouriteQuote');
this.setState({ favourited: <StarIcon2 className='copyButton' onClick={() => this.favourite()} /> });
} else {
localStorage.setItem('favouriteQuote', this.state.quote + ' - ' + this.state.author);
this.setState({ favourited: <StarIcon className='copyButton' onClick={() => this.favourite()} /> });
}
}
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() {
const copy = (localStorage.getItem('copyButton') === 'false') ? null : <FileCopy className='copyButton' onClick={() => this.copyQuote()}></FileCopy>;
const tweet = (localStorage.getItem('tweetButton') === 'false') ? null :
<TwitterIcon className='copyButton' onClick={() => window.open(`https://twitter.com/intent/tweet?text=${this.state.quote} - ${this.state.author} on @getmue`, '_blank').focus()}/>;
if (localStorage.getItem('quote') === 'false') return null;
let copy = <FileCopy className='copyButton' onClick={() => this.copyQuote()}></FileCopy>;
if (localStorage.getItem('copyButton') === 'false') copy = null;
let tweet = <TwitterIcon className='copyButton' onClick={() => window.open(`https://twitter.com/intent/tweet?text=${this.state.quote} - ${this.state.author} on @getmue`, '_blank').focus()}/>
if (localStorage.getItem('tweetButton') === 'false') tweet = null;
return (
<div className='quotediv'>
<h1 className='quote'>{`${this.state.quote}`}</h1>
<h1 className='quoteauthor'>{this.state.author} {copy} {tweet}</h1>
<h1 className='quoteauthor'>{this.state.author} {copy} {tweet} {this.state.favourited}</h1>
</div>
);
}

View File

@@ -1,8 +1,26 @@
import React from 'react';
import SearchIcon from '@material-ui/icons/Search';
import MicIcon from '@material-ui/icons/Mic';
const searchEngines = require('../../modules/searchEngines.json');
export default class Search extends React.PureComponent {
constructor(...args) {
super(...args);
this.state = {
url: '',
query: ''
};
}
startSpeechRecognition() {
if (localStorage.getItem('voiceSearch') === 'false') return;
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);
}
render() {
if (localStorage.getItem('searchBar') === 'false') return null;
@@ -24,14 +42,24 @@ export default class Search extends React.PureComponent {
window.location.href = url + `?${query}=` + value;
};
let microphone = null;
if (localStorage.getItem('voiceSearch') === 'true') {
this.setState({
url: url,
query: query
});
microphone = <MicIcon className='micIcon' onClick={() => this.startSpeechRecognition()}/>;
}
return (
<div id='searchBar' className='searchbar'>
<form id='searchBar' className='searchbarform' action={url}>
<SearchIcon onClick={() => searchButton()} />
{microphone}
<SearchIcon onClick={() => searchButton()} id='searchButton' />
<input type='text' placeholder={this.props.language} name={query} id='searchtext' className='searchtext'/>
<div className='blursearcbBG'/>
</form>
</div>
);
}
}
}

View File

@@ -1,4 +1,4 @@
export const API_URL = 'https://api.muetab.xyz';
export const UNSPLASH_URL = 'https://unsplash.muetab.xyz';
export const MARKETPLACE_URL = 'https://marketplace.muetab.xyz';
export const API_URL = 'https://api.muetab.com';
export const UNSPLASH_URL = 'https://unsplash.muetab.com';
export const MARKETPLACE_URL = 'https://marketplace.muetab.com';
export const OFFLINE_IMAGES = 20;

View File

@@ -82,5 +82,9 @@
{
"name": "tweetButton",
"value": false
},
{
"name": "favouriteQuoteEnabled",
"value": false
}
]

View File

@@ -47,12 +47,12 @@ export default class SettingsFunctions {
}
}
static saveStuff() {
static saveStuff(hexDisabled) {
localStorage.setItem('blur', document.getElementById('blurRange').value); // this is better than inline onChange for performance
localStorage.setItem('brightness', document.getElementById('brightnessRange').value);
localStorage.setItem('greetingName', document.getElementById('greetingName').value);
localStorage.setItem('customBackground', document.getElementById('customBackground').value);
if (document.getElementById('customBackgroundHex').value !== 'Disabled') {
if (document.getElementById('customBackgroundHex').value !== hexDisabled) {
localStorage.setItem('customBackgroundColour', document.getElementById('customBackgroundHex').value);
}
if (document.getElementById('searchEngineInput').enabled === 'true') {

View File

@@ -16,8 +16,8 @@ $modal: (
);
$marketplace: (
'item-background': rgba(242, 243, 244, 1),
'product-information-backgroud': rgba(242, 243, 244, 1),
'item-background': rgba(242, 243, 244, 1),
'product-information-backgroud': rgba(242, 243, 244, 1),
);
$button-colours: (

View File

@@ -80,8 +80,12 @@ body {
}
@include keyframes(fadein) {
from { opacity: 0; }
to { opacity: 1; }
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.backgroundEffects {
@@ -89,11 +93,11 @@ body {
transition: ease 0.6s;
}
#searchEngine {
width: 130px;
}
.creditlink {
text-decoration: none;
color: white;
}
::selection {
background-color: #c2c2c2;
}

View File

@@ -10,6 +10,7 @@
font-size: 20px;
border-radius: 24px;
background: none;
&:hover {
outline: none;
}
@@ -32,7 +33,6 @@
}
}
.reset {
@extend %settingsButton;
background-color: map-get($button-colours, "reset");
@@ -171,11 +171,7 @@
@extend .storebutton;
}
.sideload {
margin-top: 12px;
}
.seemore {
.sideload, .seemore {
margin-top: 12px;
}

View File

@@ -19,6 +19,14 @@
position: absolute;
bottom: 10px;
right: 50px;
padding-right: 5px;
}
.view, .favourite {
transition: all 0.5s ease 0s;
&:hover {
transform: scale(1.1);
}
}
#photographer {
@@ -75,6 +83,10 @@
opacity: 0;
transition: opacity 1s;
box-sizing: border-box;
&.dark {
background-color: #2f3542 !important;
color: white !important;
}
}
&:hover .tooltiptext {

View File

@@ -151,7 +151,6 @@ p.author {
font-size: 35px !important;
}
p.description {
margin-top: 0px;
}
@@ -213,14 +212,10 @@ p.description {
}
#marketplace {
-webkit-animation: content 0.5s;
-moz-animation: content 0.5s;
-ms-animation: content 0.5s;
-o-animation: content 0.5s;
animation: content 0.5s;
@include animation('content 0.5s');
}
@keyframes content {
@include keyframes(content) {
from {
opacity: 0;
transform: translateY(5%);
@@ -278,9 +273,9 @@ p.description {
#seemore {
display: none;
}
#seemore svg {
font-size: 35px !important;
margin-bottom: -30px;
svg {
font-size: 35px !important;
margin-bottom: -30px;
}
}

View File

@@ -49,7 +49,11 @@
overflow: hidden;
}
@-webkit-keyframes zoom-in {
.zoom-in {
@include animation('zoom-in');
}
@include keyframes(zoom-in) {
0% {
transform: scale(0);
}
@@ -63,20 +67,6 @@
}
}
@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: 100;
@@ -140,11 +130,10 @@
}
.zoom-out {
-webkit-animation: zoom-out 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
animation: zoom-out 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
@include animation('zoom-out 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both');
}
@-webkit-keyframes zoom-out {
@include keyframes(zoom-out) {
0% {
transform: scale(1, 1);
}
@@ -158,27 +147,15 @@
}
}
@keyframes zoom-out {
0% {
-webkit-transform: scale(1, 1);
}
50% {
-webkit-transform: scale(1.05, 1.05);
}
100% {
-webkit-transform: scale(0);
}
}
.updateContent {
width: 400px;
padding: 5px;
.closeModal {
margin-top: 10px;
font-size: 45px;
}
img {
width: 100%;
height: auto;
@@ -196,4 +173,4 @@
background: #34495e;
border-top-right-radius: map-get($modal, "border-radius");
border-bottom-right-radius: map-get($modal, "border-radius");
}
}

View File

@@ -37,3 +37,11 @@
.input.searchtext {
border: none;
}
.micIcon {
margin-right: 10px;
}
#searchEngine {
width: 130px;
}

View File

@@ -264,4 +264,9 @@ select#language {
.nodropdown {
cursor: default;
}
.newFeature {
color: #ff4757;
font-size: 12px;
}

View File

@@ -33,7 +33,8 @@
"quote": {
"title": "Quote",
"copy": "Copy Button",
"tweet": "Tweet Button"
"tweet": "Tweet Button",
"favourite": "Favourite Button"
},
"background": {
"title": "Background",
@@ -44,7 +45,11 @@
"custombackground": "Custom Background",
"customcolour": "Custom Background Colour",
"upload": "Upload",
"addColour": "Add colour"
"addcolour": "Add colour",
"favourite": "Favourite",
"view": "View",
"refresh": "Refresh",
"disabled": "Disabled"
},
"searchbar": {
"title": "Search Bar",
@@ -52,21 +57,19 @@
"custom": "Custom Search URL"
},
"offline": "Offline Mode",
"dark": "Dark Theme",
"experimental": {
"title": "Experimental",
"webp": "Enable WebP",
"dark": "Dark Theme",
"animations": "Animations",
"view": "View",
"favourite": "Favourite",
"refresh": "Refresh"
"voicesearch": "Voice Search",
"nightmode": "Automatic Night Mode"
},
"language": "Language",
"apply": "Apply",
"reset": "Reset",
"import": "Import",
"export": "Export",
"imported_settings": "Imported settings"
"export": "Export"
},
"update": {
"title": "Update",

View File

@@ -1,89 +1,102 @@
{
"greeting": {
"morning": "Bonjour",
"afternoon": "Bonne après-midi",
"afternoon": "Bon après-midi",
"evening": "Bonsoir",
"christmas": "Bonne Noël",
"christmas": "Joyeux Noël",
"newyear": "Bonne année",
"halloween": "Joyeux Halloween"
},
"credit": "Photo par",
"search": "Trouver",
"search": "Rechercher",
"modals": {
"title": "Options",
"settings": "Parametres",
"settings": "Paramètres",
"addons": "Mes Options",
"marketplace": "Marché"
},
"settings": {
"time": {
"title": "Temps",
"seconds": "Seconds",
"twentyfourhour": "24 Heures",
"ampm": "AM/PM (12 hour)",
"zero": "Zero-padded",
"analog": "Analogue"
"title": "Heure",
"seconds": "Secondes",
"twentyfourhour": "24 heures",
"ampm": "AM/PM (12 heures)",
"zero": "Complétion de zéros",
"analog": "Analogique"
},
"greeting": {
"title": "Salutation",
"events": "Événements",
"default": "Défaut Salutation",
"name": "Nom Pour Salutation"
"default": "Salutation par défaut",
"name": "Nom pour salutation"
},
"quote": {
"title": "Citation",
"copy": "Au bouton copie"
"copy": "Bouton Copier",
"tweet": "Bouton Twitter",
"favourite": "Bouton Ajouter aux favoris"
},
"background": {
"title": "Fond",
"API": "Fond API",
"API": "Source",
"blur": "Ajuster le flou",
"customURL": "URL D'arrière-plan personnalisée",
"custombackground": "D'arrière-plan personnalisée",
"brightness": "Ajuster la luminosité",
"customURL": "URL d'arrière-plan personnalisé",
"custombackground": "Arrière-plan personnalisé",
"customcolour": "Couleur d'arrière-plan personnalisée",
"addColour": "Ajouter de la couleur"
"upload": "Ajouter",
"addcolour": "Ajouter une couleur",
"favourite": "Ajouter aux favoris",
"view": "Mode vue",
"refresh": "Rafraîchir"
},
"searchbar": {
"title": "Barre de Recherche",
"searchengine": "Moteur de recherche"
"searchengine": "Moteur de recherche",
"custom": "URL de recherche personnalisée"
},
"offline": "Mode Hors-Ligne",
"dark": "Thème sombre",
"experimental": {
"title": "Expérimental",
"webp": "Activer WebP",
"dark": "Thème sombre",
"animations": "Animations"
"animations": "Animations",
"favourite": "Bouton Ajouter aux favoris",
"voicesearch": "Recherche vocale"
},
"language": "Langue",
"apply": "Appliquer",
"reset": "Reset",
"reset": "Réinitialiser",
"import": "Importer",
"export": "Exporter"
},
"update": {
"title": "Actualiser",
"title": "Mise à jour",
"offline": {
"title": "Hors ligne",
"description": "Peut pas se connecter à Internet"
"description": "Impossible de se connecter à Internet"
},
"error": {
"title": "Erreur",
"content": "Could not connect to the server"
"description": "Impossible de se connecter au serveur"
},
"loading": "Chargement..."
"loading": "Chargement...",
"readblog": "Lire sur le blog ",
"contactsupport": "Contactez-nous "
},
"toasts": {
"quote": "Citation Copié",
"reset": "Réinitaliser avec succès",
"quote": "Citation copiée",
"reset": "Réinitialisé avec succès",
"installed": "Installé avec succès",
"removed": "Enlevée avec succès",
"error": "Quelque chose a mal tourné."
"removed": "Enlevé avec succès",
"error": "Quelque chose s'est mal passé",
"imported": "Importé avec succès"
},
"marketplace": {
"photo_packs": "Des Photos Packs",
"quote_packs": "Des Citation Packs",
"preset_settings": "Paramètres de prédéterminée",
"themes": "Thème",
"photo_packs": "Packs Photos",
"quote_packs": "Packs Citations",
"preset_settings": "Paramètres prédéfinis",
"themes": "Thèmes",
"product": {
"overview": "Aperçu",
"information": "Information",
@@ -91,26 +104,31 @@
"version": "Version",
"author": "Auteur",
"notice": {
"title": "Écriteau",
"description": "S'il vous plait, recharger la page."
"title": "Remarque",
"description": "Pour appliquer les changements, veuillez recharger la page."
},
"buttons": {
"addtomue": "Ajouter au Mue",
"addtomue": "Ajouter à Mue",
"remove": "Enlever"
},
"quoteWarning": {
"title": "Attention",
"description": "Ce pack fait appel à des serveurs externes qui sont susceptibles de vous tracer !"
}
},
"offline": {
"title": "Vous êtes hors ligne",
"description": "Veuillez vous connecter à l'internet."
"description": "Veuillez vous connecter à Internet."
},
"see_more": "Voir de Plus"
"see_more": "Voir plus"
},
"addons": {
"added": "Ajoutée",
"added": "Ajoutées",
"empty": {
"title": "Il est vide ici",
"description": "Aller su le marché pour en ajouter.",
"title": "C'est vide par ici",
"description": "Dirigez vous vers le marché pour ajouter des options.",
"button": "Naviguer vers le marché"
}
},
"sideload": "Charger"
}
}
}

View File

@@ -42,17 +42,17 @@
"custombackground": "Aangepaste Achtergrond",
"customcolour": "Aangepaste Achtergrondkleur",
"upload": "Uploaden",
"addColour": "Kleur toevoegen"
"addcolour": "Kleur toevoegen"
},
"searchbar": {
"title": "Zoekbalk",
"searchengine": "Zoekmachine"
},
"offline": "Offline Modus",
"dark": "Donker Thema",
"experimental": {
"title": "Experimenteel",
"webp": "WebP Gebruiken",
"dark": "Donker Thema",
"animations": "Animaties"
},
"language": "Taal",

View File

@@ -41,17 +41,17 @@
"customURL": "Personlig bakgrunn URL",
"custombackground": "Personlig bakgrunn",
"customcolour": "Personlig Bakgrunn Farge",
"addColour": "Legg til farge"
"addcolour": "Legg til farge"
},
"searchbar": {
"title": "Søkebar",
"searchengine": "Søkemotor"
},
"offline": "Frakoblet Modus",
"dark": "Mørkt tema",
"experimental": {
"title": "Eksperimental",
"webp": "Skru på WebP",
"dark": "Mørkt tema",
"animations": "Animasjoner"
},
"language": "Språk",

View File

@@ -43,25 +43,24 @@
"custombackground": "Пользовательский фон",
"customcolour": "Пользовательский цвет фона",
"upload": "Загрузить",
"addColour": "Добавить цвет"
"addcolour": "Добавить цвет"
},
"searchbar": {
"title": "Панель поиска",
"searchengine": "Поисковый движок"
},
"offline": "Офлайн режим",
"dark": "Тёмная тема",
"experimental": {
"title": "Экспериментальные настройки",
"webp": "Включить WebP",
"dark": "Тёмная тема",
"animations": "Анимации"
},
"language": "Язык",
"apply": "Применить",
"reset": "Сбросить",
"import": "Импорт",
"export": "Экспорт",
"imported_settings": "Импортированные настройки"
"export": "Экспорт"
},
"update": {
"title": "Обновление",