Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e921e3c12 | ||
|
|
7e2772812c | ||
|
|
9bd4f99006 | ||
|
|
0dbc586952 | ||
|
|
e09fc3f99f | ||
|
|
7dbd4976b7 | ||
|
|
66414461c4 | ||
|
|
2dd0e9150b | ||
|
|
d1b998da12 | ||
|
|
e76594f426 | ||
|
|
6553c49fbe | ||
|
|
7b256fc956 | ||
|
|
7cc88449d7 | ||
|
|
8aeb645046 | ||
|
|
f50c32778c | ||
|
|
ed38bc2cbb | ||
|
|
e8c5f546cd | ||
|
|
d3ce835956 | ||
|
|
c858734d7f | ||
|
|
97a76bd0d7 | ||
|
|
ee4e49a058 | ||
|
|
150eb06cd0 | ||
|
|
7b71d0759e | ||
|
|
f38749961b | ||
|
|
b5e5b8618e | ||
|
|
cec368ab5f | ||
|
|
9db5150b07 | ||
|
|
4dfe05ac8a | ||
|
|
97f680d738 | ||
|
|
8b79f82e29 | ||
|
|
89a8621de1 | ||
|
|
a27cf2eede | ||
|
|
3399705935 | ||
|
|
a1963fb31b | ||
|
|
1a12f487e7 | ||
|
|
f014a79065 | ||
|
|
4fbcc19ff8 | ||
|
|
7dca1c9de9 | ||
|
|
1249ce45d3 | ||
|
|
9387357854 | ||
|
|
05c4a2c30c | ||
|
|
70cf17140b | ||
|
|
9969a4db10 | ||
|
|
ec9429adcb | ||
|
|
7dafd2c08d | ||
|
|
ad4fffb519 | ||
|
|
4715bb6144 | ||
|
|
2dc682cd14 | ||
|
|
3cfac7418b | ||
|
|
3f540b7772 | ||
|
|
003f1e62b2 | ||
|
|
320ae1c922 | ||
|
|
b6f74d4305 | ||
|
|
0a670de8f1 | ||
|
|
88efb6356a | ||
|
|
254dec9e8f | ||
|
|
c35aedbd2d | ||
|
|
97ed47b8cd | ||
|
|
6f046d144f | ||
|
|
088008165d | ||
|
|
d7e0091136 | ||
|
|
7a443c16bf | ||
|
|
b5e55fd331 | ||
|
|
5016cf3e69 | ||
|
|
a672c60afd | ||
|
|
aa5513a5dd | ||
|
|
291e7bcb82 | ||
|
|
4c9c31c90b | ||
|
|
5a15ce3cd8 | ||
|
|
8f3fa2f898 | ||
|
|
afb0f5c061 | ||
|
|
3a0468dcb9 | ||
|
|
f56854127c | ||
|
|
66980a4c62 | ||
|
|
259a36fd5d | ||
|
|
8869e53daa | ||
|
|
92495ce6ce | ||
|
|
736a589b59 | ||
|
|
2814174a38 | ||
|
|
dec9475a75 | ||
|
|
7253a174a6 | ||
|
|
348d3e8578 |
21
README.md
@@ -31,8 +31,6 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
|
|||||||
* [Other](#other)
|
* [Other](#other)
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
*May be updated in the future*
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@@ -45,6 +43,9 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
|
|||||||
* Update modal, copy button and more!
|
* Update modal, copy button and more!
|
||||||
* Marketplace - download custom photo packs, quote packs, preset settings and themes made by the community!
|
* 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)
|
||||||
|
|
||||||
## Installation
|
## 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.xyz)*
|
||||||
### Chrome
|
### Chrome
|
||||||
@@ -82,7 +83,7 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
|
|||||||
<summary><b>Chrome/Edge (Chromium)</b> (Click to expand)</summary>
|
<summary><b>Chrome/Edge (Chromium)</b> (Click to expand)</summary>
|
||||||
<ol>
|
<ol>
|
||||||
<li> <code>yarn run build</code> or <code>npm run build</code>
|
<li> <code>yarn run build</code> or <code>npm run build</code>
|
||||||
<li> Rename <code>manifest-chrome.json</code> in the "manfiest" folder to <code>manifest.json</code> in "build"
|
<li> <code>yarn run chrome</code> or <code>npm run chrome</code>
|
||||||
<li> Visit <code>chrome://extensions</code> in Chrome
|
<li> Visit <code>chrome://extensions</code> in Chrome
|
||||||
<li> Click <b>Load unpacked</b> (Make sure <b>Developer Mode</b> is on)
|
<li> Click <b>Load unpacked</b> (Make sure <b>Developer Mode</b> is on)
|
||||||
<li> Go to the directory containing the built copy of Mue and click <b>ok</b>
|
<li> Go to the directory containing the built copy of Mue and click <b>ok</b>
|
||||||
@@ -92,8 +93,7 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
|
|||||||
<summary><b>Opera</b> (Click to expand)</summary>
|
<summary><b>Opera</b> (Click to expand)</summary>
|
||||||
<ol>
|
<ol>
|
||||||
<li> <code>yarn run build</code> or <code>npm run build</code>
|
<li> <code>yarn run build</code> or <code>npm run build</code>
|
||||||
<li> Rename <code>manifest-opera.json</code> in the "manfiest" folder to <code>manifest.json</code> in "build"
|
<li> <code>yarn run opera</code> or <code>npm run opera</code>
|
||||||
<li> Copy <code>background-opera.js</code> in the "manifest" folder to "build"
|
|
||||||
<li> Visit <code>about://extensions</code> in Opera
|
<li> Visit <code>about://extensions</code> in Opera
|
||||||
<li> Click <b>Load unpacked extension...</b> (Make sure <b>Developer Mode</b> is on)
|
<li> Click <b>Load unpacked extension...</b> (Make sure <b>Developer Mode</b> is on)
|
||||||
<li> Go to the directory containing Mue and click <b>ok</b>
|
<li> Go to the directory containing Mue and click <b>ok</b>
|
||||||
@@ -103,7 +103,7 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
|
|||||||
<summary><b>Firefox</b> (Click to expand)</summary>
|
<summary><b>Firefox</b> (Click to expand)</summary>
|
||||||
<ol>
|
<ol>
|
||||||
<li> <code>yarn run build</code> or <code>npm run build</code>
|
<li> <code>yarn run build</code> or <code>npm run build</code>
|
||||||
<li> Rename <code>manifest-firefox.json</code> in the "manfiest" folder to <code>manifest.json</code> in "build"
|
<li> <code>yarn run firefox</code> or <code>npm run firefox</code>
|
||||||
<li> Visit <code>about:debugging#addons</code> in Firefox
|
<li> Visit <code>about:debugging#addons</code> in Firefox
|
||||||
<li> Click <b>Load Temporary Add-on</b>
|
<li> Click <b>Load Temporary Add-on</b>
|
||||||
<li> Go to the directory containing Mue and click on the <b>manifest.json</b>
|
<li> Go to the directory containing Mue and click on the <b>manifest.json</b>
|
||||||
@@ -131,13 +131,20 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
|
|||||||
|
|
||||||
### Translators
|
### Translators
|
||||||
English - [David Ralph (ohlookitsderpy)](https://github.com/ohlookitsderpy) & [Alex Sparkes](https://github.com/alexsparkes)
|
English - [David Ralph (ohlookitsderpy)](https://github.com/ohlookitsderpy) & [Alex Sparkes](https://github.com/alexsparkes)
|
||||||
|
|
||||||
Dutch - [Wessel Tip](https://github.com/Wessel)
|
Dutch - [Wessel Tip](https://github.com/Wessel)
|
||||||
|
|
||||||
French - [Alex Sparkes](https://github.com/alexsparkes)
|
French - [Alex Sparkes](https://github.com/alexsparkes)
|
||||||
|
|
||||||
Norwegian - [Anders](https://github.com/FuryingFox)
|
Norwegian - [Anders](https://github.com/FuryingFox)
|
||||||
|
|
||||||
|
Russian - [MrZillaGold](https://github.com/MrZillaGold)
|
||||||
|
|
||||||
### Other
|
### Other
|
||||||
[Pexels](https://pexels.com) - Stock photos used for offline mode
|
[Pexels](https://pexels.com) - Stock photos used for offline mode
|
||||||
|
|
||||||
[Opera Forum](https://forums.opera.com/topic/25046/how-to-disable-completely-the-speed-dial/14) - Portions of code to add Opera support
|
[Opera Forum](https://forums.opera.com/topic/25046/how-to-disable-completely-the-speed-dial/14) - Portions of code to add Opera support
|
||||||
[Google Fonts](https://fonts.google.com/specimen/Lexend+Deca) - Lexend Deca font
|
|
||||||
|
[Google Fonts](https://fonts.google.com) - Lexend Deca and Roboto fonts
|
||||||
|
|
||||||
And many thanks to [Highholding](https://discord.bio/p/highholding), [Noa Shapira](#), [Roee Lupo](https://github.com/RoeeLupo), [Jeroen](#), [Glasvegas](https://twitter.com/_glasvegas), [Anders](https://github.com/FuryingFox), [Oded Shapira](https://twitter.com/dondishdev), Jacob Tyrrell and [Nikka Lai](#) for letting us use their wonderful photographs
|
And many thanks to [Highholding](https://discord.bio/p/highholding), [Noa Shapira](#), [Roee Lupo](https://github.com/RoeeLupo), [Jeroen](#), [Glasvegas](https://twitter.com/_glasvegas), [Anders](https://github.com/FuryingFox), [Oded Shapira](https://twitter.com/dondishdev), Jacob Tyrrell and [Nikka Lai](#) for letting us use their wonderful photographs
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 276 KiB After Width: | Height: | Size: 262 KiB |
@@ -3,16 +3,16 @@
|
|||||||
"offline_enabled": true,
|
"offline_enabled": true,
|
||||||
"name": "Mue",
|
"name": "Mue",
|
||||||
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
|
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
"default_icon": "./icons/extension-icon.png"
|
"default_icon": "icons/128x128.png"
|
||||||
},
|
},
|
||||||
"chrome_url_overrides": {
|
"chrome_url_overrides": {
|
||||||
"newtab": "index.html"
|
"newtab": "index.html"
|
||||||
},
|
},
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "./icons/16x16-circle.png",
|
"16": "icons/16x16.png",
|
||||||
"48": "./icons/48x48-circle.png",
|
"48": "icons/48x48.png",
|
||||||
"128": "./icons/128x128-circle.png"
|
"128": "icons/128x128.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Mue",
|
"name": "Mue",
|
||||||
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
|
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
"default_icon": "./icons/extension-icon.png"
|
"default_icon": "icons/128x128.png"
|
||||||
},
|
},
|
||||||
"chrome_url_overrides": {
|
"chrome_url_overrides": {
|
||||||
"newtab": "index.html"
|
"newtab": "index.html"
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Mue",
|
"name": "Mue",
|
||||||
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
|
"description": "Fast, open and free-to-use new tab page for most modern browsers.",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"browser_action": {
|
"browser_action": {
|
||||||
"default_icon": "./icons/extension-icon.png"
|
"default_icon": "icons/128x128.png"
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": [
|
"scripts": [
|
||||||
|
|||||||
@@ -13,9 +13,8 @@
|
|||||||
"homepage": "https://muetab.xyz",
|
"homepage": "https://muetab.xyz",
|
||||||
"bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D",
|
"bugs": "https://github.com/mue/mue/issues/new?assignees=&labels=bug&template=bug-report.md&title=%5BBUG%5D",
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"version": "4.0.0",
|
"version": "4.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eartharoid/dtf": "^1.0.7",
|
|
||||||
"@material-ui/core": "^4.11.0",
|
"@material-ui/core": "^4.11.0",
|
||||||
"@material-ui/icons": "^4.9.1",
|
"@material-ui/icons": "^4.9.1",
|
||||||
"@muetab/quotes": "^1.0.0",
|
"@muetab/quotes": "^1.0.0",
|
||||||
@@ -28,7 +27,7 @@
|
|||||||
"supports-webp": "^2.0.1"
|
"supports-webp": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"react-scripts": "3.4.1",
|
"react-scripts": "3.4.3",
|
||||||
"node-sass": "^4.14.1"
|
"node-sass": "^4.14.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
BIN
public/fonts/Roboto-Cyrillic.woff2
Normal file
|
Before Width: | Height: | Size: 4.9 KiB |
BIN
public/icons/128x128.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 673 B |
BIN
public/icons/16x16.png
Normal file
|
After Width: | Height: | Size: 645 B |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
BIN
public/icons/48x48.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 607 B |
@@ -3,8 +3,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8' />
|
<meta charset='utf-8' />
|
||||||
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||||
<link rel='icon' type='image/png' sizes='32x32' href='./icons/favicon-32x32.png'>
|
<link rel='icon' type='image/png' sizes='32x32' href='./icons/32x32.png'>
|
||||||
<link rel='icon' type='image/png' sizes='16x16' href='./icons/favicon-16x16.png'>
|
<link rel='icon' type='image/png' sizes='16x16' href='./icons/16x16.png'>
|
||||||
<title>New Tab</title>
|
<title>New Tab</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
40
src/App.jsx
@@ -1,13 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import Background from './components/widgets/Background';
|
import Background from './components/widgets/Background';
|
||||||
import Clock from './components/widgets/Clock';
|
import Clock from './components/widgets/Clock';
|
||||||
import Greeting from './components/widgets/Greeting';
|
import Greeting from './components/widgets/Greeting';
|
||||||
import Quote from './components/widgets/Quote';
|
import Quote from './components/widgets/Quote';
|
||||||
import Search from './components/widgets/Search';
|
import Search from './components/widgets/Search';
|
||||||
|
import Maximise from './components/widgets/Maximise';
|
||||||
|
import Favourite from './components/widgets/Favourite';
|
||||||
|
|
||||||
import Navbar from './components/Navbar';
|
import Navbar from './components/Navbar';
|
||||||
|
|
||||||
import SettingsFunctions from './modules/settingsFunctions';
|
import SettingsFunctions from './modules/settingsFunctions';
|
||||||
import { ToastContainer } from 'react-toastify';
|
import { ToastContainer } from 'react-toastify';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
|
import { merge } from './modules/merge';
|
||||||
import RoomIcon from '@material-ui/icons/Room';
|
import RoomIcon from '@material-ui/icons/Room';
|
||||||
|
|
||||||
// Modals are lazy loaded as a user won't use them every time they open a tab
|
// Modals are lazy loaded as a user won't use them every time they open a tab
|
||||||
@@ -15,7 +21,7 @@ const Settings = React.lazy(() => import('./components/modals/Settings'));
|
|||||||
const Update = React.lazy(() => import('./components/modals/Update'));
|
const Update = React.lazy(() => import('./components/modals/Update'));
|
||||||
const Marketplace = React.lazy(() => import('./components/modals/Marketplace'));
|
const Marketplace = React.lazy(() => import('./components/modals/Marketplace'));
|
||||||
const Addons = React.lazy(() => import('./components/modals/Addons'));
|
const Addons = React.lazy(() => import('./components/modals/Addons'));
|
||||||
const Welcome = React.lazy(() => import('./components/modals/Welcome'));
|
//const Welcome = React.lazy(() => import('./components/modals/Welcome'));
|
||||||
const renderLoader = () => <div></div>;
|
const renderLoader = () => <div></div>;
|
||||||
|
|
||||||
export default class App extends React.PureComponent {
|
export default class App extends React.PureComponent {
|
||||||
@@ -42,11 +48,13 @@ export default class App extends React.PureComponent {
|
|||||||
let overlayClassList = 'Overlay';
|
let overlayClassList = 'Overlay';
|
||||||
if (localStorage.getItem('animations') === 'true') overlayClassList = 'Overlay modal-animation';
|
if (localStorage.getItem('animations') === 'true') overlayClassList = 'Overlay modal-animation';
|
||||||
|
|
||||||
let language = require(`./translations/${localStorage.getItem('language')}.json`);
|
let language = require(`./translations/${localStorage.getItem('language') || 'en'}.json`);
|
||||||
|
const en = require('./translations/en.json');
|
||||||
|
language = merge(en, language);
|
||||||
|
|
||||||
const theme = localStorage.getItem('theme');
|
const theme = localStorage.getItem('theme');
|
||||||
if (theme) {
|
if (theme) {
|
||||||
let style = document.createElement('link');
|
const style = document.createElement('link');
|
||||||
style.href = theme;
|
style.href = theme;
|
||||||
style.rel = 'stylesheet';
|
style.rel = 'stylesheet';
|
||||||
document.head.appendChild(style);
|
document.head.appendChild(style);
|
||||||
@@ -62,13 +70,16 @@ export default class App extends React.PureComponent {
|
|||||||
<Greeting language={language.greeting} />
|
<Greeting language={language.greeting} />
|
||||||
<Clock/>
|
<Clock/>
|
||||||
<Quote language={language.toasts}/>
|
<Quote language={language.toasts}/>
|
||||||
<div className='credits'>
|
<div className='credits' id='credits'>
|
||||||
<h1 id='photographer'>{language.credit}</h1>
|
<h1 id='photographer'>{language.credit}</h1>
|
||||||
|
<span id='credit' style={{'display': 'none'}}></span>
|
||||||
<div id='backgroundCredits' className='tooltip'>
|
<div id='backgroundCredits' className='tooltip'>
|
||||||
<RoomIcon className='locationicon'/>
|
<RoomIcon className='locationicon'/>
|
||||||
<span className='tooltiptext' id='location'/>
|
<span className='tooltiptext' id='location'/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Maximise/>
|
||||||
|
<Favourite/>
|
||||||
<React.Suspense fallback={renderLoader()}>
|
<React.Suspense fallback={renderLoader()}>
|
||||||
<Modal id={'modal'} onRequestClose={() => this.setState({ settingsModal: false })} isOpen={this.state.settingsModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
<Modal id={'modal'} onRequestClose={() => this.setState({ settingsModal: false })} isOpen={this.state.settingsModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
||||||
<Settings
|
<Settings
|
||||||
@@ -78,14 +89,12 @@ export default class App extends React.PureComponent {
|
|||||||
setDefaultSettings={() => SettingsFunctions.setDefaultSettings()}
|
setDefaultSettings={() => SettingsFunctions.setDefaultSettings()}
|
||||||
openMarketplace={() => this.setState({ marketplaceModal: true, settingsModal: false })}
|
openMarketplace={() => this.setState({ marketplaceModal: true, settingsModal: false })}
|
||||||
openAddons={() => this.setState({ settingsModal: false, addonsModal: true })}
|
openAddons={() => this.setState({ settingsModal: false, addonsModal: true })}
|
||||||
toastLanguage={language.toasts}
|
toastLanguage={language.toasts} />
|
||||||
/>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal onRequestClose={() => this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
<Modal onRequestClose={() => this.setState({ updateModal: false })} isOpen={this.state.updateModal} className={modalClassList} overlayClassName={overlayClassList} ariaHideApp={false}>
|
||||||
<Update
|
<Update
|
||||||
language={language.update}
|
language={language.update}
|
||||||
modalClose={() => this.setState({ updateModal: false })}
|
modalClose={() => this.setState({ updateModal: false })} />
|
||||||
/>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal onRequestClose={() => this.setState({ marketplaceModal: false })} isOpen={this.state.marketplaceModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
|
<Modal onRequestClose={() => this.setState({ marketplaceModal: false })} isOpen={this.state.marketplaceModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
|
||||||
<Marketplace
|
<Marketplace
|
||||||
@@ -94,24 +103,21 @@ export default class App extends React.PureComponent {
|
|||||||
modalClose={() => this.setState({ marketplaceModal: false })}
|
modalClose={() => this.setState({ marketplaceModal: false })}
|
||||||
openSettings={() => this.setState({ marketplaceModal: false, settingsModal: true })}
|
openSettings={() => this.setState({ marketplaceModal: false, settingsModal: true })}
|
||||||
openAddons={() => this.setState({ marketplaceModal: false, addonsModal: true })}
|
openAddons={() => this.setState({ marketplaceModal: false, addonsModal: true })}
|
||||||
toastLanguage={language.toasts}
|
toastLanguage={language.toasts} />
|
||||||
/>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal onRequestClose={() => this.setState({ addonsModal: false })} isOpen={this.state.addonsModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
|
<Modal onRequestClose={() => this.setState({ addonsModal: false })} isOpen={this.state.addonsModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
|
||||||
<Addons
|
<Addons
|
||||||
language={language.addons}
|
language={language.addons}
|
||||||
|
marketplaceLanguage={language.marketplace}
|
||||||
modalLanguage={language.modals}
|
modalLanguage={language.modals}
|
||||||
modalClose={() => this.setState({ addonsModal: false })}
|
modalClose={() => this.setState({ addonsModal: false })}
|
||||||
openSettings={() => this.setState({ addonsModal: false, settingsModal: true })}
|
openSettings={() => this.setState({ addonsModal: false, settingsModal: true })}
|
||||||
openMarketplace={() => this.setState({ addonsModal: false, marketplaceModal: true })}
|
openMarketplace={() => this.setState({ addonsModal: false, marketplaceModal: true })}
|
||||||
toastLanguage={language.toasts}
|
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>
|
</Modal>
|
||||||
|
{/* <Modal onRequestClose={() => this.setState({ welcomeModal: false })} isOpen={this.state.welcomeModal} className={modalClassList} overlayClassName='Overlay' ariaHideApp={false}>
|
||||||
|
<Welcome modalClose={() => this.setState({ welcomeModal: false })} />
|
||||||
|
</Modal> */ }
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|||||||
@@ -5,14 +5,10 @@ import NewReleases from '@material-ui/icons/NewReleases';
|
|||||||
|
|
||||||
export default class Navbar extends React.PureComponent {
|
export default class Navbar extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
let refreshHTML = <div className='navbar2' ><RefreshIcon className='refreshicon' onClick={() => window.location.reload()} /></div>
|
let refreshHTML = <div className='navbar2'><RefreshIcon className='refreshicon' onClick={() => window.location.reload()} /></div>;
|
||||||
const refresh = localStorage.getItem('refresh');
|
const refresh = localStorage.getItem('refresh');
|
||||||
if (refresh === 'false') refreshHTML = '';
|
if (refresh === 'false') refreshHTML = '';
|
||||||
|
|
||||||
const viewedUpdate = localStorage.getItem('viewedUpdate');
|
|
||||||
let update = <NewReleases className='refreshicon' onClick={this.props.updateModalOpen} />;
|
|
||||||
if (viewedUpdate === 'false') update = <NewReleases className='refreshicon' onClick={this.props.updateModalOpen} />
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='navbar-container'>
|
<div className='navbar-container'>
|
||||||
<div className='navbar1'>
|
<div className='navbar1'>
|
||||||
@@ -20,7 +16,7 @@ export default class Navbar extends React.PureComponent {
|
|||||||
</div>
|
</div>
|
||||||
{refreshHTML}
|
{refreshHTML}
|
||||||
<div className={refresh === 'false' ? 'navbar2' : 'navbar3'}>
|
<div className={refresh === 'false' ? 'navbar2' : 'navbar3'}>
|
||||||
{update}
|
<NewReleases className='refreshicon' onClick={this.props.updateModalOpen} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import LocalMallIcon from '@material-ui/icons/LocalMall';
|
import LocalMallIcon from '@material-ui/icons/LocalMall';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import dtf from '@eartharoid/dtf';
|
|
||||||
import Item from './marketplace/Item';
|
import Item from './marketplace/Item';
|
||||||
import MarketplaceFunctions from '../../modules/marketplaceFunctions';
|
import MarketplaceFunctions from '../../modules/marketplaceFunctions';
|
||||||
|
|
||||||
@@ -10,6 +9,11 @@ export default class Addons extends React.PureComponent {
|
|||||||
super(...args);
|
super(...args);
|
||||||
this.state = {
|
this.state = {
|
||||||
installed: [],
|
installed: [],
|
||||||
|
current_data: {
|
||||||
|
type: '',
|
||||||
|
name: '',
|
||||||
|
content: {}
|
||||||
|
},
|
||||||
item_data: {
|
item_data: {
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
author: 'Author',
|
author: 'Author',
|
||||||
@@ -17,11 +21,12 @@ export default class Addons extends React.PureComponent {
|
|||||||
updated: '???',
|
updated: '???',
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
icon: ''
|
icon: ''
|
||||||
}
|
},
|
||||||
|
button: <button className='removeFromMue' onClick={() => this.uninstall()}>{this.props.marketplaceLanguage.product.buttons.remove}</button>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggle(type, type2, data) {
|
toggle(type, type2, data) {
|
||||||
if (type === 'item') {
|
if (type === 'item') {
|
||||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
let installed = JSON.parse(localStorage.getItem('installed'));
|
||||||
let info = installed.find(i => i.name === data).content;
|
let info = installed.find(i => i.name === data).content;
|
||||||
@@ -31,53 +36,106 @@ export default class Addons extends React.PureComponent {
|
|||||||
name: info.data.name,
|
name: info.data.name,
|
||||||
author: info.data.author,
|
author: info.data.author,
|
||||||
description: MarketplaceFunctions.urlParser(info.data.description.replace(/\n/g, '<br>')),
|
description: MarketplaceFunctions.urlParser(info.data.description.replace(/\n/g, '<br>')),
|
||||||
updated: dtf('n_D MMM YYYY', info.updated, 'en-GB'),
|
updated: info.updated,
|
||||||
version: info.data.version,
|
version: info.data.version,
|
||||||
icon: info.data.screenshot_url
|
icon: info.data.screenshot_url
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
document.getElementById('marketplace').style.display = 'none';
|
|
||||||
document.getElementById('item').style.display = 'block';
|
document.getElementById('item').style.display = 'block';
|
||||||
|
document.getElementById('marketplace').style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
|
this.setState({
|
||||||
|
button: <button className='removeFromMue' onClick={() => this.uninstall()}>{this.props.marketplaceLanguage.product.buttons.remove}</button>
|
||||||
|
});
|
||||||
document.getElementById('marketplace').style.display = 'block';
|
document.getElementById('marketplace').style.display = 'block';
|
||||||
document.getElementById('item').style.display = 'none';
|
document.getElementById('item').style.display = 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uninstall() {
|
uninstall() {
|
||||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
let type, data = this.state.current_data.type;
|
||||||
|
if (data === undefined) data = this.state.current_data.content.data.type;
|
||||||
const uninstallStuff = () => {
|
switch (data) {
|
||||||
for (let i = 0; i < installed.length; i++) {
|
case 'photos':
|
||||||
if (installed[i].name === this.state.current_data.name) {
|
type = 'photo_packs';
|
||||||
installed.splice(i, 1);
|
break;
|
||||||
break;
|
case 'quotes':
|
||||||
}
|
type = 'quote_packs';
|
||||||
}
|
|
||||||
localStorage.setItem('installed', JSON.stringify(installed));
|
|
||||||
toast(this.props.toastLanguage.removed);
|
|
||||||
this.toggle();
|
|
||||||
this.componentDidMount();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (this.state.current_data.type) {
|
|
||||||
case 'settings':
|
|
||||||
let oldSettings = JSON.parse(localStorage.getItem('backup_settings'));
|
|
||||||
localStorage.clear();
|
|
||||||
oldSettings.forEach(item => localStorage.setItem(item.name, item.value));
|
|
||||||
uninstallStuff();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
try {
|
type = this.state.current_data.type;
|
||||||
localStorage.removeItem(this.state.current_data.type);
|
break;
|
||||||
uninstallStuff();
|
}
|
||||||
} catch (e) {
|
MarketplaceFunctions.uninstall(this.state.current_data.name, type);
|
||||||
console.log('invalid');
|
toast(this.props.toastLanguage.removed);
|
||||||
|
this.setState({
|
||||||
|
button: '',
|
||||||
|
installed: JSON.parse(localStorage.getItem('installed'))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
install(input) {
|
||||||
|
let installed = JSON.parse(localStorage.getItem('installed'));
|
||||||
|
let button;
|
||||||
|
|
||||||
|
const installStuff = () => {
|
||||||
|
installed.push({
|
||||||
|
content: {
|
||||||
|
updated: 'Unpublished',
|
||||||
|
data: input
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
localStorage.setItem('installed', JSON.stringify(installed));
|
||||||
|
toast(this.props.toastLanguage.installed);
|
||||||
|
button = <button className='removeFromMue' onClick={() => this.uninstall()}>{this.props.marketplaceLanguage.product.buttons.remove}</button>;
|
||||||
|
this.setState({
|
||||||
|
button: button,
|
||||||
|
installed: JSON.parse(localStorage.getItem('installed'))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (input.type) {
|
||||||
|
case 'settings':
|
||||||
|
localStorage.removeItem('backup_settings');
|
||||||
|
let oldSettings = [];
|
||||||
|
for (const key of Object.keys(localStorage)) oldSettings.push({name: key, value: localStorage.getItem(key)});
|
||||||
|
localStorage.setItem('backup_settings', JSON.stringify(oldSettings));
|
||||||
|
input.settings.forEach(element => localStorage.setItem(element.name, element.value));
|
||||||
|
installStuff();
|
||||||
|
break;
|
||||||
|
case 'photos':
|
||||||
|
localStorage.setItem('photo_packs', JSON.stringify(input.photos));
|
||||||
|
installStuff();
|
||||||
|
break;
|
||||||
|
case 'theme':
|
||||||
|
localStorage.setItem('theme', input.theme);
|
||||||
|
installStuff();
|
||||||
|
break;
|
||||||
|
case 'quote_packs':
|
||||||
|
if (input.quote_api) localStorage.setItem('quote_api', JSON.stringify(input.quote_api));
|
||||||
|
localStorage.setItem('quote_packs', JSON.stringify(input.quotes));
|
||||||
|
installStuff();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
document.getElementById('file-input').onchange = (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (file.type !== 'application/json') return console.error(`expected json, got ${file.type}`);
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsText(file, 'UTF-8');
|
||||||
|
|
||||||
|
reader.onload = (readerEvent) => {
|
||||||
|
const content = JSON.parse(readerEvent.target.result);
|
||||||
|
this.install(content);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
|
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
|
||||||
document.getElementById('center').classList.toggle('backgroundEffects');
|
document.getElementById('center').classList.toggle('backgroundEffects');
|
||||||
this.setState({ installed: JSON.parse(localStorage.getItem('installed')) });
|
this.setState({ installed: JSON.parse(localStorage.getItem('installed')) });
|
||||||
@@ -89,55 +147,43 @@ export default class Addons extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
let content = <div className='items'>
|
||||||
|
{this.state.installed.map((item) =>
|
||||||
|
<div className='item' onClick={() => this.toggle('item', item.type, item.name)}>
|
||||||
|
<img alt='icon' src={item.content.data.icon_url} />
|
||||||
|
<div className='details'>
|
||||||
|
<h4>{item.content.data.name}</h4>
|
||||||
|
<p>{item.content.data.author}</p>
|
||||||
|
</div>
|
||||||
|
</div>)}
|
||||||
|
</div>;
|
||||||
|
|
||||||
if (this.state.installed.length === 0) {
|
if (this.state.installed.length === 0) {
|
||||||
return <div className='content'>
|
content = <div className='items'>
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<div className='emptyMessage'>
|
||||||
<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()}>Sideload</button> */}
|
|
||||||
<h1>{this.props.language.added}</h1>
|
|
||||||
<div className="items">
|
|
||||||
<div className="emptyMessage">
|
|
||||||
<LocalMallIcon />
|
<LocalMallIcon />
|
||||||
<h1>{this.props.language.empty.title}</h1>
|
<h1>{this.props.language.empty.title}</h1>
|
||||||
<p className="description">{this.props.language.empty.description}</p>
|
<p className='description'>{this.props.language.empty.description}</p>
|
||||||
<button className="goToMarket" onClick={this.props.openMarketplace}>{this.props.language.empty.button}</button>
|
<button className='goToMarket' onClick={this.props.openMarketplace}>{this.props.language.empty.button}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>;
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className='content'>
|
return <div className='content'>
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||||
<h1>{this.props.modalLanguage.title}</h1>
|
<h1>{this.props.modalLanguage.title}</h1>
|
||||||
<div className="tab">
|
<div className='tab'>
|
||||||
<button className="tablinks" onClick={this.props.openMarketplace}>{this.props.modalLanguage.marketplace}</button>
|
<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' id='active'>{this.props.modalLanguage.addons}</button>
|
||||||
<button className="tablinks" onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</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()}>Sideload</button> */}
|
|
||||||
<h1>{this.props.language.added}</h1>
|
|
||||||
<div className="items">
|
|
||||||
{this.state.installed.map((item) =>
|
|
||||||
<div className="item" onClick={()=> this.toggle('item', item.type, item.name)}>
|
|
||||||
<img alt="icon" src={item.content.data.icon_url} />
|
|
||||||
<div className="details">
|
|
||||||
<h4>{item.content.data.name}</h4>
|
|
||||||
<p>{item.content.data.author}</p>
|
|
||||||
</div>
|
|
||||||
</div>)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<Item button={<button className="removeFromMue" onClick={() => this.uninstall()}>{this.props.language.product.buttons.remove}</button>} data={this.state.item_data} function={()=> this.toggle()} language={this.props.language.product} />
|
<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>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React from 'react';
|
|||||||
import WifiOffIcon from '@material-ui/icons/WifiOff';
|
import WifiOffIcon from '@material-ui/icons/WifiOff';
|
||||||
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import dtf from '@eartharoid/dtf';
|
|
||||||
import Item from './marketplace/Item';
|
import Item from './marketplace/Item';
|
||||||
import MarketplaceFunctions from '../../modules/marketplaceFunctions';
|
import MarketplaceFunctions from '../../modules/marketplaceFunctions';
|
||||||
import * as Constants from '../../modules/constants';
|
import * as Constants from '../../modules/constants';
|
||||||
@@ -39,17 +38,17 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
this.offlineHTML = <div className='content'>
|
this.offlineHTML = <div className='content'>
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||||
<h1>{this.props.modalLanguage.title}</h1>
|
<h1>{this.props.modalLanguage.title}</h1>
|
||||||
<div className="tab">
|
<div className='tab'>
|
||||||
<button className="tablinks" id="active">{this.props.modalLanguage.marketplace}</button>
|
<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.openAddons}>{this.props.modalLanguage.addons}</button>
|
||||||
<button className="tablinks"
|
<button className='tablinks'
|
||||||
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
|
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
|
||||||
</div>
|
</div>
|
||||||
<div id='marketplace'>
|
<div id='marketplace'>
|
||||||
<div className="emptyMessage" style={{"marginTop": "20px", "transform": "translateY(80%)"}}>
|
<div className='emptyMessage' style={{'marginTop': '20px', 'transform': 'translateY(80%)'}}>
|
||||||
<WifiOffIcon />
|
<WifiOffIcon />
|
||||||
<h1>{this.props.language.offline.title}</h1>
|
<h1>{this.props.language.offline.title}</h1>
|
||||||
<p className="description">{this.props.language.offline.description}</p>
|
<p className='description'>{this.props.language.offline.description}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
@@ -68,8 +67,7 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
if (type === 'item') {
|
if (type === 'item') {
|
||||||
let info;
|
let info;
|
||||||
try {
|
try {
|
||||||
info = await fetch(`${Constants.MARKETPLACE_URL}/item/${type2}/${data}`);
|
info = await (await fetch(`${Constants.MARKETPLACE_URL}/item/${type2}/${data}`)).json();
|
||||||
info = await info.json();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return toast(this.props.toastLanguage.error);
|
return toast(this.props.toastLanguage.error);
|
||||||
}
|
}
|
||||||
@@ -80,18 +78,19 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
name: info.data.name,
|
name: info.data.name,
|
||||||
author: info.data.author,
|
author: info.data.author,
|
||||||
description: MarketplaceFunctions.urlParser(info.data.description.replace(/\n/g, '<br>')),
|
description: MarketplaceFunctions.urlParser(info.data.description.replace(/\n/g, '<br>')),
|
||||||
updated: dtf('n_D MMM YYYY', info.updated, 'en-GB'),
|
updated: info.updated,
|
||||||
version: info.data.version,
|
version: info.data.version,
|
||||||
icon: info.data.screenshot_url
|
icon: info.data.screenshot_url
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('marketplace').style.display = 'none';
|
document.getElementById('marketplace').style.display = 'none';
|
||||||
document.getElementById('seemore').style.display = 'none';
|
document.getElementById('seemore').style.display = 'none';
|
||||||
document.getElementById('item').style.display = 'block';
|
document.getElementById('item').style.display = 'block';
|
||||||
|
|
||||||
let button = <button className="addToMue" onClick={() => this.install()}>{this.props.language.product.buttons.addtomue}</button>;
|
let button = <button className='addToMue' onClick={() => this.install()}>{this.props.language.product.buttons.addtomue}</button>;
|
||||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
const installed = JSON.parse(localStorage.getItem('installed'));
|
||||||
if (installed.some(item => item.name === data)) button = <button className="removeFromMue" onClick={() => this.uninstall()}>{this.props.language.product.buttons.remove}</button>;
|
if (installed.some(item => item.name === data)) button = <button className='removeFromMue' onClick={() => this.uninstall()}>{this.props.language.product.buttons.remove}</button>;
|
||||||
this.setState({ button: button });
|
this.setState({ button: button });
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('marketplace').style.display = 'block';
|
document.getElementById('marketplace').style.display = 'block';
|
||||||
@@ -101,22 +100,20 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getItems() {
|
async getItems() {
|
||||||
let data = await fetch(Constants.MARKETPLACE_URL + '/all');
|
const data = await (await fetch(Constants.MARKETPLACE_URL + '/all')).json();
|
||||||
data = await data.json();
|
const featured = await (await fetch(Constants.MARKETPLACE_URL + '/featured')).json();
|
||||||
let data2 = await fetch(Constants.MARKETPLACE_URL + '/featured');
|
|
||||||
data2 = await data2.json();
|
|
||||||
this.setState({
|
this.setState({
|
||||||
themes: data.data.themes,
|
themes: data.data.themes,
|
||||||
settings: data.data.settings,
|
settings: data.data.settings,
|
||||||
photo_packs: data.data.photo_packs,
|
photo_packs: data.data.photo_packs,
|
||||||
quote_packs: data.data.quote_packs,
|
quote_packs: data.data.quote_packs,
|
||||||
see_more: data.data.photo_packs,
|
see_more: data.data.photo_packs,
|
||||||
featured: data2.data,
|
featured: featured.data,
|
||||||
done: true
|
done: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async install() {
|
install() {
|
||||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
let installed = JSON.parse(localStorage.getItem('installed'));
|
||||||
let button;
|
let button;
|
||||||
|
|
||||||
@@ -124,7 +121,7 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
installed.push(this.state.current_data);
|
installed.push(this.state.current_data);
|
||||||
localStorage.setItem('installed', JSON.stringify(installed));
|
localStorage.setItem('installed', JSON.stringify(installed));
|
||||||
toast(this.props.toastLanguage.installed);
|
toast(this.props.toastLanguage.installed);
|
||||||
button = <button className="removeFromMue" onClick={() => this.uninstall()}>{this.props.language.product.buttons.remove}</button>;
|
button = <button className='removeFromMue' onClick={() => this.uninstall()}>{this.props.language.product.buttons.remove}</button>;
|
||||||
this.setState({ button: button });
|
this.setState({ button: button });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,46 +143,21 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
installStuff();
|
installStuff();
|
||||||
break;
|
break;
|
||||||
case 'quote_packs':
|
case 'quote_packs':
|
||||||
|
if (this.state.current_data.content.data.quote_api) localStorage.setItem('quote_api', JSON.stringify(this.state.current_data.content.data.quote_api));
|
||||||
localStorage.setItem('quote_packs', JSON.stringify(this.state.current_data.content.data.quotes));
|
localStorage.setItem('quote_packs', JSON.stringify(this.state.current_data.content.data.quotes));
|
||||||
installStuff();
|
installStuff();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log('invalid');
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uninstall() {
|
uninstall() {
|
||||||
let installed = JSON.parse(localStorage.getItem('installed'));
|
MarketplaceFunctions.uninstall(this.state.current_data.name, this.state.current_data.type);
|
||||||
let button;
|
|
||||||
|
|
||||||
const uninstallStuff = () => {
|
|
||||||
for (let i = 0; i < installed.length; i++) {
|
|
||||||
if (installed[i].name === this.state.current_data.name) {
|
|
||||||
installed.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
localStorage.setItem('installed', JSON.stringify(installed));
|
|
||||||
toast(this.props.toastLanguage.removed);
|
toast(this.props.toastLanguage.removed);
|
||||||
button = <button className="addToMue" onClick={() => this.install()}>{this.props.language.product.buttons.addtomue}</button>;
|
this.setState({
|
||||||
this.setState({ button: button });
|
button: <button className='addToMue' onClick={() => this.install()}>{this.props.language.product.buttons.addtomue}</button>
|
||||||
}
|
});
|
||||||
|
|
||||||
switch (this.state.current_data.type) {
|
|
||||||
case 'settings':
|
|
||||||
let oldSettings = JSON.parse(localStorage.getItem('backup_settings'));
|
|
||||||
localStorage.clear();
|
|
||||||
oldSettings.forEach(item => localStorage.setItem(item.name, item.value));
|
|
||||||
uninstallStuff();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
try {
|
|
||||||
localStorage.removeItem(this.state.current_data.type);
|
|
||||||
uninstallStuff();
|
|
||||||
} catch (e) {
|
|
||||||
console.log('invalid');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@@ -201,56 +173,71 @@ export default class Marketplace extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (navigator.onLine === false || this.state.done === false) {
|
if (navigator.onLine === false) return this.offlineHTML;
|
||||||
return this.offlineHTML;
|
if (this.state.done === false) {
|
||||||
|
return <div className='content'>
|
||||||
|
<span className='closeModal' onClick={this.props.modalClose}>×</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'>
|
||||||
|
<div className='emptyMessage' style={{'marginTop': '20px', 'transform': 'translateY(80%)'}}>
|
||||||
|
<h1>Loading...</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className='content'>
|
return <div className='content'>
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||||
<h1>{this.props.modalLanguage.title}</h1>
|
<h1>{this.props.modalLanguage.title}</h1>
|
||||||
<div className="tab">
|
<div className='tab'>
|
||||||
<button className="tablinks" id="active">{this.props.modalLanguage.marketplace}</button>
|
<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.openAddons}>{this.props.modalLanguage.addons}</button>
|
||||||
<button className="tablinks"
|
<button className='tablinks'
|
||||||
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
|
onClick={this.props.openSettings}>{this.props.modalLanguage.settings}</button>
|
||||||
</div>
|
</div>
|
||||||
<div id='marketplace'>
|
<div id='marketplace'>
|
||||||
<div className="featured" style={{backgroundColor: this.state.featured.colour}}>
|
<div className='featured' style={{backgroundColor: this.state.featured.colour}}>
|
||||||
<p>{this.state.featured.title}</p>
|
<p>{this.state.featured.title}</p>
|
||||||
<h1>{this.state.featured.name}</h1>
|
<h1>{this.state.featured.name}</h1>
|
||||||
<button className="addToMue" onClick={() => window.location.href =
|
<button className='addToMue' onClick={() => window.location.href = this.state.featured.buttonLink}>{this.state.featured.buttonText}</button>
|
||||||
this.state.featured.buttonLink}>{this.state.featured.buttonText}</button>
|
|
||||||
</div>
|
</div>
|
||||||
<Items
|
<Items
|
||||||
title={this.props.language.photo_packs}
|
title={this.props.language.photo_packs}
|
||||||
seeMoreTitle={this.props.language.see_more}
|
seeMoreTitle={this.props.language.see_more}
|
||||||
items={this.state.photo_packs.slice(0, 3)}
|
items={this.state.photo_packs.slice(0, 3)}
|
||||||
toggleFunction={(input) => this.toggle('item', 'photo_packs', input)}
|
toggleFunction={(input) => this.toggle('item', 'photo_packs', input)}
|
||||||
seeMore={true}
|
|
||||||
seeMoreFunction={() => this.toggle('seemore', 'photo_packs')} />
|
seeMoreFunction={() => this.toggle('seemore', 'photo_packs')} />
|
||||||
<Items
|
<Items
|
||||||
title={this.props.language.preset_settings}
|
title={this.props.language.preset_settings}
|
||||||
seeMoreTitle={this.props.language.see_more}
|
seeMoreTitle={this.props.language.see_more}
|
||||||
items={this.state.settings.slice(0, 3)}
|
items={this.state.settings.slice(0, 3)}
|
||||||
toggleFunction={(input) => this.toggle('item', 'settings', input)}
|
toggleFunction={(input) => this.toggle('item', 'settings', input)}
|
||||||
seeMore={true}
|
|
||||||
seeMoreFunction={() => this.toggle('seemore', 'settings')} />
|
seeMoreFunction={() => this.toggle('seemore', 'settings')} />
|
||||||
<Items
|
<Items
|
||||||
title={this.props.language.quote_packs}
|
title={this.props.language.quote_packs}
|
||||||
seeMoreTitle={this.props.language.see_more}
|
seeMoreTitle={this.props.language.see_more}
|
||||||
items={this.state.quote_packs.slice(0, 3)}
|
items={this.state.quote_packs.slice(0, 3)}
|
||||||
toggleFunction={(input) => this.toggle('item', 'quote_packs', input)}
|
toggleFunction={(input) => this.toggle('item', 'quote_packs', input)}
|
||||||
seeMore={true}
|
|
||||||
seeMoreFunction={() => this.toggle('seemore', 'quote_packs')} />
|
seeMoreFunction={() => this.toggle('seemore', 'quote_packs')} />
|
||||||
<Items
|
<Items
|
||||||
title={this.props.language.themes}
|
title={this.props.language.themes}
|
||||||
seeMoreTitle={this.props.language.see_more}
|
seeMoreTitle={this.props.language.see_more}
|
||||||
items={this.state.themes.slice(0, 3)}
|
items={this.state.themes.slice(0, 3)}
|
||||||
toggleFunction={(input) => this.toggle('item', 'theme', input)}
|
toggleFunction={(input) => this.toggle('item', 'theme', input)}
|
||||||
seeMore={true}
|
|
||||||
seeMoreFunction={() => this.toggle('seemore', 'themes')} />
|
seeMoreFunction={() => this.toggle('seemore', 'themes')} />
|
||||||
</div>
|
</div>
|
||||||
<Item button={this.state.button} data={this.state.item_data} function={()=> this.toggle()} language={this.props.language.product} />
|
<Item
|
||||||
|
button={this.state.button}
|
||||||
|
data={this.state.item_data}
|
||||||
|
content={this.state.current_data}
|
||||||
|
function={() => this.toggle()} language={this.props.language.product}
|
||||||
|
/>
|
||||||
<div id='seemore'>
|
<div id='seemore'>
|
||||||
<ArrowBackIcon className='backArrow' onClick={() => this.toggle()} />
|
<ArrowBackIcon className='backArrow' onClick={() => this.toggle()} />
|
||||||
<Items
|
<Items
|
||||||
|
|||||||
@@ -1,69 +1,28 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ExpandMore from '@material-ui/icons/ExpandMore';
|
|
||||||
import SettingsFunctions from '../../modules/settingsFunctions';
|
import SettingsFunctions from '../../modules/settingsFunctions';
|
||||||
import Checkbox from './settings/Checkbox';
|
import Checkbox from './settings/Checkbox';
|
||||||
import Slider from './settings/Slider';
|
import Slider from './settings/Slider';
|
||||||
|
import Section from './settings/Section';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
import BackgroundSettings from './settings/sections/BackgroundSettings';
|
||||||
|
import ExperimentalSettings from './settings/sections/ExperimentalSettings';
|
||||||
|
import SearchSettings from './settings/sections/SearchSettings';
|
||||||
|
import LanguageSettings from './settings/sections/LanguageSettings';
|
||||||
|
|
||||||
export default class Settings extends React.PureComponent {
|
export default class Settings extends React.PureComponent {
|
||||||
resetItem(key) {
|
resetGreeting() {
|
||||||
switch (key) {
|
document.getElementById('greetingName').value = '';
|
||||||
case 'greetingName': document.getElementById('greetingName').value = ''; break;
|
|
||||||
case 'customBackgroundColour':
|
|
||||||
localStorage.setItem('customBackgroundColour', '');
|
|
||||||
document.getElementById('customBackgroundColour').enabled = 'false';
|
|
||||||
break;
|
|
||||||
case 'customBackground': document.getElementById('customBackground').value = ''; break;
|
|
||||||
case 'blur':
|
|
||||||
localStorage.setItem('blur', 0);
|
|
||||||
document.getElementById('blurRange').value = 0;
|
|
||||||
document.getElementById('blurAmount').innerText = '0';
|
|
||||||
break;
|
|
||||||
case 'customSearchEngine': document.getElementById('searchEngine').value = 'DuckDuckGo'; break;
|
|
||||||
default: console.log('[ERROR] resetItem requires a key!');
|
|
||||||
}
|
|
||||||
toast(this.props.toastLanguage.reset);
|
toast(this.props.toastLanguage.reset);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCurrent() {
|
updateCurrent() {
|
||||||
document.getElementById('greetingName').value = localStorage.getItem('greetingName');
|
document.getElementById('greetingName').value = localStorage.getItem('greetingName');
|
||||||
document.getElementById('customBackground').value = localStorage.getItem('customBackground');
|
|
||||||
document.getElementById('backgroundAPI').value = localStorage.getItem('backgroundAPI');
|
|
||||||
document.getElementById('language').value = localStorage.getItem('language');
|
document.getElementById('language').value = localStorage.getItem('language');
|
||||||
document.getElementById('searchEngine').value = localStorage.getItem('searchEngine');
|
|
||||||
// document.getElementById('backgroundImage').style.backgroundUrl = localStorage.getItem('customBackground');
|
|
||||||
|
|
||||||
for (const key of Object.keys(localStorage)) {
|
|
||||||
let value = localStorage.getItem(key);
|
|
||||||
|
|
||||||
if (key === 'blur') {
|
|
||||||
document.getElementById('blurAmount').innerText = value;
|
|
||||||
document.getElementById('blurRange').value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tag = document.getElementById(`${key}Status`);
|
|
||||||
|
|
||||||
if (tag) {
|
|
||||||
switch (value) {
|
|
||||||
case 'true': value = true; break;
|
|
||||||
case 'false': value = false; break;
|
|
||||||
default: value = true;
|
|
||||||
}
|
|
||||||
tag.checked = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localStorage.getItem('darkTheme') === 'true') {
|
if (localStorage.getItem('darkTheme') === 'true') {
|
||||||
document.getElementById('blurRange').style.background = '#535c68';
|
const choices = document.getElementsByClassName('choices');
|
||||||
document.getElementById('customBackground').style.color = 'white';
|
for (let i = 0; i < choices.length; i++) choices[i].style.backgroundColor = '#2f3542';
|
||||||
document.getElementById('backgroundAPI').style.color = 'white';
|
|
||||||
document.getElementById('searchEngine').style.color = 'white';
|
|
||||||
document.getElementById('language').style.color = 'white';
|
|
||||||
/*[1, 2, 3, 4, 5].forEach((index) => {
|
|
||||||
console.log(index)
|
|
||||||
document.getElementsByClassName('choices')[index].style.background = 'black';
|
|
||||||
})*/
|
|
||||||
document.getElementById('greetingName').style.color = 'white';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,34 +39,9 @@ export default class Settings extends React.PureComponent {
|
|||||||
reader.onload = (readerEvent) => {
|
reader.onload = (readerEvent) => {
|
||||||
const content = JSON.parse(readerEvent.target.result);
|
const content = JSON.parse(readerEvent.target.result);
|
||||||
for (const key of Object.keys(content)) localStorage.setItem(key, content[key]);
|
for (const key of Object.keys(content)) localStorage.setItem(key, content[key]);
|
||||||
toast('Imported settings!');
|
toast(this.props.toastLanguage.imported);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById('bg-input').onchange = (e) => {
|
|
||||||
const allowed = [ 'image/svg+xml', 'image/jpeg', 'image/png', 'image/webp', 'image/webm', 'image/gif' ];
|
|
||||||
const reader = new FileReader();
|
|
||||||
const file = e.target.files[0];
|
|
||||||
|
|
||||||
if (file.size > 2000000) return toast('File is over 2MB', '#ff0000', '#ffffff');
|
|
||||||
if (!allowed.includes(file.type)) return console.error(`expected xml, svg, png or jpeg, got ${file.type}`);
|
|
||||||
|
|
||||||
reader.addEventListener('load', (e) => {
|
|
||||||
localStorage.setItem('customBackground', e.target.result);
|
|
||||||
document.getElementById('customBackground').src = e.target.result;
|
|
||||||
document.getElementById('customBackground').value = e.target.result;
|
|
||||||
document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${localStorage.getItem('customBackground')}`);
|
|
||||||
document.getElementById('backgroundImage').style.backgroundImage = `url(${localStorage.getItem('customBackground')})`
|
|
||||||
});
|
|
||||||
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
};
|
};
|
||||||
/*const hex = localStorage.getItem('customBackgroundColour');
|
|
||||||
if (!hex === '') {
|
|
||||||
document.getElementById('customBackgroundColour').value = hex;
|
|
||||||
document.getElementById('customBackgroundHex').innerText = hex;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
|
document.getElementById('backgroundImage').classList.toggle('backgroundEffects');
|
||||||
document.getElementById('center').classList.toggle('backgroundEffects');
|
document.getElementById('center').classList.toggle('backgroundEffects');
|
||||||
@@ -119,146 +53,61 @@ export default class Settings extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// let expandClassList = '';
|
return (
|
||||||
//if (localStorage.getItem('animations') === 'true') expandClassList = 'all 0.5 ease 0s';
|
<div className='content'>
|
||||||
|
|
||||||
return <div className='content'>
|
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||||
<h1>{this.props.modalLanguage.title}</h1>
|
<h1>{this.props.modalLanguage.title}</h1>
|
||||||
<div className="tab">
|
<div className='tab'>
|
||||||
<button className="tablinks" onClick={this.props.openMarketplace}>{this.props.modalLanguage.marketplace}</button>
|
<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' onClick={this.props.openAddons}>{this.props.modalLanguage.addons}</button>
|
||||||
<button className="tablinks" id="active">{this.props.modalLanguage.settings}</button>
|
<button className='tablinks' id='active'>{this.props.modalLanguage.settings}</button>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br/>
|
||||||
<div className='columns'>
|
|
||||||
<div className='section'>
|
<div className='columns'>
|
||||||
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[0], document.getElementsByClassName('expandIcons')[0])}>{this.props.language.time.title}</h4>
|
<Section title={this.props.language.time.title} name='time'>
|
||||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[0], document.getElementsByClassName('expandIcons')[0])} />
|
|
||||||
<Slider name='time' />
|
|
||||||
<li className='extraSettings'>
|
|
||||||
<Checkbox name='seconds' text={this.props.language.time.seconds} />
|
<Checkbox name='seconds' text={this.props.language.time.seconds} />
|
||||||
<Checkbox name='24hour' text={this.props.language.time.twentyfourhour} />
|
<Checkbox name='24hour' text={this.props.language.time.twentyfourhour} />
|
||||||
<Checkbox name='ampm' text={this.props.language.time.ampm} />
|
<Checkbox name='ampm' text={this.props.language.time.ampm} />
|
||||||
<Checkbox name='zero' text={this.props.language.time.zero} />
|
<Checkbox name='zero' text={this.props.language.time.zero} />
|
||||||
<Checkbox name='analog' text={this.props.language.time.analog} />
|
<Checkbox name='analog' text={this.props.language.time.analog} />
|
||||||
</li>
|
</Section>
|
||||||
</div>
|
<Section title={this.props.language.greeting.title} name='greeting'>
|
||||||
<div className='section'>
|
<Checkbox name='events' text={this.props.language.greeting.events} />
|
||||||
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[1], document.getElementsByClassName('expandIcons')[1])}>{this.props.language.greeting.title}</h4>
|
<Checkbox name='defaultGreetingMessage' text={this.props.language.greeting.default} />
|
||||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[1], document.getElementsByClassName('expandIcons')[1])} />
|
|
||||||
<Slider name='greeting' />
|
|
||||||
<li className='extraSettings'>
|
|
||||||
<Checkbox name='events' text={this.props.language.greeting.events} />
|
|
||||||
<Checkbox name='defaultGreetingMessage' text={this.props.language.greeting.default} />
|
|
||||||
<ul>
|
<ul>
|
||||||
<p>{this.props.language.greeting.name} <span className='modalLink' onClick={() => this.resetItem('greetingName')}>Reset</span></p>
|
<p>{this.props.language.greeting.name} <span className='modalLink' onClick={() => this.resetGreeting()}>{this.props.language.reset}</span></p>
|
||||||
<input type='text' id='greetingName'></input>
|
<input type='text' id='greetingName'></input>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</Section>
|
||||||
</div>
|
<Section title={this.props.language.quote.title} name='quote'>
|
||||||
<div className='section'>
|
|
||||||
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[2], document.getElementsByClassName('expandIcons')[2])}>{this.props.language.quote.title}</h4>
|
|
||||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[2], document.getElementsByClassName('expandIcons')[2])} />
|
|
||||||
<Slider name='quote' />
|
|
||||||
<li className='extraSettings'>
|
|
||||||
<Checkbox name='copyButton' text={this.props.language.quote.copy} />
|
<Checkbox name='copyButton' text={this.props.language.quote.copy} />
|
||||||
</li>
|
<Checkbox name='tweetButton' text={this.props.language.quote.tweet} />
|
||||||
|
</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 class='nodropdown'>{this.props.language.offline}</h4>
|
||||||
|
<Slider name='offlineMode'/>
|
||||||
|
</div>
|
||||||
|
<div className='section'>
|
||||||
|
<h4 class='nodropdown'>{this.props.language.experimental.dark}</h4>
|
||||||
|
<Slider name='darkTheme'/>
|
||||||
|
</div>
|
||||||
|
<ExperimentalSettings language={this.props.language} />
|
||||||
|
<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='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>
|
||||||
<div className='section'>
|
|
||||||
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[3], document.getElementsByClassName('expandIcons')[3])}>{this.props.language.background.title}</h4>
|
|
||||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[3], document.getElementsByClassName('expandIcons')[3])} />
|
|
||||||
<Slider name='background' override='customBackground' />
|
|
||||||
<li className='extraSettings'>
|
|
||||||
<ul>
|
|
||||||
<label htmlFor='8'>{this.props.language.background.API} </label>
|
|
||||||
<label className='dropdown'>
|
|
||||||
<select className='select-css' name='8' id='backgroundAPI' onChange={() => localStorage.setItem('backgroundAPI', document.getElementById('backgroundAPI').value)}>
|
|
||||||
<option value='mue'>Mue</option>
|
|
||||||
<option value='unsplash'>Unsplash</option>
|
|
||||||
{ /* <option value='custom'>Custom</option> */ }
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<p>{this.props.language.background.blur} (<span id='blurAmount'></span>%) <span className='modalLink' onClick={() => this.resetItem('blur')}>Reset</span></p>
|
|
||||||
<input className='range' type='range' min='0' max='100' id='blurRange' onInput={() => document.getElementById('blurAmount').innerText = document.getElementById('blurRange').value} />
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<p>{this.props.language.background.customURL} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>Reset</span></p>
|
|
||||||
<input type='text' id='customBackground'></input>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<p>{this.props.language.background.custombackground} <span className='modalLink' onClick={() => this.resetItem('customBackground')}>Reset</span></p>
|
|
||||||
<button className='uploadbg' onClick={() => document.getElementById('bg-input').click()}>Upload</button>
|
|
||||||
<input id='bg-input' type='file' name='name' className='hidden' />
|
|
||||||
</ul>
|
|
||||||
{ /* <ul>
|
|
||||||
<p>{this.props.language.background.customcolour} <span className='modalLink' onClick={() => this.resetItem('customBackgroundColour')}>Reset</span></p>
|
|
||||||
<input name='colour' type='color' id='customBackgroundColour' onChange={() => document.getElementById('customBackgroundHex').innerText = document.getElementById('customBackgroundColour').value}></input>
|
|
||||||
<label htmlFor='colour' id='customBackgroundHex'>#00000</label>
|
|
||||||
</ul> */ }
|
|
||||||
</li>
|
|
||||||
</div>
|
|
||||||
<div className='section'>
|
|
||||||
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[4], document.getElementsByClassName('expandIcons')[4])}>{this.props.language.searchbar.title}</h4>
|
|
||||||
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[4], document.getElementsByClassName('expandIcons')[4])} />
|
|
||||||
<Slider name='searchBar' />
|
|
||||||
<li className='extraSettings'>
|
|
||||||
<ul>
|
|
||||||
<label htmlFor='4'>{this.props.language.searchbar.searchengine} </label>
|
|
||||||
<select className='select-css' name='4' id='searchEngine' onChange={() => SettingsFunctions.setSearchEngine(document.getElementById('searchEngine').value)}>
|
|
||||||
<option value='duckduckgo'>DuckDuckGo</option>
|
|
||||||
<option value='google'>Google</option>
|
|
||||||
<option value='bing'>Bing</option>
|
|
||||||
<option value='yahoo'>Yahoo</option>
|
|
||||||
<option value='ecosia'>Ecosia</option>
|
|
||||||
<option value='yandex'>Yandex</option>
|
|
||||||
<option value='qwant'>Qwant</option>
|
|
||||||
<option value='ask'>Ask</option>
|
|
||||||
<option value='startpage'>Startpage</option>
|
|
||||||
{/* <option value='custom'>Custom</option> */}
|
|
||||||
</select>
|
|
||||||
</ul>
|
|
||||||
<ul id='searchEngineInput' style={{ display: 'none' }}>
|
|
||||||
<p style={{"marginTop": "0px"}}>Custom Search URL <span className='modalLink' onClick={() => this.resetItem('customSearchEngine')}>Reset</span></p>
|
|
||||||
<input type='text' id='customSearchEngine'></input>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
</div>
|
|
||||||
<div className='section'>
|
|
||||||
<h4>{this.props.language.offline}</h4>
|
|
||||||
<Slider name='offlineMode' />
|
|
||||||
</div>
|
|
||||||
<h3>{this.props.language.experimental.title}</h3>
|
|
||||||
<div className='section'>
|
|
||||||
<h4>{this.props.language.experimental.webp}</h4>
|
|
||||||
<Slider name='webp' />
|
|
||||||
</div>
|
|
||||||
<div className='section'>
|
|
||||||
<h4>{this.props.language.experimental.dark}</h4>
|
|
||||||
<Slider name='darkTheme' />
|
|
||||||
</div>
|
|
||||||
<div className='section'>
|
|
||||||
<h4>{this.props.language.experimental.animations}</h4>
|
|
||||||
<Slider name='animations' />
|
|
||||||
</div>
|
|
||||||
<div className='section'>
|
|
||||||
<h4 htmlFor='9'>{this.props.language.language} </h4>
|
|
||||||
<select className='select-css' name='9' id='language' onChange={() => localStorage.setItem('language', document.getElementById('language').value)}>
|
|
||||||
<option className='choices' value='en'>English</option>
|
|
||||||
<option className='choices' value='nl'>Nederlands</option>
|
|
||||||
<option className='choices' value='fr'>Français</option>
|
|
||||||
<option className='choices' value='no'>Norsk</option>
|
|
||||||
<option className='choices' value='ru'>Russian</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<button className='apply' onClick={() => SettingsFunctions.saveStuff()}>{this.props.language.apply}</button>
|
|
||||||
<button className='reset' onClick={() => this.props.setDefaultSettings()}>{this.props.language.reset}</button>
|
|
||||||
<button className='export' onClick={() => SettingsFunctions.exportSettings()}>{this.props.language.export}</button>
|
|
||||||
<button className='import' onClick={() => document.getElementById('file-input').click()}>{this.props.language.import}</button>
|
|
||||||
<input id='file-input' type='file' name='name' className='hidden' />
|
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ export default class Update extends React.PureComponent {
|
|||||||
super(...args);
|
super(...args);
|
||||||
this.state = {
|
this.state = {
|
||||||
title: this.props.language.title,
|
title: this.props.language.title,
|
||||||
date: '26/08/2020',
|
date: '???',
|
||||||
content: this.props.language.title
|
content: this.props.language.title,
|
||||||
|
url: '',
|
||||||
|
author: 'Mue'
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,11 +20,14 @@ export default class Update extends React.PureComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try { // Get update log from the API
|
try { // Get update log from the API
|
||||||
let data = await fetch(Constants.API_URL + '/getUpdate');
|
const data = await (await fetch(Constants.API_URL + '/getUpdate')).json();
|
||||||
data = await data.json();
|
|
||||||
this.setState({
|
this.setState({
|
||||||
title: data.title,
|
title: data.title,
|
||||||
content: data.content
|
content: data.content,
|
||||||
|
date: data.published,
|
||||||
|
image: data.image,
|
||||||
|
url: data.url,
|
||||||
|
author: data.author
|
||||||
});
|
});
|
||||||
} catch (e) { // If it fails, we send an error
|
} catch (e) { // If it fails, we send an error
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -33,16 +38,16 @@ export default class Update extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
localStorage.setItem('viewedUpdate', true);
|
|
||||||
this.getUpdate();
|
this.getUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div className='updateContent'>
|
return <div className='updateContent'>
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||||
<h1 style={{ 'marginBottom':'-10px' }} dangerouslySetInnerHTML={{__html: this.state.title}}></h1>
|
<h1 style={{ 'marginBottom':'-10px' }}>{this.state.title}</h1>
|
||||||
<h5 style={{ 'lineHeight':'0px' }}> By Mue • <span dangerouslySetInnerHTML={{__html: this.state.date}}></span></h5>
|
<h5 style={{ 'lineHeight':'0px' }}> By {this.state.author} • {this.state.date}</h5>
|
||||||
<p dangerouslySetInnerHTML={{__html: this.state.content}}></p>
|
<img draggable='false' src={this.state.image} alt='Update'></img>
|
||||||
|
<p dangerouslySetInnerHTML={{__html: this.state.content + `<br/><p>Read on the blog here: <a target='_blank' class='modalLink' href='${this.state.url}'>${this.state.url}</a></p>`}}></p>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,13 +5,13 @@ export default class Welcome extends React.PureComponent {
|
|||||||
render() {
|
render() {
|
||||||
return <div className='welcomeContent'>
|
return <div className='welcomeContent'>
|
||||||
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
<span className='closeModal' onClick={this.props.modalClose}>×</span>
|
||||||
<div className="welcomeModalText">
|
<div className='welcomeModalText'>
|
||||||
<h2 className="subtitle">Welcome to</h2>
|
<h2 className='subtitle'>Welcome to</h2>
|
||||||
<h1 className="welcometitle">Mue Tab</h1>
|
<h1 className='welcometitle'>Mue Tab</h1>
|
||||||
<img alt="celebration" style={{"height": "200px", "width": "auto"}} src="./././icons/undraw_celebration.svg" />
|
<img alt='celebration' style={{'height': '200px', 'width': 'auto'}} src='./././icons/undraw_celebration.svg' />
|
||||||
<h2 className="subtitle">Information</h2>
|
<h2 className='subtitle'>Information</h2>
|
||||||
<p>Thank you for downloading Mue Tab,<br/> we hope you enjoy your time with our extension.</p>
|
<p>Thank you for downloading Mue Tab,<br/> we hope you enjoy your time with our extension.</p>
|
||||||
<h2 className="subtitle">Tutorials</h2>
|
<h2 className='subtitle'>Tutorials</h2>
|
||||||
<a href=''>General Start</a>
|
<a href=''>General Start</a>
|
||||||
<br/>
|
<br/>
|
||||||
<a href='https://blog.muetab.xyz/welcome-to-marketplace/'>Marketplace</a>
|
<a href='https://blog.muetab.xyz/welcome-to-marketplace/'>Marketplace</a>
|
||||||
@@ -19,12 +19,12 @@ export default class Welcome extends React.PureComponent {
|
|||||||
<a href=''>Submitting Photos</a>
|
<a href=''>Submitting Photos</a>
|
||||||
<br/>
|
<br/>
|
||||||
<a href=''>Settings</a>
|
<a href=''>Settings</a>
|
||||||
<h2 className="subtitle">Support</h2>
|
<h2 className='subtitle'>Support</h2>
|
||||||
<img alt="twitter" href="https://twitter.com/getmue" className="icon" src="./././icons/iconmonstr-twitter.svg"/>
|
{/* <img alt='twitter' href='https://twitter.com/getmue' className='icon' src=''/>
|
||||||
<img alt="discord" href="https://discord.gg/kJsufA9" className="icon" src="https://cdn.discordapp.com/attachments/252071498397777921/747860127171739758/Discord-Logo-Black.svg"/>
|
<img alt='discord' href='https://discord.gg/kJsufA9' className='icon' src=''/> */}
|
||||||
<EmailIcon />
|
<EmailIcon />
|
||||||
<br/>
|
<br/>
|
||||||
<button className="close" onClick={this.props.modalClose}>Close</button>
|
<button className='close' onClick={this.props.modalClose}>Close</button>
|
||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,19 @@ import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
|||||||
|
|
||||||
export default class Item extends React.PureComponent {
|
export default class Item extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
|
//if (!this.props.data.icon) return null;
|
||||||
|
let warningHTML;
|
||||||
|
try { // For some reason it breaks sometimes so we use try/catch
|
||||||
|
if (this.props.content.content.data.quote_api) {
|
||||||
|
warningHTML = <div className='productInformation'>
|
||||||
|
<ul>
|
||||||
|
<li className='header'>{this.props.language.quoteWarning.title}</li>
|
||||||
|
<li id='updated'>{this.props.language.quoteWarning.description}</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='item'>
|
<div id='item'>
|
||||||
<br/>
|
<br/>
|
||||||
@@ -11,32 +24,33 @@ export default class Item extends React.PureComponent {
|
|||||||
<h1>{this.props.data.name}</h1>
|
<h1>{this.props.data.name}</h1>
|
||||||
{this.props.button}
|
{this.props.button}
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<img alt="product" src={'https://external-content.duckduckgo.com/iu/?u=' + this.props.data.icon} />
|
<img alt='product' draggable={false} src={'https://external-content.duckduckgo.com/iu/?u=' + this.props.data.icon} />
|
||||||
<div className="informationContainer">
|
<div className='informationContainer'>
|
||||||
<div className="productInformation">
|
<div className='productInformation'>
|
||||||
<h4>{this.props.language.information}</h4>
|
<h4>{this.props.language.information}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
<br/>
|
<br/>
|
||||||
<li className="header">{this.props.language.last_updated}</li>
|
<li className='header'>{this.props.language.last_updated}</li>
|
||||||
<li>{this.props.data.updated}</li>
|
<li>{this.props.data.updated}</li>
|
||||||
<br/>
|
<br/>
|
||||||
<li className="header">{this.props.language.version}</li>
|
<li className='header'>{this.props.language.version}</li>
|
||||||
<li>{this.props.data.version}</li>
|
<li>{this.props.data.version}</li>
|
||||||
<br/>
|
<br/>
|
||||||
<li className="header">{this.props.language.author}</li>
|
<li className='header'>{this.props.language.author}</li>
|
||||||
<li>{this.props.data.author}</li>
|
<li>{this.props.data.author}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className="productInformation">
|
<div className='productInformation'>
|
||||||
<ul>
|
<ul>
|
||||||
<li className="header">{this.props.language.notice.title}</li>
|
<li className='header'>{this.props.language.notice.title}</li>
|
||||||
<li id='updated'>{this.props.language.notice.description}</li>
|
<li id='updated'>{this.props.language.notice.description}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{warningHTML}
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
<h1>{this.props.language.overview}</h1>
|
<h1>{this.props.language.overview}</h1>
|
||||||
<p className="description" dangerouslySetInnerHTML={{__html: this.props.data.description}}></p>
|
<p className='description' dangerouslySetInnerHTML={{__html: this.props.data.description}}></p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,17 @@ import React from 'react';
|
|||||||
export default class Items extends React.PureComponent {
|
export default class Items extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
let seeMoreHTML;
|
let seeMoreHTML;
|
||||||
if (this.props.seeMore === true) seeMoreHTML = <button className='addToMue seemore' onClick={this.props.seeMoreFunction}>{this.props.seeMoreTitle}</button>;
|
if (this.props.seeMoreFunction) seeMoreHTML = <button className='addToMue seemore' onClick={this.props.seeMoreFunction}>{this.props.seeMoreTitle}</button>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{seeMoreHTML}
|
{seeMoreHTML}
|
||||||
<h1>{this.props.title}</h1>
|
<h1>{this.props.title}</h1>
|
||||||
<div className="items">
|
<div className='items'>
|
||||||
{this.props.items.map((item) =>
|
{this.props.items.map((item) =>
|
||||||
<div className="item" onClick={() => this.props.toggleFunction(item.name)}>
|
<div className='item' onClick={() => this.props.toggleFunction(item.name)}>
|
||||||
<img alt="icon" src={'https://external-content.duckduckgo.com/iu/?u=' + item.icon_url} />
|
<img alt='icon' draggable={false} src={'https://external-content.duckduckgo.com/iu/?u=' + item.icon_url} />
|
||||||
<div className="details">
|
<div className='details'>
|
||||||
<h4>{item.display_name}</h4>
|
<h4>{item.display_name}</h4>
|
||||||
<p>{item.author}</p>
|
<p>{item.author}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,33 +7,20 @@ export default class Checkbox extends React.PureComponent {
|
|||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
super(...args);
|
super(...args);
|
||||||
this.state = {
|
this.state = {
|
||||||
checked: true
|
checked: (localStorage.getItem(this.props.name) === 'true')
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(name) {
|
||||||
|
SettingsFunctions.setItem(name);
|
||||||
|
this.setState({ checked: (this.state.checked === true) ? false : true });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const handleChange = () => {
|
|
||||||
SettingsFunctions.setItem(this.props.name);
|
|
||||||
let checked;
|
|
||||||
if (this.state.checked === true) checked = false;
|
|
||||||
else checked = true;
|
|
||||||
this.setState({ checked: checked });
|
|
||||||
}
|
|
||||||
|
|
||||||
let value = localStorage.getItem(this.props.name);
|
|
||||||
|
|
||||||
switch (value) {
|
|
||||||
case 'true': value = true; break;
|
|
||||||
case 'false': value = false; break;
|
|
||||||
default: value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ checked: value });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<CheckboxUI name="checkedB" color="primary" checked={this.state.checked} onChange={handleChange} />}
|
control={<CheckboxUI name='checkedB' color='primary' checked={this.state.checked} onChange={() => this.handleChange(this.props.name)} />}
|
||||||
label={this.props.text}
|
label={this.props.text}
|
||||||
/>
|
/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|||||||
26
src/components/modals/settings/Section.jsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import SettingsFunctions from '../../../modules/settingsFunctions';
|
||||||
|
import Slider from './Slider';
|
||||||
|
import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||||
|
|
||||||
|
export default class Section extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
let extraHTML, expandMore;
|
||||||
|
if (this.props.children) {
|
||||||
|
extraHTML = <li className={'extraSettings ' + this.props.title}>{this.props.children}</li>
|
||||||
|
expandMore = <ExpandMore
|
||||||
|
style={{ 'transition': 'all 0.5s ease 0s' }}
|
||||||
|
className={`expandIcons expand${this.props.title}`}
|
||||||
|
onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName(this.props.title)[0], document.getElementsByClassName('expand' + this.props.title)[0])}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className='section'>
|
||||||
|
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName(this.props.title)[0], document.getElementsByClassName('expand' + this.props.title)[0])}>{this.props.title}</h4>
|
||||||
|
{expandMore}
|
||||||
|
<Slider name={this.props.name} />
|
||||||
|
{extraHTML}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,24 @@ import React from 'react';
|
|||||||
import SettingsFunctions from '../../../modules/settingsFunctions';
|
import SettingsFunctions from '../../../modules/settingsFunctions';
|
||||||
|
|
||||||
export default class Slider extends React.PureComponent {
|
export default class Slider extends React.PureComponent {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.state = {
|
||||||
|
checked: (localStorage.getItem(this.props.name) === 'true')
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange(name) {
|
||||||
|
SettingsFunctions.setItem(name);
|
||||||
|
this.setState({ checked: (this.state.checked === true) ? false : true });
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let setText = this.props.name;
|
let setText = (this.props.override) ? this.props.override : this.props.name;
|
||||||
if (this.props.override) setText = this.props.override;
|
|
||||||
return (
|
return (
|
||||||
<label className="switch">
|
<label className='switch'>
|
||||||
<input type="checkbox" onClick={() => SettingsFunctions.setItem(setText)} id={this.props.name + 'Status'} />
|
<input type='checkbox' checked={this.state.checked} onChange={() => this.handleChange(setText)} />
|
||||||
<span className="slider"></span>
|
<span className='slider'></span>
|
||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
export default class BackgroundSettings extends React.PureComponent {
|
||||||
|
resetItem(key) {
|
||||||
|
switch (key) {
|
||||||
|
case 'customBackgroundColour':
|
||||||
|
localStorage.setItem('customBackgroundColour', '');
|
||||||
|
document.getElementById('customBackgroundHex').textContent = 'Disabled';
|
||||||
|
break;
|
||||||
|
case 'customBackground': document.getElementById('customBackground').value = ''; break;
|
||||||
|
case 'blur':
|
||||||
|
localStorage.setItem('blur', 0);
|
||||||
|
document.getElementById('blurRange').value = 0;
|
||||||
|
document.getElementById('blurAmount').innerText = '0';
|
||||||
|
break;
|
||||||
|
case 'brightness':
|
||||||
|
localStorage.setItem('brightness', 100);
|
||||||
|
document.getElementById('brightnessRange').value = 100;
|
||||||
|
document.getElementById('brightnessAmount').innerText = '100';
|
||||||
|
break;
|
||||||
|
default: toast('resetItem requires a key!');
|
||||||
|
}
|
||||||
|
toast(this.props.toastLanguage.reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
document.getElementById('bg-input').onchange = (e) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
const file = e.target.files[0];
|
||||||
|
|
||||||
|
if (file.size > 2000000) return toast('File is over 2MB', '#ff0000', '#ffffff');
|
||||||
|
|
||||||
|
reader.addEventListener('load', (e) => {
|
||||||
|
localStorage.setItem('customBackground', e.target.result);
|
||||||
|
document.getElementById('customBackground').src = e.target.result;
|
||||||
|
document.getElementById('customBackground').value = e.target.result;
|
||||||
|
});
|
||||||
|
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hex = localStorage.getItem('customBackgroundColour');
|
||||||
|
if (hex !== '') {
|
||||||
|
document.getElementById('customBackgroundColour').value = hex;
|
||||||
|
document.getElementById('customBackgroundHex').innerText = hex;
|
||||||
|
} else document.getElementById('customBackgroundHex').innerText = 'Disabled';
|
||||||
|
|
||||||
|
const blur = localStorage.getItem('blur');
|
||||||
|
const brightness = localStorage.getItem('brightness');
|
||||||
|
|
||||||
|
document.getElementById('blurAmount').innerText = blur;
|
||||||
|
document.getElementById('blurRange').value = blur;
|
||||||
|
|
||||||
|
document.getElementById('brightnessAmount').innerText = brightness;
|
||||||
|
document.getElementById('brightnessRange').value = brightness;
|
||||||
|
|
||||||
|
document.getElementById('customBackground').value = localStorage.getItem('customBackground');
|
||||||
|
document.getElementById('backgroundAPI').value = localStorage.getItem('backgroundAPI');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
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} (<span id='blurAmount'></span>%) <span className='modalLink' onClick={() => this.resetItem('blur')}>{this.props.language.reset}</span></p>
|
||||||
|
<input className='range' type='range' min='0' max='100' id='blurRange' onInput={() => document.getElementById('blurAmount').innerText = document.getElementById('blurRange').value} />
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<p>{this.props.language.background.brightness} (<span id='brightnessAmount'></span>%) <span className='modalLink' onClick={() => this.resetItem('brightness')}>{this.props.language.reset}</span></p>
|
||||||
|
<input className='range' type='range' min='0' max='100' id='brightnessRange' onInput={() => document.getElementById('brightnessAmount').innerText = document.getElementById('brightnessRange').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 name='colour' type='color' id='customBackgroundColour' onChange={() => document.getElementById('customBackgroundHex').innerText = document.getElementById('customBackgroundColour').value}></input>
|
||||||
|
<label htmlFor='colour' id='customBackgroundHex'>#00000</label>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Checkbox from '../Checkbox';
|
||||||
|
import ExpandMore from '@material-ui/icons/ExpandMore';
|
||||||
|
import SettingsFunctions from '../../../../modules/settingsFunctions';
|
||||||
|
|
||||||
|
export default class ExperimentalSettings extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className='section'>
|
||||||
|
<h4 onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[5], document.getElementsByClassName('expandIcons')[5])}>{this.props.language.experimental.title}</h4>
|
||||||
|
<ExpandMore style={{ 'transition': 'all 0.5s ease 0s' }} className='expandIcons' onClick={() => SettingsFunctions.toggleExtra(document.getElementsByClassName('extraSettings')[5], document.getElementsByClassName('expandIcons')[5])} />
|
||||||
|
<li className='extraSettings'>
|
||||||
|
<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} />
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/components/modals/settings/sections/LanguageSettings.jsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default class LanguageSettings extends React.PureComponent {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className='section'>
|
||||||
|
<h4 htmlFor='language'>{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>
|
||||||
|
<option className='choices' value='fr'>Français</option>
|
||||||
|
<option className='choices' value='no'>Norsk</option>
|
||||||
|
<option className='choices' value='ru'>Pусский</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/components/modals/settings/sections/SearchSettings.jsx
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import SettingsFunctions from '../../../../modules/settingsFunctions';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
const searchEngines = require('../../../../modules/searchEngines.json');
|
||||||
|
|
||||||
|
export default class SearchSettings extends React.PureComponent {
|
||||||
|
resetSearch() {
|
||||||
|
localStorage.removeItem('customSearchEngine');
|
||||||
|
document.getElementById('customSearchEngine').value = '';
|
||||||
|
toast(this.props.toastLanguage.reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (localStorage.getItem('searchEngine') === 'custom') {
|
||||||
|
const input = document.getElementById('searchEngineInput');
|
||||||
|
input.style.display = 'block';
|
||||||
|
input.enabled = 'true';
|
||||||
|
document.getElementById('customSearchEngine').value = localStorage.getItem('customSearchEngine');
|
||||||
|
} else localStorage.removeItem('customSearchEngine');
|
||||||
|
|
||||||
|
document.getElementById('searchEngine').value = localStorage.getItem('searchEngine');
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,79 +1,87 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import supportsWebP from 'supports-webp';
|
|
||||||
import * as Constants from '../../modules/constants';
|
import * as Constants from '../../modules/constants';
|
||||||
|
|
||||||
export default class Background extends React.PureComponent {
|
export default class Background extends React.PureComponent {
|
||||||
doOffline() {
|
setBackground(url, colour, credit) { // Sets the attributes of the background image
|
||||||
const photo = Math.floor(Math.random() * (Constants.OFFLINE_IMAGES - 1 + 1)) + 1; // There are 20 images in the offline-images folder
|
const background = colour ? `background-color: ${colour};` : `background-image: url(${url});`;
|
||||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
|
||||||
|
|
||||||
let photographer; // Photographer credit
|
document.querySelector('#backgroundImage').setAttribute(
|
||||||
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
|
'style',
|
||||||
else switch (photo) {
|
`${background};
|
||||||
case 1: photographer = 'Tirachard Kumtanom'; break;
|
-webkit-filter: blur(${localStorage.getItem('blur')}px);
|
||||||
case 4: photographer = 'Sohail Na'; break;
|
-webkit-filter: brightness(${localStorage.getItem('brightness')}%);`
|
||||||
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
|
if (credit === 'false') document.querySelector('#credits').style.display = 'none'; // Hide the credit
|
||||||
let credit = document.getElementById('photographer');
|
|
||||||
credit.innerText = `${credit.innerText} ${photographer} (Pexels)`; // Set the credit
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setBackground() {
|
setCredit(photographer) {
|
||||||
|
document.querySelector('#photographer').append(` ${photographer}`); // Append credit
|
||||||
|
document.getElementById('credit').textContent = photographer;
|
||||||
|
}
|
||||||
|
|
||||||
|
doOffline() { // Handles setting the background if the user is offline
|
||||||
|
const offlineImages = require('../../modules/offlineImages.json');
|
||||||
|
const photographers = Object.keys(offlineImages); // Get all photographers from the keys in offlineImages.json
|
||||||
|
const photographer = photographers[Math.floor(Math.random() * photographers.length)]; // Select a random photographer from the keys
|
||||||
|
const randomImage = offlineImages[photographer].photo[
|
||||||
|
Math.floor(Math.random() * offlineImages[photographer].photo.length)
|
||||||
|
]; // Select a random image
|
||||||
|
const url = `../offline-images/${randomImage}.jpeg`;
|
||||||
|
|
||||||
|
this.setBackground(url);
|
||||||
|
this.setCredit(photographer);
|
||||||
|
|
||||||
|
document.querySelector('#backgroundCredits').style.display = 'none'; // Hide the location icon
|
||||||
|
}
|
||||||
|
|
||||||
|
async determineMode() {
|
||||||
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
||||||
|
|
||||||
const photoPack = JSON.parse(localStorage.getItem('photo_packs'));
|
const photoPack = JSON.parse(localStorage.getItem('photo_packs'));
|
||||||
if (photoPack) {
|
const customBackgroundColour = localStorage.getItem('customBackgroundColour');
|
||||||
let background = photoPack[Math.floor(Math.random() * photoPack.length)];
|
const customBackground = localStorage.getItem('customBackground');
|
||||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
const favourited = JSON.parse(localStorage.getItem('favourite'));
|
||||||
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 (favourited) {
|
||||||
if (colour) {
|
this.setBackground(favourited.url, null, 'true');
|
||||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
this.setCredit(favourited.credit);
|
||||||
document.getElementById('photographer').style.display = 'none';
|
document.getElementById('location').textContent = favourited.location;
|
||||||
return document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-color: ${colour}`); // Set background and blur etc
|
} else if (photoPack) {
|
||||||
}
|
const randomPhoto = photoPack[Math.floor(Math.random() * photoPack.length)];
|
||||||
|
this.setBackground(randomPhoto.url.default, null, randomPhoto.photographer);
|
||||||
const custom = localStorage.getItem('customBackground');
|
this.setCredit(randomPhoto.photographer);
|
||||||
if (custom !== '') {
|
document.getElementById('location').textContent = randomPhoto.location;
|
||||||
document.getElementById('backgroundCredits').style.display = 'none'; // Hide the location icon
|
} else if (customBackgroundColour) {
|
||||||
document.getElementById('photographer').style.display = 'none';
|
this.setBackground(null, customBackgroundColour, 'false');
|
||||||
return document.getElementById('backgroundImage').setAttribute('style', `-webkit-filter:blur(${localStorage.getItem('blur')}px); background-image: url(${custom})`); // Set background and blur etc
|
} else if (customBackground !== '') { // Local
|
||||||
} else {
|
this.setBackground(customBackground, null, 'false');
|
||||||
|
} else { // Online
|
||||||
try { // First we try and get an image from the API...
|
try { // First we try and get an image from the API...
|
||||||
let requestURL;
|
|
||||||
const enabled = localStorage.getItem('webp');
|
const enabled = localStorage.getItem('webp');
|
||||||
const backgroundAPI = localStorage.getItem('backgroundAPI');
|
let requestURL;
|
||||||
let data;
|
|
||||||
|
|
||||||
switch (backgroundAPI) {
|
switch (localStorage.getItem('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':
|
case 'unsplash':
|
||||||
requestURL = 'https://unsplash.muetab.xyz/getImage';
|
requestURL = `${Constants.UNSPLASH_URL}/getImage`;
|
||||||
break;
|
break;
|
||||||
default:
|
default: // Defaults to Mue
|
||||||
if (await supportsWebP && enabled === 'true') requestURL = Constants.API_URL +'/getImage?webp=true';
|
if (localStorage.getItem('supportswebp') === 'true' && enabled === 'true') requestURL = `${Constants.API_URL}/getImage?webp=true`;
|
||||||
else requestURL = Constants.API_URL + '/getImage?category=Outdoors';
|
else requestURL = `${Constants.API_URL}/getImage?category=Outdoors`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = await fetch(requestURL);
|
const data = await (await fetch(requestURL)).json(); // Fetch JSON data from 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
|
if (data.statusCode === 429) {
|
||||||
let credit = document.getElementById('photographer');
|
this.doOffline(); // If we hit the rate limit, fallback to local images
|
||||||
credit.innerText = `${credit.innerText} ${data.photographer}`; // Set the credit
|
} else { // Otherwise, set the background and credit from remote data
|
||||||
document.getElementById('location').innerText = `${data.location}`; // Set the location tooltip
|
this.setBackground(data.file);
|
||||||
|
this.setCredit(data.photographer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.location.replace(/[null]+/g, '') === ' ') return document.querySelector('#backgroundCredits').style.display = 'none';
|
||||||
|
document.getElementById('location').innerText = `${data.location.replace('null', '')}`; // Set the location tooltip
|
||||||
} catch (e) { // ..and if that fails we load one locally
|
} catch (e) { // ..and if that fails we load one locally
|
||||||
this.doOffline();
|
this.doOffline();
|
||||||
}
|
}
|
||||||
@@ -81,12 +89,12 @@ export default class Background extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (localStorage.getItem('background') === 'false') return document.getElementById('backgroundCredits').style.display = 'none';
|
if (localStorage.getItem('background') === 'false') return document.querySelector('#credits').style.display = 'none'; // Hide the credit
|
||||||
if (localStorage.getItem('animations') === 'true') document.getElementById('backgroundImage').classList.add('fade-in');
|
if (localStorage.getItem('animations') === 'true') document.querySelector('#backgroundImage').classList.add('fade-in');
|
||||||
this.setBackground();
|
this.determineMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div id='backgroundImage'></div>;
|
return <div id='backgroundImage'></div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export default class Clock extends React.PureComponent {
|
|||||||
if (localStorage.getItem('24hour') === 'true') {
|
if (localStorage.getItem('24hour') === 'true') {
|
||||||
let time = '';
|
let time = '';
|
||||||
if (zero === 'false') time = `${now.getHours()}:${now.getMinutes()}${sec}`;
|
if (zero === 'false') time = `${now.getHours()}:${now.getMinutes()}${sec}`;
|
||||||
|
|
||||||
else time = `${('00' + now.getHours()).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
|
else time = `${('00' + now.getHours()).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
|
||||||
this.setState({
|
this.setState({
|
||||||
time: time
|
time: time
|
||||||
@@ -51,6 +52,7 @@ export default class Clock extends React.PureComponent {
|
|||||||
let time = '';
|
let time = '';
|
||||||
if (zero === 'false') time = `${hours}:${now.getMinutes()}${sec}`;
|
if (zero === 'false') time = `${hours}:${now.getMinutes()}${sec}`;
|
||||||
else time = `${('00' + hours).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
|
else time = `${('00' + hours).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
time: time,
|
time: time,
|
||||||
ampm: ampm
|
ampm: ampm
|
||||||
|
|||||||
36
src/components/widgets/Favourite.jsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import StarIcon from '@material-ui/icons/Star';
|
||||||
|
import StarIcon2 from '@material-ui/icons/StarBorder';
|
||||||
|
|
||||||
|
export default class Favourite extends React.PureComponent {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.state = {
|
||||||
|
favourited: <StarIcon2 id='favouriteButton' onClick={() => this.favourite()} />
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
favourite() {
|
||||||
|
if (localStorage.getItem('favourite')) {
|
||||||
|
localStorage.removeItem('favourite');
|
||||||
|
this.setState({ favourited: <StarIcon2 id='favouriteButton' onClick={() => this.favourite()} /> });
|
||||||
|
} else {
|
||||||
|
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 id='favouriteButton' onClick={() => this.favourite()} /> });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (localStorage.getItem('favourite')) this.setState({ favourited: <StarIcon id='favouriteButton' onClick={() => this.favourite()} /> });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (localStorage.getItem('favouriteEnabled') === 'false') return null;
|
||||||
|
return <div className='favourite'>
|
||||||
|
{this.state.favourited}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/components/widgets/Maximise.jsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import FullscreenIcon from '@material-ui/icons/Fullscreen';
|
||||||
|
|
||||||
|
export default class View extends React.PureComponent {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
this.state = {
|
||||||
|
hidden: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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}%);`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
viewStuff() {
|
||||||
|
const elements = ['#searchBar', '.navbar-container', '.clock', '.greeting', '.quotediv', 'time'];
|
||||||
|
elements.forEach((element) => {
|
||||||
|
try {
|
||||||
|
(this.state.hidden === false) ? document.querySelector(element).style.display = 'none' : document.querySelector(element).style.display = 'block';
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (this.state.hidden === false) {
|
||||||
|
this.setState({ hidden: true });
|
||||||
|
this.setAttribute(0, 100);
|
||||||
|
} else {
|
||||||
|
this.setState({ hidden: false });
|
||||||
|
this.setAttribute(localStorage.getItem('blur'), localStorage.getItem('brightness'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (localStorage.getItem('view') === 'false') return null;
|
||||||
|
return <div className='view'>
|
||||||
|
<FullscreenIcon id='viewButton' onClick={() => this.viewStuff()} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import Quotes from '@muetab/quotes';
|
|||||||
import FileCopy from '@material-ui/icons/FilterNone';
|
import FileCopy from '@material-ui/icons/FilterNone';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import * as Constants from '../../modules/constants';
|
import * as Constants from '../../modules/constants';
|
||||||
|
import TwitterIcon from '@material-ui/icons/Twitter';
|
||||||
|
|
||||||
export default class Quote extends React.PureComponent {
|
export default class Quote extends React.PureComponent {
|
||||||
constructor(...args) {
|
constructor(...args) {
|
||||||
@@ -21,22 +22,41 @@ export default class Quote extends React.PureComponent {
|
|||||||
}); // Set the quote
|
}); // Set the quote
|
||||||
}
|
}
|
||||||
|
|
||||||
async getQuote() {
|
getQuotePack() {
|
||||||
const quotePack = JSON.parse(localStorage.getItem('quote_packs'));
|
let quotePack = localStorage.getItem('quote_packs');
|
||||||
|
if (quotePack === 'undefined') return this.doOffline();
|
||||||
|
quotePack = JSON.parse(quotePack);
|
||||||
|
|
||||||
if (quotePack) {
|
if (quotePack) {
|
||||||
const data = quotePack[Math.floor(Math.random() * quotePack.length)]
|
const data = quotePack[Math.floor(Math.random() * quotePack.length)];
|
||||||
return this.setState({
|
return this.setState({
|
||||||
quote: '"' + data.quote + '"',
|
quote: '"' + data.quote + '"',
|
||||||
author: data.author
|
author: data.author
|
||||||
});
|
});
|
||||||
|
} else this.doOffline();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getQuote() {
|
||||||
|
const quotePackAPI = JSON.parse(localStorage.getItem('quote_api'));
|
||||||
|
if (quotePackAPI) {
|
||||||
|
try {
|
||||||
|
const data = await (await fetch(quotePackAPI.url)).json();
|
||||||
|
let author = data[quotePackAPI.author];
|
||||||
|
if (quotePackAPI.authorOverride) author = quotePackAPI.authorOverride;
|
||||||
|
return this.setState({
|
||||||
|
quote: '"' + data[quotePackAPI.quote] + '"',
|
||||||
|
author: author
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
return this.getQuotePack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
if (localStorage.getItem('offlineMode') === 'true') return this.doOffline();
|
||||||
|
|
||||||
try { // First we try and get a quote from the API...
|
try { // First we try and get a quote from the API...
|
||||||
let data = await fetch(Constants.API_URL + '/getQuote');
|
const data = await (await fetch(Constants.API_URL + '/getQuote')).json();
|
||||||
data = await data.json();
|
if (data.statusCode === 429) return this.doOffline(); // If we hit the ratelimit, we fallback to local quotes
|
||||||
if (data.statusCode === 429) this.doOffline(); // If we hit the ratelimit, we fallback to local quotes
|
|
||||||
this.setState({
|
this.setState({
|
||||||
quote: '"' + data.quote + '"',
|
quote: '"' + data.quote + '"',
|
||||||
author: data.author
|
author: data.author
|
||||||
@@ -57,14 +77,17 @@ export default class Quote extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let copy = <FileCopy className='copyButton' onClick={() => this.copyQuote() }></FileCopy>;
|
let copy = <FileCopy className='copyButton' onClick={() => this.copyQuote()}></FileCopy>;
|
||||||
if (localStorage.getItem('copyButton') === 'false') copy = '';
|
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 (
|
return (
|
||||||
<div>
|
<div className='quotediv'>
|
||||||
<h1 className='quote'>{`${this.state.quote}`}</h1>
|
<h1 className='quote'>{`${this.state.quote}`}</h1>
|
||||||
<h1 className='quoteauthor'>{this.state.author} {copy}</h1>
|
<h1 className='quoteauthor'>{this.state.author} {copy} {tweet}</h1>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,38 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SearchIcon from '@material-ui/icons/Search';
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
const searchEngines = require('../../modules/searchEngines.json');
|
||||||
|
|
||||||
export default class Search extends React.PureComponent {
|
export default class Search extends React.PureComponent {
|
||||||
render() {
|
render() {
|
||||||
if (localStorage.getItem('searchBar') === 'false') return <div></div>;
|
if (localStorage.getItem('searchBar') === 'false') return null;
|
||||||
|
|
||||||
let url;
|
let url;
|
||||||
let query = 'q';
|
let query = 'q';
|
||||||
|
|
||||||
switch (localStorage.getItem('searchEngine')) {
|
const setting = localStorage.getItem('searchEngine');
|
||||||
case 'duckduckgo': url = 'https://duckduckgo.com'; break;
|
const info = searchEngines.find(i => i.settingsName === setting);
|
||||||
case 'google': url = 'https://google.com/search'; break;
|
if (info !== undefined) {
|
||||||
case 'bing': url = 'https://bing.com/search'; break;
|
url = info.url;
|
||||||
case 'yahoo': url ='https://search.yahoo.com/search'; break;
|
if (info.query) query = info.query;
|
||||||
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 custom = localStorage.getItem('customSearchEngine');
|
||||||
|
if (custom) url = custom;
|
||||||
|
|
||||||
const searchButton = () => {
|
const searchButton = () => {
|
||||||
let value = document.getElementById('searchtext').value;
|
let value = document.getElementById('searchtext').value;
|
||||||
if (!value) value = 'mue fast';
|
if (!value) value = 'mue fast';
|
||||||
window.location.href = url + '?q=' + value;
|
window.location.href = url + `?${query}=` + value;
|
||||||
}
|
};
|
||||||
|
|
||||||
return <div id='searchBar' className='searchbar'>
|
return (
|
||||||
|
<div id='searchBar' className='searchbar'>
|
||||||
<form id='searchBar' className='searchbarform' action={url}>
|
<form id='searchBar' className='searchbarform' action={url}>
|
||||||
<SearchIcon onClick={() => searchButton()} />
|
<SearchIcon onClick={() => searchButton()} />
|
||||||
<input type='text' placeholder={this.props.language} name={query} id='searchtext' className='searchtext'/>
|
<input type='text' placeholder={this.props.language} name={query} id='searchtext' className='searchtext'/>
|
||||||
<div className='blursearcbBG'/>
|
<div className='blursearcbBG'/>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,10 @@
|
|||||||
"name": "blur",
|
"name": "blur",
|
||||||
"value": 0
|
"value": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "brightness",
|
||||||
|
"value": 100
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "events",
|
"name": "events",
|
||||||
"value": true
|
"value": true
|
||||||
@@ -62,5 +66,21 @@
|
|||||||
{
|
{
|
||||||
"name": "searchEngine",
|
"name": "searchEngine",
|
||||||
"value": "duckduckgo"
|
"value": "duckduckgo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "refresh",
|
||||||
|
"value": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "view",
|
||||||
|
"value": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "favouriteEnabled",
|
||||||
|
"value": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "tweetButton",
|
||||||
|
"value": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -1,6 +1,44 @@
|
|||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
export default class MarketplaceFunctions {
|
export default class MarketplaceFunctions {
|
||||||
static urlParser (input) { // based on https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
|
static urlParser (input) { // based on https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
|
||||||
let urlPattern = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_+.~#?&//=]*)/;
|
const urlPattern = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_+.~#?&//=]*)/;
|
||||||
return input.replace(urlPattern, '<a href="$&" target="_blank">$&</a>');
|
return input.replace(urlPattern, '<a href="$&" target="_blank">$&</a>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uninstall(name, type) {
|
||||||
|
let installed = JSON.parse(localStorage.getItem('installed'));
|
||||||
|
|
||||||
|
const uninstallStuff = () => {
|
||||||
|
for (let i = 0; i < installed.length; i++) {
|
||||||
|
if (installed[i].name === name) {
|
||||||
|
installed.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
localStorage.setItem('installed', JSON.stringify(installed));
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case 'settings':
|
||||||
|
const oldSettings = JSON.parse(localStorage.getItem('backup_settings'));
|
||||||
|
localStorage.clear();
|
||||||
|
oldSettings.forEach(item => localStorage.setItem(item.name, item.value));
|
||||||
|
uninstallStuff();
|
||||||
|
break;
|
||||||
|
case 'quote_packs':
|
||||||
|
localStorage.removeItem('quote_packs');
|
||||||
|
localStorage.removeItem('quote_api');
|
||||||
|
uninstallStuff();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
try {
|
||||||
|
localStorage.removeItem(type);
|
||||||
|
uninstallStuff();
|
||||||
|
} catch (e) {
|
||||||
|
toast('Failed to uninstall addon, check the console');
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
17
src/modules/merge.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Merges 2 objects into a huge one
|
||||||
|
* @template T The original object
|
||||||
|
* @template U The object that is returned
|
||||||
|
* @param {...T} items The objects to merge
|
||||||
|
* @returns {U} The merged object
|
||||||
|
*/
|
||||||
|
export const merge = (...items) => {
|
||||||
|
const obj = {};
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
for (const k in items[i]) {
|
||||||
|
if (!obj.hasOwnProperty(k)) obj[k] = items[i][k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
20
src/modules/offlineImages.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"Tirachard Kumtanom" : {
|
||||||
|
"photo": [1]
|
||||||
|
},
|
||||||
|
"Sohail Na": {
|
||||||
|
"photo": [4]
|
||||||
|
},
|
||||||
|
"Miriam Espacio": {
|
||||||
|
"photo": [7]
|
||||||
|
},
|
||||||
|
"Fabian Wiktor": {
|
||||||
|
"photo": [20]
|
||||||
|
},
|
||||||
|
"Pixabay": {
|
||||||
|
"photo": [2, 3, 9, 11, 13, 14, 15]
|
||||||
|
},
|
||||||
|
"Unknown" : {
|
||||||
|
"photo": [5, 6, 8, 10, 12, 16, 17, 18, 19]
|
||||||
|
}
|
||||||
|
}
|
||||||
48
src/modules/searchEngines.json
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "DuckDuckGo",
|
||||||
|
"settingsName": "duckduckgo",
|
||||||
|
"url": "https://duckduckgo.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Google",
|
||||||
|
"settingsName": "google",
|
||||||
|
"url": "https://google.com/search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bing",
|
||||||
|
"settingsName": "bing",
|
||||||
|
"url": "https://bing.com/search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Yahoo",
|
||||||
|
"settingsName": "yahoo",
|
||||||
|
"url": "https://search.yahoo.com/search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ecosia",
|
||||||
|
"settingsName": "ecosia",
|
||||||
|
"url": "https://ecosia.org/search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Яндекс",
|
||||||
|
"settingsName": "yandex",
|
||||||
|
"url": "https://yandex.ru/search",
|
||||||
|
"query": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Qwant",
|
||||||
|
"settingsName": "qwant",
|
||||||
|
"url": "https://www.quant.com/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ask",
|
||||||
|
"settingsName": "ask",
|
||||||
|
"url": "https://ask.com/web"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Startpage",
|
||||||
|
"settingsName": "startpage",
|
||||||
|
"url": "https://www.startpage.com/sp/search"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -14,7 +14,7 @@ const saveFile = (data, filename = 'file') => {
|
|||||||
|
|
||||||
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||||
a.dispatchEvent(e);
|
a.dispatchEvent(e);
|
||||||
}
|
};
|
||||||
|
|
||||||
const defaultSettings = require('./defaultSettings.json');
|
const defaultSettings = require('./defaultSettings.json');
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ export default class SettingsFunctions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static setItem(key, value) {
|
static setItem(key, value) {
|
||||||
let old = localStorage.getItem(key);
|
const old = localStorage.getItem(key);
|
||||||
let val = true;
|
let val = true;
|
||||||
|
|
||||||
if (old !== null && !value) {
|
if (old !== null && !value) {
|
||||||
@@ -45,46 +45,52 @@ export default class SettingsFunctions {
|
|||||||
static setSearchEngine(input) {
|
static setSearchEngine(input) {
|
||||||
const searchEngineInput = document.getElementById('searchEngineInput');
|
const searchEngineInput = document.getElementById('searchEngineInput');
|
||||||
if (input === 'custom') {
|
if (input === 'custom') {
|
||||||
searchEngineInput.enabled = 'false';
|
searchEngineInput.enabled = 'true';
|
||||||
searchEngineInput.style.display = 'block';
|
searchEngineInput.style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
searchEngineInput.style.display = 'none';
|
searchEngineInput.style.display = 'none';
|
||||||
searchEngineInput.enabled = 'true';
|
searchEngineInput.enabled = 'false';
|
||||||
localStorage.setItem('searchEngine', input);
|
localStorage.setItem('searchEngine', input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static saveStuff() {
|
static saveStuff() {
|
||||||
localStorage.setItem('blur', document.getElementById('blurRange').value); // this is better than inline onChange for performance
|
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('greetingName', document.getElementById('greetingName').value);
|
||||||
localStorage.setItem('customBackground', document.getElementById('customBackground').value);
|
localStorage.setItem('customBackground', document.getElementById('customBackground').value);
|
||||||
if (!document.getElementById('searchEngineInput').enabled === 'false') {
|
if (document.getElementById('customBackgroundHex').textContent !== 'Disabled') {
|
||||||
localStorage.setItem('customSearchEngine', document.getElementById('searchEngineInput').value);
|
localStorage.setItem('customBackgroundColour', document.getElementById('customBackgroundHex').textContent);
|
||||||
|
}
|
||||||
|
if (document.getElementById('searchEngineInput').enabled === 'true') {
|
||||||
|
const input = document.getElementById('customSearchEngine').value;
|
||||||
|
if (input) {
|
||||||
|
localStorage.setItem('searchEngine', 'custom');
|
||||||
|
localStorage.setItem('customSearchEngine', input);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
static setDefaultSettings() {
|
static setDefaultSettings() {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
defaultSettings.forEach(element => localStorage.setItem(element.name, element.value));
|
defaultSettings.forEach((element) => localStorage.setItem(element.name, element.value));
|
||||||
|
|
||||||
// Set theme depending on user preferred
|
// Set theme depending on user preferred
|
||||||
// if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true);
|
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) localStorage.setItem('darkTheme', true);
|
||||||
//else localStorage.setItem('darkTheme', false);
|
else localStorage.setItem('darkTheme', false);
|
||||||
|
|
||||||
switch(detectBrowserLanguage()) {
|
// Webp support
|
||||||
case 'nl':
|
const supportsWebP = require('supports-webp'); // We import it here so it doesn't run the function on each page load
|
||||||
localStorage.setItem('language', 'nl');
|
if (supportsWebP) localStorage.setItem('supportswebp', 'true');
|
||||||
break;
|
|
||||||
case 'no':
|
// Languages
|
||||||
localStorage.setItem('language', 'no');
|
const languages = ['nl', 'no', 'fr', 'ru'];
|
||||||
break;
|
const browserLanguage = detectBrowserLanguage();
|
||||||
case 'fr':
|
if (languages.includes(browserLanguage)) {
|
||||||
localStorage.setItem('language', 'fr');
|
localStorage.setItem('language', browserLanguage);
|
||||||
break;
|
document.documentElement.lang = browserLanguage;
|
||||||
default:
|
} else localStorage.setItem('language', 'en');
|
||||||
localStorage.setItem('language', 'en');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally we set this to true so it doesn't run the function on every load
|
// Finally we set this to true so it doesn't run the function on every load
|
||||||
localStorage.setItem('firstRun', true);
|
localStorage.setItem('firstRun', true);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
font-family: 'Lexend Deca' !important;
|
font-family: 'Lexend Deca', 'Roboto' !important;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,6 +34,11 @@ body {
|
|||||||
src: url('/./fonts/LexendDeca-Regular.woff2') format('woff2');
|
src: url('/./fonts/LexendDeca-Regular.woff2') format('woff2');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
src: url('/./fonts/Roboto-Cyrillic.woff2') format('woff2');
|
||||||
|
}
|
||||||
|
|
||||||
#center {
|
#center {
|
||||||
margin-left: 2vw;
|
margin-left: 2vw;
|
||||||
margin-right: 2vw;
|
margin-right: 2vw;
|
||||||
@@ -80,7 +85,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.backgroundEffects {
|
.backgroundEffects {
|
||||||
opacity: .7;
|
opacity: 0.7;
|
||||||
transition: ease 0.6s;
|
transition: ease 0.6s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,18 @@
|
|||||||
margin-bottom: -10px;
|
margin-bottom: -10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.view {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.favourite {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 10px;
|
||||||
|
right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
#photographer {
|
#photographer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
@@ -16,12 +28,12 @@
|
|||||||
width: 1000px;
|
width: 1000px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.locationicon {
|
.locationicon, #viewButton, #favouriteButton {
|
||||||
width: auto;
|
width: auto;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-container > svg, #backgroundCredits > svg {
|
.navbar-container > svg, #backgroundCredits > svg, #viewButton > svg, #favouriteButton > svg {
|
||||||
font-size: calc(10px + 1.5vmin) !important;
|
font-size: calc(10px + 1.5vmin) !important;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ button.tablinks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
|
|
||||||
.tab,
|
.tab,
|
||||||
button.tablinks {
|
button.tablinks {
|
||||||
color: white;
|
color: white;
|
||||||
@@ -146,8 +145,8 @@ p.author {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#item>h1,
|
#item > h1,
|
||||||
#item>.MuiSvgIcon-root {
|
#item > .MuiSvgIcon-root {
|
||||||
display: inline;
|
display: inline;
|
||||||
font-size: 35px !important;
|
font-size: 35px !important;
|
||||||
}
|
}
|
||||||
@@ -207,7 +206,7 @@ p.description {
|
|||||||
background: #2d3436;
|
background: #2d3436;
|
||||||
}
|
}
|
||||||
|
|
||||||
#item>img {
|
#item > img {
|
||||||
border-radius: 24px;
|
border-radius: 24px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|||||||
@@ -13,13 +13,13 @@
|
|||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
scrollbar-color: #34495e #bdc3c7;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.modalLink {
|
.modalLink {
|
||||||
color: #5352ed;
|
color: #5352ed;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -93,8 +93,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal-animation {
|
.modal-animation {
|
||||||
-webkit-animation: zoom-in 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
-webkit-animation: zoom-in 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||||
animation: zoom-in 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
animation: zoom-in 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ReactModal__Content {
|
.ReactModal__Content {
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (min-height: 700px){
|
@media only screen and (min-height: 700px) {
|
||||||
.ReactModal__Content {
|
.ReactModal__Content {
|
||||||
min-height: 600px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
@@ -140,8 +140,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.zoom-out {
|
.zoom-out {
|
||||||
-webkit-animation: zoom-out 0.6s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
|
-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.250, 0.460, 0.450, 0.940) both;
|
animation: zoom-out 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
|
||||||
}
|
}
|
||||||
|
|
||||||
@-webkit-keyframes zoom-out {
|
@-webkit-keyframes zoom-out {
|
||||||
@@ -183,4 +183,17 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 13px;
|
||||||
|
background: #bdc3c7;
|
||||||
|
border-top-right-radius: map-get($modal, "border-radius");
|
||||||
|
border-bottom-right-radius: map-get($modal, "border-radius");
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #34495e;
|
||||||
|
border-top-right-radius: map-get($modal, "border-radius");
|
||||||
|
border-bottom-right-radius: map-get($modal, "border-radius");
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
min-width: 50px;
|
min-width: 50px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-filter: drop-shadow(0 0 6px rgba(0,0,0,.3));
|
-webkit-filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.3));
|
||||||
filter: drop-shadow(0 0 6px rgba(0,0,0,.3));
|
filter: drop-shadow(0 0 6px rgba(0, 0, 0, 0.3));
|
||||||
top: 20px;
|
top: 20px;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
@@ -23,11 +23,12 @@
|
|||||||
.navbar1 {
|
.navbar1 {
|
||||||
@extend %navbar;
|
@extend %navbar;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
-webkit-backface-visibility: hidden;
|
-webkit-backface-visibility: hidden;
|
||||||
-webkit-transform: translateZ(0) scale(1.0, 1.0);
|
-webkit-transform: translateZ(0) scale(1, 1);
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
transform: translateZ(0) scale(1.0, 1.0);
|
transform: translateZ(0) scale(1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
transition: ease 0.2s !important;
|
transition: ease 0.2s !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,16 +69,6 @@ input {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 5px;
|
|
||||||
background: #bdc3c7;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
background: #34495e;
|
|
||||||
}
|
|
||||||
|
|
||||||
h4,
|
h4,
|
||||||
.switch,
|
.switch,
|
||||||
.expandIcons {
|
.expandIcons {
|
||||||
@@ -170,6 +160,7 @@ li {
|
|||||||
width: 25px;
|
width: 25px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
border: 0;
|
||||||
background: map-get($theme-colours, "gradient");
|
background: map-get($theme-colours, "gradient");
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -195,6 +186,27 @@ input[type=color] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is duplicated because it didn't work with a comma, need to look into it later
|
||||||
|
input[type=color]::-moz-color-swatch {
|
||||||
|
border-radius: 100%;
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
box-shadow: map-get($main-parts, "shadow");
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
&::-moz-color-swatch-wrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-color-swatch {
|
||||||
|
border: none;
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input[type=checkbox] {
|
input[type=checkbox] {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
@@ -216,4 +228,32 @@ select {
|
|||||||
|
|
||||||
select#language {
|
select#language {
|
||||||
float: right;
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#customBackgroundColour {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Dark Theme
|
||||||
|
.dark {
|
||||||
|
#blurRange, #brightnessRange {
|
||||||
|
background-color: #535c68;
|
||||||
|
}
|
||||||
|
|
||||||
|
#customBackground, #backgroundAPI, #searchEngine, #language, #greetingName, #customSearchEngine {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.choices {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modalLink {
|
||||||
|
color: #3498db;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nodropdown {
|
||||||
|
cursor: default;
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
.welcomeModalText {
|
.welcomeModalText {
|
||||||
line-height: 2px;
|
line-height: 2px;
|
||||||
|
|
||||||
h2.subtitle {
|
h2.subtitle {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: #535353;
|
color: #535353;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1.welcometitle {
|
h1.welcometitle {
|
||||||
font-size: 50px;
|
font-size: 50px;
|
||||||
}
|
}
|
||||||
@@ -13,6 +15,7 @@
|
|||||||
.welcomeContent {
|
.welcomeContent {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 25px;
|
padding: 25px;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
line-height: 20px !important;
|
line-height: 20px !important;
|
||||||
@@ -22,6 +25,7 @@
|
|||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img.icon, svg {
|
img.icon, svg {
|
||||||
margin-top: -12px;
|
margin-top: -12px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@@ -31,10 +35,12 @@
|
|||||||
transform: scale(1.1);
|
transform: scale(1.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin-top: 0.7rem;
|
margin-top: 0.7rem;
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
img, svg {
|
img, svg {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|||||||
@@ -32,32 +32,40 @@
|
|||||||
},
|
},
|
||||||
"quote": {
|
"quote": {
|
||||||
"title": "Quote",
|
"title": "Quote",
|
||||||
"copy": "Copy Button"
|
"copy": "Copy Button",
|
||||||
|
"tweet": "Tweet Button"
|
||||||
},
|
},
|
||||||
"background": {
|
"background": {
|
||||||
"title": "Background",
|
"title": "Background",
|
||||||
"API": "Background API",
|
"API": "Background API",
|
||||||
"blur": "Adjust Blur",
|
"blur": "Adjust Blur",
|
||||||
|
"brightness": "Adjust Brightness",
|
||||||
"customURL": "Custom Background URL",
|
"customURL": "Custom Background URL",
|
||||||
"custombackground": "Custom Background",
|
"custombackground": "Custom Background",
|
||||||
"customcolour": "Custom Background Colour"
|
"customcolour": "Custom Background Colour",
|
||||||
|
"upload": "Upload"
|
||||||
},
|
},
|
||||||
"searchbar": {
|
"searchbar": {
|
||||||
"title": "Search Bar",
|
"title": "Search Bar",
|
||||||
"searchengine": "Search Engine"
|
"searchengine": "Search Engine",
|
||||||
|
"custom": "Custom Search URL"
|
||||||
},
|
},
|
||||||
"offline": "Offline Mode",
|
"offline": "Offline Mode",
|
||||||
"experimental": {
|
"experimental": {
|
||||||
"title": "Experimental",
|
"title": "Experimental",
|
||||||
"webp": "Enable WebP",
|
"webp": "Enable WebP",
|
||||||
"dark": "Dark Theme",
|
"dark": "Dark Theme",
|
||||||
"animations": "Animations"
|
"animations": "Animations",
|
||||||
|
"view": "View",
|
||||||
|
"favourite": "Favourite",
|
||||||
|
"refresh": "Refresh"
|
||||||
},
|
},
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"apply": "Apply",
|
"apply": "Apply",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"import": "Import",
|
"import": "Import",
|
||||||
"export": "Export"
|
"export": "Export",
|
||||||
|
"imported_settings": "Imported settings"
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"title": "Update",
|
"title": "Update",
|
||||||
@@ -76,7 +84,8 @@
|
|||||||
"reset": "Reset successfully",
|
"reset": "Reset successfully",
|
||||||
"installed": "Successfully installed",
|
"installed": "Successfully installed",
|
||||||
"removed": "Successfully removed",
|
"removed": "Successfully removed",
|
||||||
"error": "Something went wrong"
|
"error": "Something went wrong",
|
||||||
|
"imported": "Successfully imported"
|
||||||
},
|
},
|
||||||
"marketplace": {
|
"marketplace": {
|
||||||
"photo_packs": "Photo Packs",
|
"photo_packs": "Photo Packs",
|
||||||
@@ -96,6 +105,10 @@
|
|||||||
"buttons": {
|
"buttons": {
|
||||||
"addtomue": "Add To Mue",
|
"addtomue": "Add To Mue",
|
||||||
"remove": "Remove"
|
"remove": "Remove"
|
||||||
|
},
|
||||||
|
"quoteWarning": {
|
||||||
|
"title": "Warning",
|
||||||
|
"description": "This quote pack requests to external servers that may track you!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"offline": {
|
"offline": {
|
||||||
@@ -106,25 +119,11 @@
|
|||||||
},
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"added": "Added",
|
"added": "Added",
|
||||||
"product": {
|
|
||||||
"overview": "Overview",
|
|
||||||
"information": "Information",
|
|
||||||
"last_updated": "Last Updated",
|
|
||||||
"version": "Version",
|
|
||||||
"author": "Author",
|
|
||||||
"notice": {
|
|
||||||
"title": "Notice",
|
|
||||||
"description": "In order for the change to take place, the page must be refreshed."
|
|
||||||
},
|
|
||||||
"buttons": {
|
|
||||||
"addtomue": "Add To Mue",
|
|
||||||
"remove": "Remove"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "It's empty here",
|
"title": "It's empty here",
|
||||||
"description": "Head to the marketplace to add some.",
|
"description": "Head to the marketplace to add some.",
|
||||||
"button": "Take me there"
|
"button": "Take me there"
|
||||||
}
|
},
|
||||||
|
"sideload": "Sideload"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,21 +106,6 @@
|
|||||||
},
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"added": "Ajoutée",
|
"added": "Ajoutée",
|
||||||
"product": {
|
|
||||||
"overview": "Aperçu",
|
|
||||||
"information": "Informations",
|
|
||||||
"last_updated": "Dernière mise à jour",
|
|
||||||
"version": "Version",
|
|
||||||
"author": "Auteure",
|
|
||||||
"notice": {
|
|
||||||
"title": "Écriteau",
|
|
||||||
"description": "S'il vous plait, recharger la page."
|
|
||||||
},
|
|
||||||
"buttons": {
|
|
||||||
"addtomue": "Ajouter au Mue",
|
|
||||||
"remove": "Enlever"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "Il est vide ici",
|
"title": "Il est vide ici",
|
||||||
"description": "Aller su le marché pour en ajouter.",
|
"description": "Aller su le marché pour en ajouter.",
|
||||||
|
|||||||
@@ -40,7 +40,8 @@
|
|||||||
"blur": "Onscherpte Aanpassen",
|
"blur": "Onscherpte Aanpassen",
|
||||||
"customURL": "Aangepaste Achtergrond URL",
|
"customURL": "Aangepaste Achtergrond URL",
|
||||||
"custombackground": "Aangepaste Achtergrond",
|
"custombackground": "Aangepaste Achtergrond",
|
||||||
"customcolour": "Aangepaste Achtergrondkleur"
|
"customcolour": "Aangepaste Achtergrondkleur",
|
||||||
|
"upload": "Uploaden"
|
||||||
},
|
},
|
||||||
"searchbar": {
|
"searchbar": {
|
||||||
"title": "Zoekbalk",
|
"title": "Zoekbalk",
|
||||||
@@ -106,21 +107,6 @@
|
|||||||
},
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"added": "Toegevoegd",
|
"added": "Toegevoegd",
|
||||||
"product": {
|
|
||||||
"overview": "Overzicht",
|
|
||||||
"information": "Informatie",
|
|
||||||
"last_updated": "Laatst Geüpdatet",
|
|
||||||
"version": "Versie",
|
|
||||||
"author": "Auteur",
|
|
||||||
"notice": {
|
|
||||||
"title": "Aankondiging",
|
|
||||||
"description": "De veranderingen gaan in zodra je de pagina herlaad."
|
|
||||||
},
|
|
||||||
"buttons": {
|
|
||||||
"addtomue": "Voeg aan Mue toe",
|
|
||||||
"remove": "Verwijder"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "Het is hier leeg",
|
"title": "Het is hier leeg",
|
||||||
"description": "Ga naar de marktplaats om een paar extensies toe te veogen.",
|
"description": "Ga naar de marktplaats om een paar extensies toe te veogen.",
|
||||||
|
|||||||
@@ -106,21 +106,6 @@
|
|||||||
},
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"added": "Lagt til",
|
"added": "Lagt til",
|
||||||
"product": {
|
|
||||||
"overview": "Oversikt",
|
|
||||||
"information": "Informasjon",
|
|
||||||
"last_updated": "Sist oppdatert",
|
|
||||||
"version": "Versjon",
|
|
||||||
"author": "Forfatter",
|
|
||||||
"notice": {
|
|
||||||
"title": "Vær oppmerksom",
|
|
||||||
"description": "For at endringen skal ta skje, må siden relastes."
|
|
||||||
},
|
|
||||||
"buttons": {
|
|
||||||
"addtomue": "Legg Til Mue",
|
|
||||||
"remove": "Fjern"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "Det er tomt her.",
|
"title": "Det er tomt her.",
|
||||||
"description": "Gå til markedsplassen å legg til noe.",
|
"description": "Gå til markedsplassen å legg til noe.",
|
||||||
|
|||||||
@@ -9,9 +9,13 @@
|
|||||||
},
|
},
|
||||||
"credit": "Фото",
|
"credit": "Фото",
|
||||||
"search": "Поиск",
|
"search": "Поиск",
|
||||||
|
"modals": {
|
||||||
|
"title": "Options",
|
||||||
|
"settings": "Settings",
|
||||||
|
"addons": "My Add-ons",
|
||||||
|
"marketplace": "Marketplace"
|
||||||
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"title": "Настройки",
|
|
||||||
"description": "Измените компоненты Mue по своему вкусу.",
|
|
||||||
"time": {
|
"time": {
|
||||||
"title": "Время",
|
"title": "Время",
|
||||||
"seconds": "Секунды",
|
"seconds": "Секунды",
|
||||||
@@ -34,9 +38,11 @@
|
|||||||
"title": "Фон",
|
"title": "Фон",
|
||||||
"API": "API для фона",
|
"API": "API для фона",
|
||||||
"blur": "Размытие",
|
"blur": "Размытие",
|
||||||
|
"brightness": "Яркость",
|
||||||
"customURL": "Ссылка для пользовательского фона",
|
"customURL": "Ссылка для пользовательского фона",
|
||||||
"custombackground": "Пользовательский фон",
|
"custombackground": "Пользовательский фон",
|
||||||
"customcolour": "Пользовательский цвет фона"
|
"customcolour": "Пользовательский цвет фона",
|
||||||
|
"upload": "Загрузить"
|
||||||
},
|
},
|
||||||
"searchbar": {
|
"searchbar": {
|
||||||
"title": "Панель поиска",
|
"title": "Панель поиска",
|
||||||
@@ -53,7 +59,8 @@
|
|||||||
"apply": "Применить",
|
"apply": "Применить",
|
||||||
"reset": "Сбросить",
|
"reset": "Сбросить",
|
||||||
"import": "Импорт",
|
"import": "Импорт",
|
||||||
"export": "Экспорт"
|
"export": "Экспорт",
|
||||||
|
"imported_settings": "Импортированные настройки"
|
||||||
},
|
},
|
||||||
"update": {
|
"update": {
|
||||||
"title": "Обновление",
|
"title": "Обновление",
|
||||||
@@ -69,6 +76,43 @@
|
|||||||
},
|
},
|
||||||
"toasts": {
|
"toasts": {
|
||||||
"quote": "Цитата скопирована!",
|
"quote": "Цитата скопирована!",
|
||||||
"reset": "Сброшено!"
|
"reset": "Сброшено!",
|
||||||
|
"installed": "Успешно установлено",
|
||||||
|
"removed": "Успешно удалено",
|
||||||
|
"error": "Что-то пошло не так"
|
||||||
|
},
|
||||||
|
"marketplace": {
|
||||||
|
"photo_packs": "Наборы фото",
|
||||||
|
"quote_packs": "Наборы цитат",
|
||||||
|
"preset_settings": "Пресеты настроек",
|
||||||
|
"themes": "Темы",
|
||||||
|
"product": {
|
||||||
|
"overview": "Обзор",
|
||||||
|
"information": "Информация",
|
||||||
|
"last_updated": "Последнее обновление",
|
||||||
|
"version": "Версия",
|
||||||
|
"author": "Автор",
|
||||||
|
"notice": {
|
||||||
|
"title": "Предупреждение",
|
||||||
|
"description": "Для того, чтобы изменения вступили в силу необходимо обновить страницу."
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"addtomue": "Добавить в Mue",
|
||||||
|
"remove": "Удалить"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"offline": {
|
||||||
|
"title": "Похоже, что вы офлайн",
|
||||||
|
"description": "Пожалуйста, подключитесь к интернету."
|
||||||
|
},
|
||||||
|
"see_more": "Показать больше"
|
||||||
|
},
|
||||||
|
"addons": {
|
||||||
|
"added": "Добавлен",
|
||||||
|
"empty": {
|
||||||
|
"title": "Здесь пусто",
|
||||||
|
"description": "Зайдите в магазин, чтобы найти что-то интересное.",
|
||||||
|
"button": "Перейти"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||