fix: author loading before quote

- Make author div not load if quote is empty
- photoinformation taking too much of the screen
- more transitions and consistent transitions
- running prettier across all files

Co-authored-by: David Ralph <me@davidcralph.co.uk>
This commit is contained in:
alexsparkes 2022-04-11 22:57:07 +01:00
parent 4498f5b934
commit 7bb48ebc8e
84 changed files with 2630 additions and 2323 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -1,4 +1,4 @@
module.exports = { module.exports = {
extends: 'react-app', extends: 'react-app',
parser: '@babel/eslint-parser' parser: '@babel/eslint-parser',
}; };

View File

@ -1,7 +1,7 @@
{ {
"printWidth": 100, "printWidth": 100,
"trailingComma": "all", "trailingComma": "all",
"tabWidth": 2, "tabWidth": 2,
"semi": true, "semi": true,
"singleQuote": true "singleQuote": true
} }

View File

@ -12,76 +12,95 @@ Mue is a fast, open and free-to-use browser extension that gives a new, fresh an
<br> <br>
## NOTICE ## NOTICE
This is the branch for the next version of Mue, 7.0. All development is occuring in this branch which will be merged into main when it is finished. If you want the current code, see the main branch. This is the branch for the next version of Mue, 7.0. All development is occuring in this branch which will be merged into main when it is finished. If you want the current code, see the main branch.
## Table of contents ## Table of contents
* [Screenshots](#screenshot)
* [Features](#features) - [Screenshots](#screenshot)
* [Planned Features](#planned-features) - [Features](#features)
* [Installation](#installation) - [Planned Features](#planned-features)
* [Chrome](#chrome) - [Installation](#installation)
* [Firefox](#firefox) - [Chrome](#chrome)
* [Edge Chromium](#edge-chromium) - [Firefox](#firefox)
* [Whale](#whale) - [Edge Chromium](#edge-chromium)
* [Other](#other) - [Whale](#whale)
* [Contributing](#development) - [Other](#other)
* [Translations](#translations) - [Contributing](#development)
* [Credits](#credits) - [Translations](#translations)
* [Developers](#developers) - [Credits](#credits)
* [Translators](#translators) - [Developers](#developers)
* [Contributors](#contributors) - [Translators](#translators)
* [Resources](#resources) - [Contributors](#contributors)
- [Resources](#resources)
## Screenshots ## Screenshots
![Screenshot](assets/screenshot.webp) ![Screenshot](assets/screenshot.webp)
![Settings Modal](assets/screenshot2.webp) ![Settings Modal](assets/screenshot2.webp)
## Features ## Features
* Fast and free
* Supports multiple browsers - Fast and free
* Actively developed and open source - Supports multiple browsers
* Automatically updating [API](https://github.com/mue/api) with new photos, quotes and offline mode - Actively developed and open source
* Widgets such as search bar, weather, quick links, clock, date, quote, greeting - Automatically updating [API](https://github.com/mue/api) with new photos, quotes and offline mode
* Settings - enable/disable various features and customise parts of Mue - Widgets such as search bar, weather, quick links, clock, date, quote, greeting
* Navbar with copy button, favourite background, notes feature etc - Settings - enable/disable various features and customise parts of Mue
* [Marketplace](https://github.com/mue/marketplace) - download custom photo packs, quote packs and preset settings made by the community - Navbar with copy button, favourite background, notes feature etc
- [Marketplace](https://github.com/mue/marketplace) - download custom photo packs, quote packs and preset settings made by the community
### Planned Features ### Planned Features
Please see our [roadmap](https://trello.com/b/w7zhS7Hi/mue-50). Please see our [roadmap](https://trello.com/b/w7zhS7Hi/mue-50).
## Installation ## Installation
*A demo of the tab can be found [here](https://demo.muetab.com), and the latest GitHub commit build [here](https://mue.vercel.app)*
_A demo of the tab can be found [here](https://demo.muetab.com), and the latest GitHub commit build [here](https://mue.vercel.app)_
### Chrome ### Chrome
[![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid) [![Chrome Web Store Logo](assets/chrome.png)](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
<br> <br>
[Chrome Web Store](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid) [Chrome Web Store](https://chrome.google.com/webstore/detail/mue/bngmbednanpcfochchhgbkookpiaiaid)
### Firefox ### Firefox
[![Firefox Add-ons Logo](assets/firefox.png)](https://addons.mozilla.org/firefox/addon/mue) [![Firefox Add-ons Logo](assets/firefox.png)](https://addons.mozilla.org/firefox/addon/mue)
<br> <br>
[Firefox Add-ons](https://addons.mozilla.org/firefox/addon/mue) [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/mue)
### Edge (Chromium) ### Edge (Chromium)
[Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja) [Microsoft Edge Addons](https://microsoftedge.microsoft.com/addons/detail/aepnglgjfokepefimhbnibfjekidhmja)
### Whale ### Whale
[Whale Store](https://store.whale.naver.com/detail/ecllekeilcmicbfkkiknfdddbogibbnc) [Whale Store](https://store.whale.naver.com/detail/ecllekeilcmicbfkkiknfdddbogibbnc)
### Other ### Other
[GitHub Releases](https://github.com/mue/mue/releases) [GitHub Releases](https://github.com/mue/mue/releases)
## Development ## Development
Please see the [documentation](https://docs.muetab.com/development#mue-tab). Please see the [documentation](https://docs.muetab.com/development#mue-tab).
### Translations ### Translations
Please see the [documentation](https://docs.muetab.com/translations). Please see the [documentation](https://docs.muetab.com/translations).
## Credits ## Credits
### Developers ### Developers
[David Ralph](https://github.com/davidcralph) - Lead development, photographer <br/> [David Ralph](https://github.com/davidcralph) - Lead development, photographer <br/>
[Alex Sparkes](https://github.com/alexsparkes) - Name, lead design, photographer <br/> [Alex Sparkes](https://github.com/alexsparkes) - Name, lead design, photographer <br/>
[Isaac Saunders](https://github.com/eartharoid) - QA, development, photographer <br/> [Isaac Saunders](https://github.com/eartharoid) - QA, development, photographer <br/>
[Wessel Tip](https://github.com/Wessel) - Development <br/> [Wessel Tip](https://github.com/Wessel) - Development <br/>
### Translators ### Translators
[Wessel Tip](https://github.com/Wessel), [Heimen Stoffels](https://github.com/Vistaus) - Dutch <br/> [Wessel Tip](https://github.com/Wessel), [Heimen Stoffels](https://github.com/Vistaus) - Dutch <br/>
[Alex Sparkes](https://github.com/alexsparkes), [Maxime](https://github.com/exiam) - French <br/> [Alex Sparkes](https://github.com/alexsparkes), [Maxime](https://github.com/exiam) - French <br/>
[Anders](https://github.com/FuryingFox) - Norwegian <br/> [Anders](https://github.com/FuryingFox) - Norwegian <br/>
@ -90,10 +109,14 @@ Please see the [documentation](https://docs.muetab.com/translations).
[Austin Huang](https://github.com/austinhuang0131) - Chinese (Simplified) <br/> [Austin Huang](https://github.com/austinhuang0131) - Chinese (Simplified) <br/>
[FreeFun](https://github.com/xXFreeFunXx) - German <br/> [FreeFun](https://github.com/xXFreeFunXx) - German <br/>
[Aksal](https://github.com/aksalsf) - Indonesian <br/> [Aksal](https://github.com/aksalsf) - Indonesian <br/>
### Contributors ### Contributors
Many thanks to the photographers [here](https://api.muetab.com/images/photographers) for letting us use their wonderful photographs. Many thanks to the photographers [here](https://api.muetab.com/images/photographers) for letting us use their wonderful photographs.
And finally, a big thank you to all the other [contributors](https://github.com/mue/mue/graphs/contributors)! And finally, a big thank you to all the other [contributors](https://github.com/mue/mue/graphs/contributors)!
### Resources ### Resources
[Pexels](https://pexels.com), [Unsplash](https://unsplash.com) - Stock photos used for offline mode <br/> [Pexels](https://pexels.com), [Unsplash](https://unsplash.com) - Stock photos used for offline mode <br/>
[Undraw](https://undraw.co) - Welcome modal images [Undraw](https://undraw.co) - Welcome modal images

View File

@ -1,6 +1,16 @@
module.exports = { module.exports = {
presets: ['@babel/preset-env', ['@babel/preset-react', { presets: [
runtime: 'automatic' '@babel/preset-env',
}]], [
plugins: ['@babel/transform-runtime', '@babel/plugin-transform-react-inline-elements', '@babel/plugin-transform-react-constant-elements'] '@babel/preset-react',
{
runtime: 'automatic',
},
],
],
plugins: [
'@babel/transform-runtime',
'@babel/plugin-transform-react-inline-elements',
'@babel/plugin-transform-react-constant-elements',
],
}; };

View File

@ -4,7 +4,7 @@ chrome.runtime.setUninstallURL('https://muetab.com/uninstall');
chrome.runtime.onInstalled.addListener((details) => { chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') { if (details.reason === 'install') {
chrome.tabs.create({ chrome.tabs.create({
url: chrome.runtime.getURL('index.html') url: chrome.runtime.getURL('index.html'),
}); });
} }
}); });

View File

@ -4,7 +4,7 @@ browser.runtime.setUninstallURL('https://muetab.com/uninstall');
browser.runtime.onInstalled.addListener((details) => { browser.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') { if (details.reason === 'install') {
browser.tabs.create({ browser.tabs.create({
url: browser.runtime.getURL('index.html') url: browser.runtime.getURL('index.html'),
}); });
} }
}); });

View File

@ -20,6 +20,6 @@
"content_security_policy": "script-src 'self' https://api.bing.com https://www.google.com; object-src 'self'", "content_security_policy": "script-src 'self' https://api.bing.com https://www.google.com; object-src 'self'",
"background": { "background": {
"persistent": false, "persistent": false,
"scripts": [ "background-chrome.js" ] "scripts": ["background-chrome.js"]
} }
} }

View File

@ -1,17 +1,18 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang='en'> <html lang="en">
<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/32x32.png'> <link rel="icon" type="image/png" sizes="32x32" href="./icons/32x32.png" />
<link rel='icon' type='image/png' sizes='16x16' href='./icons/16x16.png'> <link rel="icon" type="image/png" sizes="16x16" href="./icons/16x16.png" />
<title>New Tab</title> <title>New Tab</title>
</head> </head>
<body> <body>
<noscript> <noscript>
<style> <style>
*, a { *,
a {
font-family: 'Lexend Deca', sans-serif; font-family: 'Lexend Deca', sans-serif;
text-align: center; text-align: center;
color: black; color: black;
@ -19,7 +20,8 @@
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
*, a { *,
a {
color: white; color: white;
background: #2f3640 !important; background: #2f3640 !important;
} }
@ -27,8 +29,11 @@
</style> </style>
<h1>Error</h1> <h1>Error</h1>
<h2>You need to enable JavaScript to use Mue</h2> <h2>You need to enable JavaScript to use Mue</h2>
<p>Having trouble? Contact us: <a href='https://muetab.com/contact'>https://muetab.com/contact</a></p> <p>
Having trouble? Contact us:
<a href="https://muetab.com/contact">https://muetab.com/contact</a>
</p>
</noscript> </noscript>
<div id='root'></div> <div id="root"></div>
</body> </body>
</html> </html>

View File

@ -7,7 +7,10 @@ fs.readdirSync('../src/translations').forEach((file) => {
return; return;
} }
const newdata = merge(require('../src/translations/en_GB.json'), require('../src/translations/' + file)); const newdata = merge(
require('../src/translations/en_GB.json'),
require('../src/translations/' + file),
);
fs.writeFileSync('../src/translations/' + file, JSON.stringify(newdata, null, 2)); fs.writeFileSync('../src/translations/' + file, JSON.stringify(newdata, null, 2));
// add new line // add new line
fs.appendFileSync('../src/translations/' + file, '\n'); fs.appendFileSync('../src/translations/' + file, '\n');

View File

@ -18,7 +18,7 @@ export default class App extends PureComponent {
if (!localStorage.getItem('firstRun') || !localStorage.getItem('stats')) { if (!localStorage.getItem('firstRun') || !localStorage.getItem('stats')) {
moveSettings(); moveSettings();
window.location.reload(); window.location.reload();
} }
loadSettings(); loadSettings();
@ -34,11 +34,17 @@ export default class App extends PureComponent {
render() { render() {
return ( return (
<> <>
{(localStorage.getItem('background') === 'true') ? <Background/> : null} {localStorage.getItem('background') === 'true' ? <Background /> : null}
<ToastContainer position='bottom-right' autoClose={localStorage.getItem('toastDisplayTime') || 2500} newestOnTop={true} closeOnClick pauseOnFocusLoss/> <ToastContainer
<div id='center'> position="bottom-right"
<Widgets/> autoClose={localStorage.getItem('toastDisplayTime') || 2500}
<Modals/> newestOnTop={true}
closeOnClick
pauseOnFocusLoss
/>
<div id="center">
<Widgets />
<Modals />
</div> </div>
</> </>
); );

View File

@ -12,20 +12,22 @@ export default class Autocomplete extends PureComponent {
this.state = { this.state = {
filtered: [], filtered: [],
input: '', input: '',
autocompleteDisabled: (localStorage.getItem('autocomplete') !== 'true') autocompleteDisabled: localStorage.getItem('autocomplete') !== 'true',
}; };
} }
onChange = (e) => { onChange = (e) => {
if (this.state.autocompleteDisabled) { if (this.state.autocompleteDisabled) {
return this.setState({ return this.setState({
input: e.target.value input: e.target.value,
}); });
} }
this.setState({ this.setState({
filtered: this.props.suggestions.filter((suggestion) => suggestion.toLowerCase().indexOf(e.target.value.toLowerCase()) > -1), filtered: this.props.suggestions.filter(
input: e.target.value (suggestion) => suggestion.toLowerCase().indexOf(e.target.value.toLowerCase()) > -1,
),
input: e.target.value,
}); });
this.props.onChange(e.target.value); this.props.onChange(e.target.value);
@ -34,14 +36,14 @@ export default class Autocomplete extends PureComponent {
onClick = (e) => { onClick = (e) => {
this.setState({ this.setState({
filtered: [], filtered: [],
input: e.target.innerText input: e.target.innerText,
}); });
this.props.onClick({ this.props.onClick({
preventDefault: () => e.preventDefault(), preventDefault: () => e.preventDefault(),
target: { target: {
value: e.target.innerText value: e.target.innerText,
} },
}); });
}; };
@ -49,7 +51,7 @@ export default class Autocomplete extends PureComponent {
EventBus.on('refresh', (data) => { EventBus.on('refresh', (data) => {
if (data === 'search') { if (data === 'search') {
this.setState({ this.setState({
autocompleteDisabled: (localStorage.getItem('autocomplete') !== 'true') autocompleteDisabled: localStorage.getItem('autocomplete') !== 'true',
}); });
} }
}); });
@ -65,7 +67,7 @@ export default class Autocomplete extends PureComponent {
// length will only be > 0 if enabled // length will only be > 0 if enabled
if (this.state.filtered.length > 0 && this.state.input.length > 0) { if (this.state.filtered.length > 0 && this.state.input.length > 0) {
autocomplete = ( autocomplete = (
<div className='suggestions'> <div className="suggestions">
{this.state.filtered.map((suggestion) => ( {this.state.filtered.map((suggestion) => (
<div key={suggestion} onClick={this.onClick}> <div key={suggestion} onClick={this.onClick}>
{suggestion} {suggestion}
@ -76,8 +78,16 @@ export default class Autocomplete extends PureComponent {
} }
return ( return (
<div style={{display: 'flex', flexFlow: 'column'}}> <div style={{ display: 'flex', flexFlow: 'column' }}>
<input type='text' onChange={this.onChange} value={this.state.input} placeholder={this.props.placeholder || ''} autoComplete='off' spellCheck={false} id={this.props.id || ''} /> <input
type="text"
onChange={this.onChange}
value={this.state.input}
placeholder={this.props.placeholder || ''}
autoComplete="off"
spellCheck={false}
id={this.props.id || ''}
/>
{autocomplete} {autocomplete}
</div> </div>
); );

View File

@ -6,9 +6,9 @@ export default function Preview(props) {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text); const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return ( return (
<div className='preview-mode'> <div className="preview-mode">
<span className='title'>{getMessage('modals.main.settings.reminder.title')}</span> <span className="title">{getMessage('modals.main.settings.reminder.title')}</span>
<span className='subtitle'>{getMessage('modals.welcome.preview.description')}</span> <span className="subtitle">{getMessage('modals.welcome.preview.description')}</span>
<button onClick={() => props.setup()}>{getMessage('modals.welcome.preview.continue')}</button> <button onClick={() => props.setup()}>{getMessage('modals.welcome.preview.continue')}</button>
</div> </div>
); );

View File

@ -1,59 +1,58 @@
@import '../../../scss/variables'; @import '../../../scss/variables';
.shareModal { .shareModal {
@extend %tabText; @extend %tabText;
display: flex;
flex-flow: column;
gap: 15px;
padding: 15px;
@include themed() {
background: t($modal-background);
}
.buttons {
justify-content: space-between;
display: flex; display: flex;
flex-flow: column;
gap: 15px; gap: 15px;
padding: 15px; }
button {
place-items: center;
display: grid;
@include basicIconButton(11px, 1.3rem, modal);
}
.copy {
display: flex;
flex-flow: row;
gap: 15px;
}
input[type='text'] {
@include themed() { @include themed() {
background: t($modal-background); background: t($modal-sidebar);
border-radius: t($borderRadius);
box-shadow: 0 0 0 4px t($modal-sidebarActive);
padding: 11px;
flex: 1;
color: t($color);
} }
.buttons { border: none;
justify-content: space-between; outline: none;
display: flex; }
gap: 15px; .close {
} padding: 15px;
button { place-items: center;
place-items: center; display: grid;
display: grid; cursor: pointer;
@include basicIconButton(11px, 1.3rem, modal); &:hover {
}
.copy {
display: flex;
flex-flow: row;
gap: 15px;
}
input[type='text'] {
@include themed() { @include themed() {
background: t($modal-sidebar); background: t($modal-sidebar);
border-radius: t($borderRadius); border-radius: t($borderRadius);
box-shadow: 0 0 0 4px t($modal-sidebarActive);
padding: 11px;
flex: 1;
color: t($color);
}
border: none;
outline: none;
}
.close {
padding: 15px;
place-items: center;
display: grid;
cursor: pointer;
&:hover {
@include themed() {
background: t($modal-sidebar);
border-radius: t($borderRadius);
}
} }
} }
} }
}
.shareHeader {
display: flex; .shareHeader {
flex-flow: row; display: flex;
justify-content: space-between; flex-flow: row;
align-items: center; justify-content: space-between;
} align-items: center;
}

View File

@ -1,11 +1,11 @@
import { useState } from "react"; import { useState } from 'react';
import { useFloating, flip, offset, shift } from "@floating-ui/react-dom"; import { useFloating, flip, offset, shift } from '@floating-ui/react-dom';
import "./tooltip.scss"; import './tooltip.scss';
export default function Tooltip({ children, title, style, placement }) { export default function Tooltip({ children, title, style, placement }) {
const [showTooltip, setShowTooltip] = useState(false); const [showTooltip, setShowTooltip] = useState(false);
const { x, y, reference, floating, strategy } = useFloating({ const { x, y, reference, floating, strategy } = useFloating({
placement: placement || "bottom", placement: placement || 'bottom',
middleware: [flip(), offset(15), shift()], middleware: [flip(), offset(15), shift()],
}); });
@ -25,8 +25,8 @@ export default function Tooltip({ children, title, style, placement }) {
ref={floating} ref={floating}
style={{ style={{
position: strategy, position: strategy,
top: y ?? "", top: y ?? '',
left: x ?? "", left: x ?? '',
}} }}
className="tooltipTitle" className="tooltipTitle"
> >

View File

@ -93,19 +93,16 @@ export default class Modals extends PureComponent {
<Main modalClose={() => this.toggleModal('mainModal', false)} /> <Main modalClose={() => this.toggleModal('mainModal', false)} />
</Modal> </Modal>
<Modal <Modal
closeTimeoutMS={300} closeTimeoutMS={300}
onRequestClose={() => this.closeWelcome()} onRequestClose={() => this.closeWelcome()}
isOpen={this.state.welcomeModal} isOpen={this.state.welcomeModal}
className="Modal welcomemodal mainModal" className="Modal welcomemodal mainModal"
overlayClassName="Overlay welcomeoverlay" overlayClassName="Overlay welcomeoverlay"
shouldCloseOnOverlayClick={false} shouldCloseOnOverlayClick={false}
ariaHideApp={false} ariaHideApp={false}
> >
<Welcome <Welcome modalClose={() => this.closeWelcome()} modalSkip={() => this.previewWelcome()} />
modalClose={() => this.closeWelcome()} </Modal>
modalSkip={() => this.previewWelcome()}
/>
</Modal>
{this.state.preview ? <Preview setup={() => window.location.reload()} /> : null} {this.state.preview ? <Preview setup={() => window.location.reload()} /> : null}
{/*variables.keybinds.toggleModal && variables.keybinds.toggleModal !== '' ? <Hotkeys keyName={variables.keybinds.toggleModal} onKeyDown={() => this.toggleModal('mainModal', (this.state.mainModal === true ? false : true))}/> : null*/} {/*variables.keybinds.toggleModal && variables.keybinds.toggleModal !== '' ? <Hotkeys keyName={variables.keybinds.toggleModal} onKeyDown={() => this.toggleModal('mainModal', (this.state.mainModal === true ? false : true))}/> : null*/}
</> </>

View File

@ -1,26 +1,24 @@
import variables from "modules/variables"; import variables from 'modules/variables';
export default function Collection({ items, toggleFunction }) { export default function Collection({ items, toggleFunction }) {
return [ return [
<div className='collection starWars'> <div className="collection starWars">
<div className='content'> <div className="content">
<div className="tags"> <div className="tags">
<div className="tag"> <div className="tag">
<span>Star Wars</span> <span>Star Wars</span>
</div> </div>
</div> </div>
<span className='title'>Star Wars Collection</span> <span className="title">Star Wars Collection</span>
<span className='subtitle'>A Collection of stuff inspired by the film franchise star wars..</span> <span className="subtitle">
<button>Explore Collection</button> A Collection of stuff inspired by the film franchise star wars..
</div> </span>
</div>, <button>Explore Collection</button>
<div className="items"> </div>
</div>,
<div className="items">
{items.map((item) => ( {items.map((item) => (
<div <div className="item" onClick={() => toggleFunction(item)} key={item.name}>
className="item"
onClick={() => toggleFunction(item)}
key={item.name}
>
<img <img
alt="icon" alt="icon"
draggable="false" draggable="false"
@ -33,7 +31,7 @@ export default function Collection({ items, toggleFunction }) {
<div className="tag"> <div className="tag">
<span>{item.author}</span> <span>{item.author}</span>
</div> </div>
<div className='moreTag'> <div className="moreTag">
<span>1</span> <span>1</span>
</div> </div>
</div> </div>

View File

@ -5,8 +5,10 @@ export default function Lightbox({ modalClose, img }) {
return ( return (
<> <>
<span className='closeModal' onClick={modalClose}>&times;</span> <span className="closeModal" onClick={modalClose}>
<img src={img} className='lightboximg' draggable={false} alt='Item screenshot'/> &times;
</span>
<img src={img} className="lightboximg" draggable={false} alt="Item screenshot" />
</> </>
); );
} }

View File

@ -1,5 +1,5 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { import {
MdSettings as Settings, MdSettings as Settings,
MdOutlineInsertPhoto as Photos, MdOutlineInsertPhoto as Photos,
@ -9,18 +9,18 @@ import {
MdArrowBack, MdArrowBack,
MdDownload, MdDownload,
MdOpenInNew, MdOpenInNew,
} from "react-icons/md"; } from 'react-icons/md';
import { TextField } from "@mui/material"; import { TextField } from '@mui/material';
import { toast } from "react-toastify"; import { toast } from 'react-toastify';
import SettingsItem from "../../../main/settings/SettingsItem"; import SettingsItem from '../../../main/settings/SettingsItem';
import { saveFile } from "modules/helpers/settings/modals"; import { saveFile } from 'modules/helpers/settings/modals';
import Tooltip from "../../../../helpers/tooltip/Tooltip"; import Tooltip from '../../../../helpers/tooltip/Tooltip';
import FileUpload from "../../settings/FileUpload"; import FileUpload from '../../settings/FileUpload';
import Dropdown from "../../settings/Dropdown"; import Dropdown from '../../settings/Dropdown';
import "../../../welcome/welcome.scss"; import '../../../welcome/welcome.scss';
export default class Create extends PureComponent { export default class Create extends PureComponent {
constructor() { constructor() {
@ -28,18 +28,18 @@ export default class Create extends PureComponent {
this.state = { this.state = {
currentTab: 1, currentTab: 1,
addonMetadata: { addonMetadata: {
name: "", name: '',
description: "", description: '',
type: "", type: '',
version: "", version: '',
author: "", author: '',
icon_url: "", icon_url: '',
screenshot_url: "", screenshot_url: '',
}, },
addonData: "", addonData: '',
settingsClasses: { settingsClasses: {
current: "toggle lightTheme", current: 'toggle lightTheme',
json: "toggle lightTheme", json: 'toggle lightTheme',
}, },
}; };
} }
@ -64,17 +64,17 @@ export default class Create extends PureComponent {
let settings = {}; let settings = {};
Object.keys(data).forEach((key) => { Object.keys(data).forEach((key) => {
if ( if (
key === "statsData" || key === 'statsData' ||
key === "firstRun" || key === 'firstRun' ||
key === "showWelcome" || key === 'showWelcome' ||
key === "language" || key === 'language' ||
key === "installed" || key === 'installed' ||
key === "stats" || key === 'stats' ||
key === "backup_settings" || key === 'backup_settings' ||
key === "showReminder" || key === 'showReminder' ||
key === "experimental" || key === 'experimental' ||
key === "debugtimeout" || key === 'debugtimeout' ||
key === "quotelanguage" key === 'quotelanguage'
) { ) {
return; return;
} }
@ -84,14 +84,12 @@ export default class Create extends PureComponent {
this.setState({ this.setState({
addonData: settings, addonData: settings,
settingsClasses: { settingsClasses: {
current: input ? "toggle lightTheme active" : "toggle lightTheme", current: input ? 'toggle lightTheme active' : 'toggle lightTheme',
json: input ? "toggle lightTheme active" : "toggle lightTheme", json: input ? 'toggle lightTheme active' : 'toggle lightTheme',
}, },
}); });
toast( toast(variables.language.getMessage(variables.languagecode, 'toasts.imported'));
variables.language.getMessage(variables.languagecode, "toasts.imported")
);
} }
updateQuotePackType(type) { updateQuotePackType(type) {
@ -104,7 +102,7 @@ export default class Create extends PureComponent {
icon_url: this.state.addonMetadata.icon_url, icon_url: this.state.addonMetadata.icon_url,
screenshot_url: this.state.addonMetadata.screenshot_url, screenshot_url: this.state.addonMetadata.screenshot_url,
}; };
if (type === "quotePack") { if (type === 'quotePack') {
this.setState({ this.setState({
addonMetadata: { addonMetadata: {
addonMetadata, addonMetadata,
@ -117,9 +115,9 @@ export default class Create extends PureComponent {
addonMetadata, addonMetadata,
}, },
addonData: { addonData: {
url: "", url: '',
name: "", name: '',
author: "", author: '',
}, },
}); });
} }
@ -128,45 +126,38 @@ export default class Create extends PureComponent {
updateQuotePackAPI(type, data) { updateQuotePackAPI(type, data) {
this.setState({ this.setState({
addonData: { addonData: {
url: type === "url" ? data : this.state.addonData.url || "", url: type === 'url' ? data : this.state.addonData.url || '',
name: type === "name" ? data : this.state.addonData.name || "", name: type === 'name' ? data : this.state.addonData.name || '',
author: type === "author" ? data : this.state.addonData.author || "", author: type === 'author' ? data : this.state.addonData.author || '',
}, },
}); });
} }
importQuotes() { importQuotes() {
this.setState({ this.setState({
addonData: JSON.parse(localStorage.getItem("customQuote")) || [], addonData: JSON.parse(localStorage.getItem('customQuote')) || [],
}); });
toast( toast(variables.language.getMessage(variables.languagecode, 'toasts.imported'));
variables.language.getMessage(variables.languagecode, "toasts.imported")
);
} }
importPhotos() { importPhotos() {
let data = []; let data = [];
try { try {
const current = const current = JSON.parse(localStorage.getItem('customBackground')) || [];
JSON.parse(localStorage.getItem("customBackground")) || [];
data = current.map((item) => { data = current.map((item) => {
return { return {
photographer: "???", photographer: '???',
location: "???", location: '???',
url: { url: {
default: item, default: item,
}, },
}; };
}); });
toast( toast(variables.language.getMessage(variables.languagecode, 'toasts.imported'));
variables.language.getMessage(variables.languagecode, "toasts.imported")
);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
toast( toast(variables.language.getMessage(variables.languagecode, 'toasts.error'));
variables.language.getMessage(variables.languagecode, "toasts.error")
);
} }
this.setState({ this.setState({
@ -180,23 +171,20 @@ export default class Create extends PureComponent {
name: this.state.addonMetadata.name, name: this.state.addonMetadata.name,
description: this.state.addonMetadata.description, description: this.state.addonMetadata.description,
type: type:
this.state.addonMetadata.type === "quote_api" this.state.addonMetadata.type === 'quote_api' ? 'quotes' : this.state.addonMetadata.type,
? "quotes"
: this.state.addonMetadata.type,
version: this.state.addonMetadata.version, version: this.state.addonMetadata.version,
author: this.state.addonMetadata.author, author: this.state.addonMetadata.author,
icon_url: this.state.addonMetadata.icon_url, icon_url: this.state.addonMetadata.icon_url,
screenshot_url: this.state.addonMetadata.screenshot_url, screenshot_url: this.state.addonMetadata.screenshot_url,
[this.state.addonMetadata.type]: this.state.addonData, [this.state.addonMetadata.type]: this.state.addonData,
}, },
this.state.addonMetadata.name + ".json" this.state.addonMetadata.name + '.json',
); );
} }
render() { render() {
let tabContent; let tabContent;
const getMessage = (text) => const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
const chooseType = ( const chooseType = (
<> <>
@ -204,8 +192,7 @@ export default class Create extends PureComponent {
<div className="content"> <div className="content">
<span className="title">Help Centre</span> <span className="title">Help Centre</span>
<span className="subtitle"> <span className="subtitle">
Home of all docs and guides on creating addons for Mue's Home of all docs and guides on creating addons for Mue's marketplace
marketplace
</span> </span>
</div> </div>
<button> <button>
@ -215,28 +202,17 @@ export default class Create extends PureComponent {
</div> </div>
<div className="themesToggleArea"> <div className="themesToggleArea">
<div className="options"> <div className="options">
<div <div className="toggle lightTheme" onClick={() => this.changeTab(2, 'photos')}>
className="toggle lightTheme"
onClick={() => this.changeTab(2, "photos")}
>
<Photos /> <Photos />
<span>{getMessage("modals.main.marketplace.photo_packs")}</span> <span>{getMessage('modals.main.marketplace.photo_packs')}</span>
</div> </div>
<div <div className="toggle lightTheme" onClick={() => this.changeTab(2, 'quotes')}>
className="toggle lightTheme"
onClick={() => this.changeTab(2, "quotes")}
>
<Quotes /> <Quotes />
<span>{getMessage("modals.main.marketplace.quote_packs")}</span> <span>{getMessage('modals.main.marketplace.quote_packs')}</span>
</div> </div>
<div <div className="toggle lightTheme" onClick={() => this.changeTab(2, 'settings')}>
className="toggle lightTheme"
onClick={() => this.changeTab(2, "settings")}
>
<Settings /> <Settings />
<span> <span>{getMessage('modals.main.marketplace.preset_settings')}</span>
{getMessage("modals.main.marketplace.preset_settings")}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -256,19 +232,13 @@ export default class Create extends PureComponent {
const setMetadata = (data, type) => { const setMetadata = (data, type) => {
this.setState({ this.setState({
addonMetadata: { addonMetadata: {
name: type === "name" ? data : this.state.addonMetadata.name, name: type === 'name' ? data : this.state.addonMetadata.name,
description: description: type === 'description' ? data : this.state.addonMetadata.description,
type === "description" version: type === 'version' ? data : this.state.addonMetadata.version,
? data author: type === 'author' ? data : this.state.addonMetadata.author,
: this.state.addonMetadata.description, icon_url: type === 'icon_url' ? data : this.state.addonMetadata.icon_url,
version: type === "version" ? data : this.state.addonMetadata.version,
author: type === "author" ? data : this.state.addonMetadata.author,
icon_url:
type === "icon_url" ? data : this.state.addonMetadata.icon_url,
screenshot_url: screenshot_url:
type === "screenshot_url" type === 'screenshot_url' ? data : this.state.addonMetadata.screenshot_url,
? data
: this.state.addonMetadata.screenshot_url,
type: this.state.addonMetadata.type, type: this.state.addonMetadata.type,
}, },
}); });
@ -278,7 +248,7 @@ export default class Create extends PureComponent {
<> <>
<div className="smallBanner"> <div className="smallBanner">
<div className="content"> <div className="content">
<span className="title" style={{ textTransform: "capitalize" }}> <span className="title" style={{ textTransform: 'capitalize' }}>
Create {this.state.addonMetadata.type} Pack Create {this.state.addonMetadata.type} Pack
</span> </span>
<span className="subtitle">Description of what is being made</span> <span className="subtitle">Description of what is being made</span>
@ -288,120 +258,97 @@ export default class Create extends PureComponent {
<MdDownload /> <MdDownload />
</button> </button>
</div> </div>
<SettingsItem <SettingsItem title={getMessage('modals.main.addons.create.metadata.name')}>
title={getMessage("modals.main.addons.create.metadata.name")}
>
<TextField <TextField
label={getMessage("modals.main.addons.create.metadata.name")} label={getMessage('modals.main.addons.create.metadata.name')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonMetadata.name} value={this.state.addonMetadata.name}
onInput={(e) => setMetadata(e.target.value, "name")} onInput={(e) => setMetadata(e.target.value, 'name')}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem title={getMessage('modals.main.marketplace.product.version')}>
title={getMessage("modals.main.marketplace.product.version")}
>
<TextField <TextField
label={getMessage("modals.main.marketplace.product.version")} label={getMessage('modals.main.marketplace.product.version')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonMetadata.version} value={this.state.addonMetadata.version}
onInput={(e) => setMetadata(e.target.value, "version")} onInput={(e) => setMetadata(e.target.value, 'version')}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem title={getMessage('modals.main.marketplace.product.author')}>
title={getMessage("modals.main.marketplace.product.author")}
>
<TextField <TextField
label={getMessage("modals.main.marketplace.product.author")} label={getMessage('modals.main.marketplace.product.author')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonMetadata.author} value={this.state.addonMetadata.author}
onInput={(e) => setMetadata(e.target.value, "author")} onInput={(e) => setMetadata(e.target.value, 'author')}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem title={getMessage('modals.main.addons.create.metadata.icon_url')}>
title={getMessage("modals.main.addons.create.metadata.icon_url")}
>
<TextField <TextField
label={getMessage("modals.main.addons.create.metadata.icon_url")} label={getMessage('modals.main.addons.create.metadata.icon_url')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonMetadata.icon_url} value={this.state.addonMetadata.icon_url}
onInput={(e) => setMetadata(e.target.value, "icon_url")} onInput={(e) => setMetadata(e.target.value, 'icon_url')}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem title={getMessage('modals.main.addons.create.metadata.screenshot_url')}>
title={getMessage(
"modals.main.addons.create.metadata.screenshot_url"
)}
>
<TextField <TextField
label={getMessage( label={getMessage('modals.main.addons.create.metadata.screenshot_url')}
"modals.main.addons.create.metadata.screenshot_url"
)}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonMetadata.screenshot_url} value={this.state.addonMetadata.screenshot_url}
onInput={(e) => setMetadata(e.target.value, "screenshot_url")} onInput={(e) => setMetadata(e.target.value, 'screenshot_url')}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem title={getMessage('modals.main.addons.create.metadata.description')}>
title={getMessage("modals.main.addons.create.metadata.description")}
>
<TextField <TextField
label={getMessage("modals.main.addons.create.metadata.description")} label={getMessage('modals.main.addons.create.metadata.description')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
multiline multiline
spellCheck={false} spellCheck={false}
rows={4} rows={4}
value={this.state.addonMetadata.description} value={this.state.addonMetadata.description}
onInput={(e) => setMetadata(e.target.value, "description")} onInput={(e) => setMetadata(e.target.value, 'description')}
/> />
</SettingsItem> </SettingsItem>
<div className="createButtons"> <div className="createButtons">
<button onClick={() => this.changeTab(1)}> <button onClick={() => this.changeTab(1)}>
{getMessage("modals.welcome.buttons.previous")} {getMessage('modals.welcome.buttons.previous')}
</button> </button>
<button <button
onClick={() => this.changeTab(this.state.addonMetadata.type)} onClick={() => this.changeTab(this.state.addonMetadata.type)}
disabled={nextDescriptionDisabled} disabled={nextDescriptionDisabled}
> >
{getMessage("modals.welcome.buttons.next")} {getMessage('modals.welcome.buttons.next')}
</button> </button>
</div> </div>
</> </>
); );
// settings // settings
const nextSettingsDisabled = this.state.addonData === ""; const nextSettingsDisabled = this.state.addonData === '';
const importSettings = ( const importSettings = (
<> <>
<SettingsItem <SettingsItem final={true} title={getMessage('modals.welcome.sections.settings.title')}>
final={true}
title={getMessage("modals.welcome.sections.settings.title")}
>
<div className="themesToggleArea"> <div className="themesToggleArea">
<div className="options" style={{ maxWidth: "512px" }}> <div className="options" style={{ maxWidth: '512px' }}>
<div <div
className={this.state.settingsClasses.current} className={this.state.settingsClasses.current}
onClick={() => this.importSettings()} onClick={() => this.importSettings()}
> >
<ExportIcon /> <ExportIcon />
<span> <span>{getMessage('modals.main.addons.create.settings.current')}</span>
{getMessage("modals.main.addons.create.settings.current")}
</span>
</div> </div>
<div <div
className={this.state.settingsClasses.json} className={this.state.settingsClasses.json}
onClick={() => document.getElementById("file-input").click()} onClick={() => document.getElementById('file-input').click()}
> >
<ImportIcon /> <ImportIcon />
<span> <span>{getMessage('modals.main.addons.create.settings.json')}</span>
{getMessage("modals.main.addons.create.settings.json")}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -411,20 +358,15 @@ export default class Create extends PureComponent {
id="file-input" id="file-input"
type="settings" type="settings"
accept="application/json" accept="application/json"
loadFunction={(e) => loadFunction={(e) => this.importSettings(JSON.parse(e.target.result))}
this.importSettings(JSON.parse(e.target.result))
}
/> />
</SettingsItem> </SettingsItem>
<div className="createButtons"> <div className="createButtons">
<button onClick={() => this.changeTab(2)}> <button onClick={() => this.changeTab(2)}>
{getMessage("modals.welcome.buttons.previous")} {getMessage('modals.welcome.buttons.previous')}
</button> </button>
<button <button onClick={() => this.changeTab(3)} disabled={nextSettingsDisabled}>
onClick={() => this.changeTab(3)} {getMessage('modals.welcome.buttons.next')}
disabled={nextSettingsDisabled}
>
{getMessage("modals.welcome.buttons.next")}
</button> </button>
</div> </div>
</> </>
@ -432,68 +374,68 @@ export default class Create extends PureComponent {
// quotes // quotes
const nextQuotesDisabled = !( const nextQuotesDisabled = !(
(this.state.addonMetadata.type === "quote_api" && (this.state.addonMetadata.type === 'quote_api' &&
this.state.addonData.url !== "" && this.state.addonData.url !== '' &&
this.state.addonData.name !== "" && this.state.addonData.name !== '' &&
this.state.addonData.author !== "") || this.state.addonData.author !== '') ||
(this.state.addonMetadata.type === "quotes" && (this.state.addonMetadata.type === 'quotes' && this.state.addonData.quotes !== '')
this.state.addonData.quotes !== "")
); );
const addQuotes = ( const addQuotes = (
<> <>
<SettingsItem final={true} title={getMessage("modals.main.addons.create.quotes.title")}> <SettingsItem final={true} title={getMessage('modals.main.addons.create.quotes.title')}>
<Dropdown <Dropdown
label={getMessage("modals.main.settings.sections.time.type")} label={getMessage('modals.main.settings.sections.time.type')}
noSetting noSetting
onChange={(e) => this.updateQuotePackType(e)} onChange={(e) => this.updateQuotePackType(e)}
> >
<option value="quotes"> <option value="quotes">
{getMessage("modals.main.addons.create.quotes.local.title")} {getMessage('modals.main.addons.create.quotes.local.title')}
</option> </option>
<option value="quote_api"> <option value="quote_api">
{getMessage("modals.main.addons.create.quotes.api.title")} {getMessage('modals.main.addons.create.quotes.api.title')}
</option> </option>
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
{this.state.addonMetadata.type === "quote_api" ? ( {this.state.addonMetadata.type === 'quote_api' ? (
<> <>
<TextField <TextField
label={getMessage("modals.main.addons.create.quotes.api.url")} label={getMessage('modals.main.addons.create.quotes.api.url')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonData.url} value={this.state.addonData.url}
onInput={(e) => this.updateQuotePack(e.target.value, "url")} onInput={(e) => this.updateQuotePack(e.target.value, 'url')}
/> />
<TextField <TextField
label={getMessage("modals.main.addons.create.quotes.api.name")} label={getMessage('modals.main.addons.create.quotes.api.name')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonData.name} value={this.state.addonData.name}
onInput={(e) => this.updateQuotePack(e.target.value, "name")} onInput={(e) => this.updateQuotePack(e.target.value, 'name')}
/> />
<TextField <TextField
label={getMessage("modals.main.addons.create.quotes.api.author")} label={getMessage('modals.main.addons.create.quotes.api.author')}
varient="outlined" varient="outlined"
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
value={this.state.addonData.author} value={this.state.addonData.author}
onInput={(e) => this.updateQuotePack(e.target.value, "author")} onInput={(e) => this.updateQuotePack(e.target.value, 'author')}
/> />
<br /> <br />
<br /> <br />
</> </>
) : ( ) : (
<SettingsItem final={true} title={getMessage("modals.main.addons.create.settings.current")} > <SettingsItem
final={true}
title={getMessage('modals.main.addons.create.settings.current')}
>
<div className="themesToggleArea"> <div className="themesToggleArea">
<div className="options"> <div className="options">
<div <div
onClick={() => this.importQuotes()} onClick={() => this.importQuotes()}
className="toggle lightTheme" className="toggle lightTheme"
style={{ width: "60%", margin: "10px 0 10px 0" }} style={{ width: '60%', margin: '10px 0 10px 0' }}
> >
<ExportIcon /> <ExportIcon />
<span> <span>{getMessage('modals.main.addons.create.settings.current')}</span>
{getMessage("modals.main.addons.create.settings.current")}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -501,13 +443,10 @@ export default class Create extends PureComponent {
)} )}
<div className="createButtons"> <div className="createButtons">
<button onClick={() => this.changeTab(2)}> <button onClick={() => this.changeTab(2)}>
{getMessage("modals.welcome.buttons.previous")} {getMessage('modals.welcome.buttons.previous')}
</button> </button>
<button <button onClick={() => this.changeTab(3)} disabled={nextQuotesDisabled}>
onClick={() => this.changeTab(3)} {getMessage('modals.welcome.buttons.next')}
disabled={nextQuotesDisabled}
>
{getMessage("modals.welcome.buttons.next")}
</button> </button>
</div> </div>
</> </>
@ -515,26 +454,24 @@ export default class Create extends PureComponent {
// photos // photos
const nextPhotosDisabled = !( const nextPhotosDisabled = !(
this.state.addonData.photos !== "" && this.state.addonData.photos !== [] this.state.addonData.photos !== '' && this.state.addonData.photos !== []
); );
const addPhotos = ( const addPhotos = (
<> <>
<SettingsItem <SettingsItem
final={true} final={true}
title={getMessage("modals.main.addons.create.photos.title")} title={getMessage('modals.main.addons.create.photos.title')}
subtitle={"Import from custom settings."} subtitle={'Import from custom settings.'}
> >
<div className="themesToggleArea"> <div className="themesToggleArea">
<div className="options"> <div className="options">
<div <div
onClick={() => this.importPhotos()} onClick={() => this.importPhotos()}
className="toggle lightTheme" className="toggle lightTheme"
style={{ width: "60%", margin: "10px 0 10px 0" }} style={{ width: '60%', margin: '10px 0 10px 0' }}
> >
<ExportIcon /> <ExportIcon />
<span> <span>{getMessage('modals.main.addons.create.settings.current')}</span>
{getMessage("modals.main.addons.create.settings.current")}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -542,13 +479,10 @@ export default class Create extends PureComponent {
<br /> <br />
<div className="createButtons"> <div className="createButtons">
<button onClick={() => this.changeTab(2)}> <button onClick={() => this.changeTab(2)}>
{getMessage("modals.welcome.buttons.previous")} {getMessage('modals.welcome.buttons.previous')}
</button> </button>
<button <button onClick={() => this.changeTab(3)} disabled={nextPhotosDisabled}>
onClick={() => this.changeTab(3)} {getMessage('modals.welcome.buttons.next')}
disabled={nextPhotosDisabled}
>
{getMessage("modals.welcome.buttons.next")}
</button> </button>
</div> </div>
</> </>
@ -558,12 +492,11 @@ export default class Create extends PureComponent {
<> <>
<div className="smallBanner"> <div className="smallBanner">
<div className="content"> <div className="content">
<span className="title" style={{ textTransform: "capitalize" }}> <span className="title" style={{ textTransform: 'capitalize' }}>
Next step, Publishing... Next step, Publishing...
</span> </span>
<span className="subtitle"> <span className="subtitle">
Visit the Mue Knowledgebase on information on how to publish your Visit the Mue Knowledgebase on information on how to publish your newly created addon.
newly created addon.
</span> </span>
</div> </div>
<button> <button>
@ -577,12 +510,10 @@ export default class Create extends PureComponent {
<div <div
onClick={() => this.downloadAddon()} onClick={() => this.downloadAddon()}
className="toggle lightTheme" className="toggle lightTheme"
style={{ width: "60%", margin: "10px 0 10px 0" }} style={{ width: '60%', margin: '10px 0 10px 0' }}
> >
<ExportIcon /> <ExportIcon />
<span> <span>{getMessage('modals.main.addons.create.finish.download')}</span>
{getMessage("modals.main.addons.create.finish.download")}
</span>
</div> </div>
</div> </div>
</div> </div>
@ -591,14 +522,14 @@ export default class Create extends PureComponent {
<button <button
onClick={() => onClick={() =>
this.changeTab( this.changeTab(
this.state.addonMetadata.type === "quote_api" this.state.addonMetadata.type === 'quote_api'
? "quotes" ? 'quotes'
: this.state.addonMetadata.type : this.state.addonMetadata.type,
) )
} }
disabled={nextDescriptionDisabled} disabled={nextDescriptionDisabled}
> >
{getMessage("modals.welcome.buttons.previous")} {getMessage('modals.welcome.buttons.previous')}
</button> </button>
</div> </div>
{/*<button {/*<button
@ -619,13 +550,13 @@ export default class Create extends PureComponent {
case 2: case 2:
tabContent = writeDescription; tabContent = writeDescription;
break; break;
case "settings": case 'settings':
tabContent = importSettings; tabContent = importSettings;
break; break;
case "quotes": case 'quotes':
tabContent = addQuotes; tabContent = addQuotes;
break; break;
case "photos": case 'photos':
tabContent = addPhotos; tabContent = addPhotos;
break; break;
case 3: case 3:
@ -648,9 +579,7 @@ export default class Create extends PureComponent {
</Tooltip> </Tooltip>
</div> </div>
)} )}
<span className="mainTitle"> <span className="mainTitle">{getMessage('modals.main.addons.create.other_title')}</span>
{getMessage("modals.main.addons.create.other_title")}
</span>
</div> </div>
{tabContent} {tabContent}
</> </>

View File

@ -146,7 +146,7 @@ h5 {
gap: 15px; gap: 15px;
align-items: center; align-items: center;
&:hover { &:hover {
opacity: .8; opacity: 0.8;
cursor: pointer; cursor: pointer;
} }
} }
@ -187,7 +187,7 @@ h5 {
gap: 15px; gap: 15px;
align-items: center; align-items: center;
&:hover { &:hover {
opacity: .8; opacity: 0.8;
cursor: pointer; cursor: pointer;
} }
} }

View File

@ -3,7 +3,6 @@
margin-left: 20px; margin-left: 20px;
} }
p.description { p.description {
margin-top: 0; margin-top: 0;
max-width: 800px; max-width: 800px;

View File

@ -102,4 +102,4 @@ table {
svg { svg {
font-size: 1.5rem !important; font-size: 1.5rem !important;
} }
} }

View File

@ -26,4 +26,4 @@
display: flex; display: flex;
flex-flow: row; flex-flow: row;
justify-content: space-around; justify-content: space-around;
} }

View File

@ -8,23 +8,26 @@ export default class Checkbox extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
checked: (localStorage.getItem(this.props.name) === 'true') checked: localStorage.getItem(this.props.name) === 'true',
}; };
} }
handleChange = () => { handleChange = () => {
const value = (this.state.checked !== true); const value = this.state.checked !== true;
localStorage.setItem(this.props.name, value); localStorage.setItem(this.props.name, value);
this.setState({ this.setState({
checked: value checked: value,
}); });
if (this.props.onChange) { if (this.props.onChange) {
this.props.onChange(value); this.props.onChange(value);
} }
variables.stats.postEvent('setting', `${this.props.name} ${(this.state.checked === true) ? 'enabled' : 'disabled'}`); variables.stats.postEvent(
'setting',
`${this.props.name} ${this.state.checked === true ? 'enabled' : 'disabled'}`,
);
if (this.props.element) { if (this.props.element) {
if (!document.querySelector(this.props.element)) { if (!document.querySelector(this.props.element)) {
@ -34,13 +37,22 @@ export default class Checkbox extends PureComponent {
} }
EventBus.dispatch('refresh', this.props.category); EventBus.dispatch('refresh', this.props.category);
} };
render() { render() {
return ( return (
<> <>
<FormControlLabel <FormControlLabel
control={<CheckboxUI name={this.props.name} color='primary' className='checkbox' checked={this.state.checked} onChange={this.handleChange} disabled={this.props.disabled || false} />} control={
<CheckboxUI
name={this.props.name}
color="primary"
className="checkbox"
checked={this.state.checked}
onChange={this.handleChange}
disabled={this.props.disabled || false}
/>
}
label={this.props.text} label={this.props.text}
/> />
</> </>

View File

@ -9,7 +9,7 @@ export default class Dropdown extends PureComponent {
super(props); super(props);
this.state = { this.state = {
value: localStorage.getItem(this.props.name) || this.props.children[0].props.value, value: localStorage.getItem(this.props.name) || this.props.children[0].props.value,
title: '' title: '',
}; };
this.dropdown = createRef(); this.dropdown = createRef();
} }
@ -24,13 +24,13 @@ export default class Dropdown extends PureComponent {
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`); variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
this.setState({ this.setState({
value value,
}); });
if (!this.props.noSetting) { if (!this.props.noSetting) {
localStorage.setItem(this.props.name, value); localStorage.setItem(this.props.name, value);
} }
if (this.props.onChange) { if (this.props.onChange) {
this.props.onChange(value); this.props.onChange(value);
} }
@ -43,7 +43,7 @@ export default class Dropdown extends PureComponent {
} }
EventBus.dispatch('refresh', this.props.category); EventBus.dispatch('refresh', this.props.category);
} };
render() { render() {
const id = 'dropdown' + this.props.name; const id = 'dropdown' + this.props.name;
@ -52,10 +52,24 @@ export default class Dropdown extends PureComponent {
return ( return (
<FormControl fullWidth className={id}> <FormControl fullWidth className={id}>
<InputLabel id={id}>{label}</InputLabel> <InputLabel id={id}>{label}</InputLabel>
<Select labelId={id} id={this.props.name} value={this.state.value} label={label} onChange={this.onChange} ref={this.dropdown} key={id}> <Select
{this.props.manual ? this.props.children : this.props.children.map((e, index) => { labelId={id}
return e ? <MenuItem key={index} value={e.props ? e.props.value : ''}>{e.props ? e.props.children : ''}</MenuItem> : null id={this.props.name}
})} value={this.state.value}
label={label}
onChange={this.onChange}
ref={this.dropdown}
key={id}
>
{this.props.manual
? this.props.children
: this.props.children.map((e, index) => {
return e ? (
<MenuItem key={index} value={e.props ? e.props.value : ''}>
{e.props ? e.props.children : ''}
</MenuItem>
) : null;
})}
</Select> </Select>
</FormControl> </FormControl>
); );

View File

@ -28,6 +28,13 @@ export default class FileUpload extends PureComponent {
} }
render() { render() {
return <input id={this.props.id} type='file' style={{ display: 'none' }} accept={this.props.accept} />; return (
<input
id={this.props.id}
type="file"
style={{ display: 'none' }}
accept={this.props.accept}
/>
);
} }
} }

View File

@ -7,17 +7,53 @@ export default function KeybindInput(props) {
const getButton = () => { const getButton = () => {
if (!value) { if (!value) {
return <button className='cleanButton' style={{ visibility: 'hidden' }} onClick={() => props.action('reset', props.setting)}><MdCancel/></button>;; return (
} else if (value === variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.keybinds.recording')) { <button
return <button className='cleanButton' onClick={() => props.action('cancel', props.setting)}><MdCancel/></button>; className="cleanButton"
style={{ visibility: 'hidden' }}
onClick={() => props.action('reset', props.setting)}
>
<MdCancel />
</button>
);
} else if (
value ===
variables.language.getMessage(
variables.languagecode,
'modals.main.settings.sections.keybinds.recording',
)
) {
return (
<button className="cleanButton" onClick={() => props.action('cancel', props.setting)}>
<MdCancel />
</button>
);
} else { } else {
return <button className='cleanButton' onClick={() => props.action('reset', props.setting)}><MdCancel/></button>; return (
<button className="cleanButton" onClick={() => props.action('reset', props.setting)}>
<MdCancel />
</button>
);
} }
} };
return ( return (
<> <>
<TextField label={props.name} onClick={() => props.action('listen', props.setting)} value={value || variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.keybinds.click_to_record')} readOnly spellCheck={false} varient='outlined' InputLabelProps={{ shrink: true }} /> <TextField
label={props.name}
onClick={() => props.action('listen', props.setting)}
value={
value ||
variables.language.getMessage(
variables.languagecode,
'modals.main.settings.sections.keybinds.click_to_record',
)
}
readOnly
spellCheck={false}
varient="outlined"
InputLabelProps={{ shrink: true }}
/>
{getButton()} {getButton()}
</> </>
); );

View File

@ -1,6 +1,12 @@
import variables from 'modules/variables'; import variables from 'modules/variables';
import { PureComponent } from 'react'; import { PureComponent } from 'react';
import { Radio as RadioUI, RadioGroup, FormControlLabel, FormControl, FormLabel } from '@mui/material'; import {
Radio as RadioUI,
RadioGroup,
FormControlLabel,
FormControl,
FormLabel,
} from '@mui/material';
import EventBus from 'modules/helpers/eventbus'; import EventBus from 'modules/helpers/eventbus';
@ -8,10 +14,10 @@ export default class Radio extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
value: localStorage.getItem(this.props.name) value: localStorage.getItem(this.props.name),
}; };
} }
handleChange = (e) => { handleChange = (e) => {
const { value } = e.target; const { value } = e.target;
@ -21,15 +27,21 @@ export default class Radio extends PureComponent {
if (this.props.name === 'language') { if (this.props.name === 'language') {
// old tab name // old tab name
if (localStorage.getItem('tabName') === variables.language.getMessage(variables.languagecode, 'tabname')) { if (
localStorage.setItem('tabName', require(`translations/${value.replace('-', '_')}.json`).tabname); localStorage.getItem('tabName') ===
variables.language.getMessage(variables.languagecode, 'tabname')
) {
localStorage.setItem(
'tabName',
require(`translations/${value.replace('-', '_')}.json`).tabname,
);
} }
} }
localStorage.setItem(this.props.name, value); localStorage.setItem(this.props.name, value);
this.setState({ this.setState({
value value,
}); });
if (this.props.onChange) { if (this.props.onChange) {
@ -37,7 +49,7 @@ export default class Radio extends PureComponent {
} }
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`); variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
if (this.props.element) { if (this.props.element) {
if (!document.querySelector(this.props.element)) { if (!document.querySelector(this.props.element)) {
document.querySelector('.reminder-info').style.display = 'flex'; document.querySelector('.reminder-info').style.display = 'flex';
@ -46,15 +58,30 @@ export default class Radio extends PureComponent {
} }
EventBus.dispatch('refresh', this.props.category); EventBus.dispatch('refresh', this.props.category);
} };
render() { render() {
return ( return (
<FormControl component='fieldset'> <FormControl component="fieldset">
<FormLabel className={this.props.smallTitle ? 'radio-title-small' : 'radio-title'} component='legend'>{this.props.title}</FormLabel> <FormLabel
<RadioGroup aria-label={this.props.name} name={this.props.name} onChange={this.handleChange} value={this.state.value}> className={this.props.smallTitle ? 'radio-title-small' : 'radio-title'}
component="legend"
>
{this.props.title}
</FormLabel>
<RadioGroup
aria-label={this.props.name}
name={this.props.name}
onChange={this.handleChange}
value={this.state.value}
>
{this.props.options.map((option) => ( {this.props.options.map((option) => (
<FormControlLabel value={option.value} control={<RadioUI/>} label={option.name} key={option.name} /> <FormControlLabel
value={option.value}
control={<RadioUI />}
label={option.name}
key={option.name}
/>
))} ))}
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>

View File

@ -8,19 +8,22 @@ export default class Switch extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
checked: (localStorage.getItem(this.props.name) === 'true') checked: localStorage.getItem(this.props.name) === 'true',
}; };
} }
handleChange = () => { handleChange = () => {
const value = (this.state.checked !== true); const value = this.state.checked !== true;
localStorage.setItem(this.props.name, value); localStorage.setItem(this.props.name, value);
this.setState({ this.setState({
checked: value checked: value,
}); });
variables.stats.postEvent('setting', `${this.props.name} ${(this.state.checked === true) ? 'enabled' : 'disabled'}`); variables.stats.postEvent(
'setting',
`${this.props.name} ${this.state.checked === true ? 'enabled' : 'disabled'}`,
);
if (this.props.element) { if (this.props.element) {
if (!document.querySelector(this.props.element)) { if (!document.querySelector(this.props.element)) {
@ -30,15 +33,22 @@ export default class Switch extends PureComponent {
} }
EventBus.dispatch('refresh', this.props.category); EventBus.dispatch('refresh', this.props.category);
} };
render() { render() {
return ( return (
<> <>
<FormControlLabel <FormControlLabel
control={<SwitchUI name={this.props.name} color='primary' checked={this.state.checked} onChange={this.handleChange} />} control={
<SwitchUI
name={this.props.name}
color="primary"
checked={this.state.checked}
onChange={this.handleChange}
/>
}
label={this.props.text} label={this.props.text}
labelPlacement='start' labelPlacement="start"
/> />
</> </>
); );

View File

@ -9,13 +9,13 @@ export default class Text extends PureComponent {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
value: localStorage.getItem(this.props.name) || '' value: localStorage.getItem(this.props.name) || '',
}; };
} }
handleChange = (e) => { handleChange = (e) => {
let { value } = e.target; let { value } = e.target;
// Alex wanted font to work with montserrat and Montserrat, so I made it work // Alex wanted font to work with montserrat and Montserrat, so I made it work
if (this.props.upperCaseFirst === true) { if (this.props.upperCaseFirst === true) {
value = value.charAt(0).toUpperCase() + value.slice(1); value = value.charAt(0).toUpperCase() + value.slice(1);
@ -23,7 +23,7 @@ export default class Text extends PureComponent {
localStorage.setItem(this.props.name, value); localStorage.setItem(this.props.name, value);
this.setState({ this.setState({
value value,
}); });
if (this.props.element) { if (this.props.element) {
@ -34,25 +34,47 @@ export default class Text extends PureComponent {
} }
EventBus.dispatch('refresh', this.props.category); EventBus.dispatch('refresh', this.props.category);
} };
resetItem = () => { resetItem = () => {
this.handleChange({ this.handleChange({
target: { target: {
value: this.props.default || '' value: this.props.default || '',
} },
}); });
toast(variables.language.getMessage(variables.languagecode, 'toasts.reset')); toast(variables.language.getMessage(variables.languagecode, 'toasts.reset'));
} };
render() { render() {
return ( return (
<> <>
{(this.props.textarea === true) ? {this.props.textarea === true ? (
<TextField label={this.props.title} value={this.state.value} onChange={this.handleChange} varient='outlined' multiline spellCheck={false} minRows={4} maxRows={10} InputLabelProps={{ shrink: true }} /> <TextField
: <TextField label={this.props.title} value={this.state.value} onChange={this.handleChange} varient='outlined' InputLabelProps={{ shrink: true }} /> label={this.props.title}
} value={this.state.value}
<span className='link' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span> onChange={this.handleChange}
varient="outlined"
multiline
spellCheck={false}
minRows={4}
maxRows={10}
InputLabelProps={{ shrink: true }}
/>
) : (
<TextField
label={this.props.title}
value={this.state.value}
onChange={this.handleChange}
varient="outlined"
InputLabelProps={{ shrink: true }}
/>
)}
<span className="link" onClick={this.resetItem}>
{variables.language.getMessage(
variables.languagecode,
'modals.main.settings.buttons.reset',
)}
</span>
</> </>
); );
} }

View File

@ -134,7 +134,7 @@ export default class About extends PureComponent {
<span className="mainTitle"> <span className="mainTitle">
{this.getMessage('modals.main.settings.sections.about.title')} {this.getMessage('modals.main.settings.sections.about.title')}
</span> </span>
<div className='settingsRow' style={{ justifyContent: 'center' }}> <div className="settingsRow" style={{ justifyContent: 'center' }}>
<div style={{ display: 'flex', flexFlow: 'column', gap: '5px' }}> <div style={{ display: 'flex', flexFlow: 'column', gap: '5px' }}>
<img draggable="false" className="aboutLogo" src={this.state.image} alt="Logo" /> <img draggable="false" className="aboutLogo" src={this.state.image} alt="Logo" />
<span className="title"> <span className="title">
@ -179,10 +179,10 @@ export default class About extends PureComponent {
{this.getMessage('modals.main.settings.sections.about.contact_us')} {this.getMessage('modals.main.settings.sections.about.contact_us')}
</span> </span>
<div className="aboutContact"> <div className="aboutContact">
<a class='donateButton' href='https://muetab.com/contact'> <a class="donateButton" href="https://muetab.com/contact">
<MdContactPage /> <MdContactPage />
Form Form
</a> </a>
<Tooltip title={'Email'}> <Tooltip title={'Email'}>
<a <a
href={'mailto:' + variables.constants.EMAIL} href={'mailto:' + variables.constants.EMAIL}
@ -217,13 +217,16 @@ export default class About extends PureComponent {
<span className="title"> <span className="title">
{this.getMessage('modals.main.settings.sections.about.support_mue')} {this.getMessage('modals.main.settings.sections.about.support_mue')}
</span> </span>
<p>As Mue is entirely free, we rely on donations to cover pay the server bills and fund development</p> <p>
As Mue is entirely free, we rely on donations to cover pay the server bills and fund
development
</p>
<div className="aboutContact"> <div className="aboutContact">
<a class='donateButton' href={variables.constants.DONATE_LINK}> <a class="donateButton" href={variables.constants.DONATE_LINK}>
<BiDonateHeart /> <BiDonateHeart />
Donate Donate
</a> </a>
<Tooltip title={'Github Sponsors'}> <Tooltip title={'Github Sponsors'}>
<a <a
href={'https://discord.gg/' + variables.constants.DISCORD_SERVER} href={'https://discord.gg/' + variables.constants.DISCORD_SERVER}
target="_blank" target="_blank"

View File

@ -1,27 +1,24 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import Modal from "react-modal"; import Modal from 'react-modal';
import { MenuItem } from "@mui/material"; import { MenuItem } from '@mui/material';
import { import {
MdUpload as ImportIcon, MdUpload as ImportIcon,
MdDownload as ExportIcon, MdDownload as ExportIcon,
MdRestartAlt as ResetIcon, MdRestartAlt as ResetIcon,
} from "react-icons/md"; } from 'react-icons/md';
import { import { exportSettings, importSettings } from 'modules/helpers/settings/modals';
exportSettings,
importSettings,
} from "modules/helpers/settings/modals";
import Checkbox from "../Checkbox"; import Checkbox from '../Checkbox';
import FileUpload from "../FileUpload"; import FileUpload from '../FileUpload';
import Text from "../Text"; import Text from '../Text';
import Switch from "../Switch"; import Switch from '../Switch';
import ResetModal from "../ResetModal"; import ResetModal from '../ResetModal';
import Dropdown from "../Dropdown"; import Dropdown from '../Dropdown';
import SettingsItem from "../SettingsItem"; import SettingsItem from '../SettingsItem';
const time_zones = require("components/widgets/time/timezones.json"); const time_zones = require('components/widgets/time/timezones.json');
export default class AdvancedSettings extends PureComponent { export default class AdvancedSettings extends PureComponent {
constructor() { constructor() {
@ -32,52 +29,41 @@ export default class AdvancedSettings extends PureComponent {
} }
render() { render() {
const getMessage = (text) => const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
return ( return (
<> <>
<span className="mainTitle"> <span className="mainTitle">
{getMessage("modals.main.settings.sections.advanced.title")} {getMessage('modals.main.settings.sections.advanced.title')}
</span> </span>
<SettingsItem <SettingsItem title={getMessage('modals.main.settings.sections.advanced.offline_mode')}>
title={getMessage(
"modals.main.settings.sections.advanced.offline_mode"
)}
>
<Switch <Switch
name="offlineMode" name="offlineMode"
text={getMessage( text={getMessage('modals.main.settings.sections.advanced.offline_mode')}
"modals.main.settings.sections.advanced.offline_mode"
)}
element=".other" element=".other"
/> />
</SettingsItem> </SettingsItem>
{localStorage.getItem("welcomePreview") !== "true" ? ( {localStorage.getItem('welcomePreview') !== 'true' ? (
<div className="settingsRow"> <div className="settingsRow">
<div className="content"> <div className="content">
<span className="title"> <span className="title">
{getMessage("modals.main.settings.sections.advanced.data")} {getMessage('modals.main.settings.sections.advanced.data')}
</span> </span>
<span className="subtitle"> <span className="subtitle">
{getMessage( {getMessage('modals.main.settings.sections.advanced.experimental_warning')}
"modals.main.settings.sections.advanced.experimental_warning"
)}
</span> </span>
</div> </div>
<div className="action activityButtons"> <div className="action activityButtons">
<button onClick={() => this.setState({ resetModal: true })}> <button onClick={() => this.setState({ resetModal: true })}>
{getMessage("modals.main.settings.buttons.reset")} {getMessage('modals.main.settings.buttons.reset')}
<ResetIcon /> <ResetIcon />
</button> </button>
<button onClick={() => exportSettings()}> <button onClick={() => exportSettings()}>
{getMessage("modals.main.settings.buttons.export")} {getMessage('modals.main.settings.buttons.export')}
<ExportIcon /> <ExportIcon />
</button> </button>
<button <button onClick={() => document.getElementById('file-input').click()}>
onClick={() => document.getElementById("file-input").click()} {getMessage('modals.main.settings.buttons.import')}
>
{getMessage("modals.main.settings.buttons.import")}
<ImportIcon /> <ImportIcon />
</button> </button>
</div> </div>
@ -86,16 +72,12 @@ export default class AdvancedSettings extends PureComponent {
<SettingsItem title="This should really be in time"> <SettingsItem title="This should really be in time">
<Dropdown <Dropdown
name="timezone" name="timezone"
label={getMessage( label={getMessage('modals.main.settings.sections.advanced.timezone.title')}
"modals.main.settings.sections.advanced.timezone.title"
)}
category="timezone" category="timezone"
manual={true} manual={true}
> >
<MenuItem value="auto"> <MenuItem value="auto">
{getMessage( {getMessage('modals.main.settings.sections.advanced.timezone.automatic')}
"modals.main.settings.sections.advanced.timezone.automatic"
)}
</MenuItem> </MenuItem>
{time_zones.map((timezone) => ( {time_zones.map((timezone) => (
<MenuItem value={timezone} key={timezone}> <MenuItem value={timezone} key={timezone}>
@ -104,15 +86,11 @@ export default class AdvancedSettings extends PureComponent {
))} ))}
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem title={getMessage('modals.main.settings.sections.advanced.tab_name')}>
title={getMessage("modals.main.settings.sections.advanced.tab_name")}
>
<Text <Text
title={getMessage( title={getMessage('modals.main.settings.sections.advanced.tab_name')}
"modals.main.settings.sections.advanced.tab_name"
)}
name="tabName" name="tabName"
default={getMessage("tabname")} default={getMessage('tabname')}
category="other" category="other"
/> />
</SettingsItem> </SettingsItem>
@ -122,15 +100,9 @@ export default class AdvancedSettings extends PureComponent {
type="settings" type="settings"
loadFunction={(e) => importSettings(e)} loadFunction={(e) => importSettings(e)}
/> />
<SettingsItem <SettingsItem title={getMessage('modals.main.settings.sections.advanced.custom_css')}>
title={getMessage(
"modals.main.settings.sections.advanced.custom_css"
)}
>
<Text <Text
title={getMessage( title={getMessage('modals.main.settings.sections.advanced.custom_css')}
"modals.main.settings.sections.advanced.custom_css"
)}
name="customcss" name="customcss"
textarea={true} textarea={true}
category="other" category="other"
@ -139,18 +111,16 @@ export default class AdvancedSettings extends PureComponent {
<div className="settingsRow"> <div className="settingsRow">
<div className="content"> <div className="content">
<span className="title"> <span className="title">
{getMessage("modals.main.settings.sections.experimental.title")} {getMessage('modals.main.settings.sections.experimental.title')}
</span> </span>
<span className="subtitle"> <span className="subtitle">
{getMessage( {getMessage('modals.main.settings.sections.advanced.experimental_warning')}
"modals.main.settings.sections.advanced.experimental_warning"
)}
</span> </span>
</div> </div>
<div className="action"> <div className="action">
<Switch <Switch
name="experimental" name="experimental"
text={getMessage("modals.main.settings.enabled")} text={getMessage('modals.main.settings.enabled')}
element=".other" element=".other"
/> />
</div> </div>

View File

@ -1,53 +1,52 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import Checkbox from "../Checkbox"; import Checkbox from '../Checkbox';
import Dropdown from "../Dropdown"; import Dropdown from '../Dropdown';
import Radio from "../Radio"; import Radio from '../Radio';
import Slider from "../Slider"; import Slider from '../Slider';
import Text from "../Text"; import Text from '../Text';
import SettingsItem from "../SettingsItem"; import SettingsItem from '../SettingsItem';
import { values } from "modules/helpers/settings/modals"; import { values } from 'modules/helpers/settings/modals';
export default function AppearanceSettings() { export default function AppearanceSettings() {
const getMessage = (text) => const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
const themeOptions = [ const themeOptions = [
{ {
name: getMessage("modals.main.settings.sections.appearance.theme.auto"), name: getMessage('modals.main.settings.sections.appearance.theme.auto'),
value: "auto", value: 'auto',
}, },
{ {
name: getMessage("modals.main.settings.sections.appearance.theme.light"), name: getMessage('modals.main.settings.sections.appearance.theme.light'),
value: "light", value: 'light',
}, },
{ {
name: getMessage("modals.main.settings.sections.appearance.theme.dark"), name: getMessage('modals.main.settings.sections.appearance.theme.dark'),
value: "dark", value: 'dark',
}, },
]; ];
const styleOptions = [ const styleOptions = [
{ {
name: "Legacy", name: 'Legacy',
value: "legacy", value: 'legacy',
}, },
{ {
name: "New", name: 'New',
value: "new", value: 'new',
}, },
]; ];
return ( return (
<> <>
<span className="mainTitle"> <span className="mainTitle">
{getMessage("modals.main.settings.sections.appearance.title")} {getMessage('modals.main.settings.sections.appearance.title')}
</span> </span>
<div className="settingsRow"> <div className="settingsRow">
<div className="content"> <div className="content">
<span className="title"> <span className="title">
{getMessage("modals.main.settings.sections.appearance.theme.title")} {getMessage('modals.main.settings.sections.appearance.theme.title')}
</span> </span>
<span className="subtitle">subtitle</span> <span className="subtitle">subtitle</span>
</div> </div>
@ -58,96 +57,66 @@ export default function AppearanceSettings() {
<div className="settingsRow"> <div className="settingsRow">
<div className="content"> <div className="content">
<span className="title"> <span className="title">
{getMessage("modals.main.settings.sections.appearance.font.title")} {getMessage('modals.main.settings.sections.appearance.font.title')}
</span> </span>
<span className="subtitle">subtitle</span> <span className="subtitle">subtitle</span>
</div> </div>
<div className="action"> <div className="action">
<Checkbox <Checkbox
name="fontGoogle" name="fontGoogle"
text={getMessage( text={getMessage('modals.main.settings.sections.appearance.font.google')}
"modals.main.settings.sections.appearance.font.google"
)}
category="other" category="other"
/> />
<Text <Text
title={getMessage( title={getMessage('modals.main.settings.sections.appearance.font.custom')}
"modals.main.settings.sections.appearance.font.custom"
)}
name="font" name="font"
upperCaseFirst={true} upperCaseFirst={true}
category="other" category="other"
/> />
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.appearance.font.weight.title')}
"modals.main.settings.sections.appearance.font.weight.title"
)}
name="fontweight" name="fontweight"
category="other" category="other"
> >
{/* names are taken from https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight */} {/* names are taken from https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight */}
<option value="100"> <option value="100">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.thin')}
"modals.main.settings.sections.appearance.font.weight.thin"
)}
</option> </option>
<option value="200"> <option value="200">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.extra_light')}
"modals.main.settings.sections.appearance.font.weight.extra_light"
)}
</option> </option>
<option value="300"> <option value="300">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.light')}
"modals.main.settings.sections.appearance.font.weight.light"
)}
</option> </option>
<option value="400"> <option value="400">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.normal')}
"modals.main.settings.sections.appearance.font.weight.normal"
)}
</option> </option>
<option value="500"> <option value="500">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.medium')}
"modals.main.settings.sections.appearance.font.weight.medium"
)}
</option> </option>
<option value="600"> <option value="600">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.semi_bold')}
"modals.main.settings.sections.appearance.font.weight.semi_bold"
)}
</option> </option>
<option value="700"> <option value="700">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.bold')}
"modals.main.settings.sections.appearance.font.weight.bold"
)}
</option> </option>
<option value="800"> <option value="800">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.weight.extra_bold')}
"modals.main.settings.sections.appearance.font.weight.extra_bold"
)}
</option> </option>
</Dropdown> </Dropdown>
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.appearance.font.style.title')}
"modals.main.settings.sections.appearance.font.style.title"
)}
name="fontstyle" name="fontstyle"
category="other" category="other"
> >
<option value="normal"> <option value="normal">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.style.normal')}
"modals.main.settings.sections.appearance.font.style.normal"
)}
</option> </option>
<option value="italic"> <option value="italic">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.style.italic')}
"modals.main.settings.sections.appearance.font.style.italic"
)}
</option> </option>
<option value="oblique"> <option value="oblique">
{getMessage( {getMessage('modals.main.settings.sections.appearance.font.style.oblique')}
"modals.main.settings.sections.appearance.font.style.oblique"
)}
</option> </option>
</Dropdown> </Dropdown>
</div> </div>
@ -167,17 +136,13 @@ export default function AppearanceSettings() {
<div className="settingsRow"> <div className="settingsRow">
<div className="content"> <div className="content">
<span className="title"> <span className="title">
{getMessage( {getMessage('modals.main.settings.sections.appearance.accessibility.title')}
"modals.main.settings.sections.appearance.accessibility.title"
)}
</span> </span>
<span className="subtitle">subtitle</span> <span className="subtitle">subtitle</span>
</div> </div>
<div className="action"> <div className="action">
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.appearance.accessibility.text_shadow')}
"modals.main.settings.sections.appearance.accessibility.text_shadow"
)}
name="textBorder" name="textBorder"
category="other" category="other"
> >
@ -186,27 +151,23 @@ export default function AppearanceSettings() {
<option value="none">None</option> <option value="none">None</option>
</Dropdown> </Dropdown>
<Checkbox <Checkbox
text={getMessage( text={getMessage('modals.main.settings.sections.appearance.accessibility.animations')}
"modals.main.settings.sections.appearance.accessibility.animations"
)}
name="animations" name="animations"
category="other" category="other"
/> />
<Slider <Slider
title={getMessage( title={getMessage(
"modals.main.settings.sections.appearance.accessibility.toast_duration" 'modals.main.settings.sections.appearance.accessibility.toast_duration',
)} )}
name="toastDisplayTime" name="toastDisplayTime"
default="2500" default="2500"
step="100" step="100"
min="500" min="500"
max="5000" max="5000"
marks={values("toast")} marks={values('toast')}
display={ display={
" " + ' ' +
getMessage( getMessage('modals.main.settings.sections.appearance.accessibility.milliseconds')
"modals.main.settings.sections.appearance.accessibility.milliseconds"
)
} }
/> />
</div> </div>

View File

@ -1,9 +1,9 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent, createRef } from "react"; import { PureComponent, createRef } from 'react';
import { MdOutlineWifiOff } from "react-icons/md"; import { MdOutlineWifiOff } from 'react-icons/md';
import Modal from "react-modal"; import Modal from 'react-modal';
import Lightbox from "../../marketplace/Lightbox"; import Lightbox from '../../marketplace/Lightbox';
export default class Changelog extends PureComponent { export default class Changelog extends PureComponent {
constructor() { constructor() {
@ -13,14 +13,14 @@ export default class Changelog extends PureComponent {
showLightbox: false, showLightbox: false,
lightboxImg: null, lightboxImg: null,
}; };
this.offlineMode = localStorage.getItem("offlineMode") === "true"; this.offlineMode = localStorage.getItem('offlineMode') === 'true';
this.controller = new AbortController(); this.controller = new AbortController();
this.changelog = createRef(); this.changelog = createRef();
} }
async getUpdate() { async getUpdate() {
const data = await ( const data = await (
await fetch(variables.constants.BLOG_POST + "/index.json", { await fetch(variables.constants.BLOG_POST + '/index.json', {
signal: this.controller.signal, signal: this.controller.signal,
}) })
).json(); ).json();
@ -29,11 +29,11 @@ export default class Changelog extends PureComponent {
return; return;
} }
let date = new Date(data.date.split(" ")[0]); let date = new Date(data.date.split(' ')[0]);
date = date.toLocaleDateString(variables.languagecode.replace("_", "-"), { date = date.toLocaleDateString(variables.languagecode.replace('_', '-'), {
year: "numeric", year: 'numeric',
month: "long", month: 'long',
day: "numeric", day: 'numeric',
}); });
this.setState({ this.setState({
@ -42,17 +42,17 @@ export default class Changelog extends PureComponent {
image: data.featured_image || null, image: data.featured_image || null,
author: variables.language.getMessage( author: variables.language.getMessage(
variables.languagecode, variables.languagecode,
"modals.main.settings.sections.changelog.by", 'modals.main.settings.sections.changelog.by',
{ {
author: data.authors.join(", "), author: data.authors.join(', '),
} },
), ),
html: data.html, html: data.html,
}); });
// lightbox etc // lightbox etc
const images = this.changelog.current.getElementsByTagName("img"); const images = this.changelog.current.getElementsByTagName('img');
const links = this.changelog.current.getElementsByTagName("a"); const links = this.changelog.current.getElementsByTagName('a');
for (const img of images) { for (const img of images) {
img.draggable = false; img.draggable = false;
@ -66,8 +66,8 @@ export default class Changelog extends PureComponent {
// open in new tab // open in new tab
for (let link = 0; link < links.length; link++) { for (let link = 0; link < links.length; link++) {
links[link].target = "_blank"; links[link].target = '_blank';
links[link].rel = "noopener noreferrer"; links[link].rel = 'noopener noreferrer';
} }
} }
@ -85,8 +85,7 @@ export default class Changelog extends PureComponent {
} }
render() { render() {
const getMessage = (text) => const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
const errorMessage = (msg) => { const errorMessage = (msg) => {
return ( return (
@ -100,11 +99,9 @@ export default class Changelog extends PureComponent {
return errorMessage( return errorMessage(
<> <>
<MdOutlineWifiOff /> <MdOutlineWifiOff />
<h1>{getMessage("modals.main.marketplace.offline.title")}</h1> <h1>{getMessage('modals.main.marketplace.offline.title')}</h1>
<p className="description"> <p className="description">{getMessage('modals.main.marketplace.offline.description')}</p>
{getMessage("modals.main.marketplace.offline.description")} </>,
</p>
</>
); );
} }
@ -113,7 +110,7 @@ export default class Changelog extends PureComponent {
<div className="loaderHolder"> <div className="loaderHolder">
<div id="loader"></div> <div id="loader"></div>
<span className="subtitle">Just be a sec.</span> <span className="subtitle">Just be a sec.</span>
</div> </div>,
); );
} }
@ -131,10 +128,7 @@ export default class Changelog extends PureComponent {
className="updateImage" className="updateImage"
/> />
) : null} ) : null}
<div <div className="updateChangelog" dangerouslySetInnerHTML={{ __html: this.state.html }} />
className="updateChangelog"
dangerouslySetInnerHTML={{ __html: this.state.html }}
/>
<Modal <Modal
closeTimeoutMS={100} closeTimeoutMS={100}
onRequestClose={() => this.setState({ showLightbox: false })} onRequestClose={() => this.setState({ showLightbox: false })}

View File

@ -1,44 +1,39 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import Header from "../Header"; import Header from '../Header';
import Checkbox from "../Checkbox"; import Checkbox from '../Checkbox';
import Dropdown from "../Dropdown"; import Dropdown from '../Dropdown';
import SettingsItem from "../SettingsItem"; import SettingsItem from '../SettingsItem';
export default class DateSettings extends PureComponent { export default class DateSettings extends PureComponent {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
dateType: localStorage.getItem("dateType") || "long", dateType: localStorage.getItem('dateType') || 'long',
}; };
} }
render() { render() {
const getMessage = (text) => const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
let dateSettings; let dateSettings;
const longSettings = ( const longSettings = (
<> <>
<Dropdown <Dropdown label="Long Format" name="longFormat" category="date">
label="Long Format"
name="longFormat"
category="date"
>
<option value="DMY">DMY</option> <option value="DMY">DMY</option>
<option value="MDY">MDY</option> <option value="MDY">MDY</option>
<option value="YMD">YMD</option> <option value="YMD">YMD</option>
</Dropdown> </Dropdown>
<Checkbox <Checkbox
name="dayofweek" name="dayofweek"
text={getMessage("modals.main.settings.sections.date.day_of_week")} text={getMessage('modals.main.settings.sections.date.day_of_week')}
category="date" category="date"
/> />
<Checkbox <Checkbox
name="datenth" name="datenth"
text={getMessage("modals.main.settings.sections.date.datenth")} text={getMessage('modals.main.settings.sections.date.datenth')}
category="date" category="date"
/> />
</> </>
@ -47,7 +42,7 @@ export default class DateSettings extends PureComponent {
const shortSettings = ( const shortSettings = (
<> <>
<Dropdown <Dropdown
label={getMessage("modals.main.settings.sections.date.short_format")} label={getMessage('modals.main.settings.sections.date.short_format')}
name="dateFormat" name="dateFormat"
category="date" category="date"
> >
@ -57,37 +52,27 @@ export default class DateSettings extends PureComponent {
</Dropdown> </Dropdown>
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.date.short_separator.title')}
"modals.main.settings.sections.date.short_separator.title"
)}
name="shortFormat" name="shortFormat"
category="date" category="date"
> >
<option value="dash"> <option value="dash">
{getMessage( {getMessage('modals.main.settings.sections.date.short_separator.dash')}
"modals.main.settings.sections.date.short_separator.dash"
)}
</option> </option>
<option value="dots"> <option value="dots">
{getMessage( {getMessage('modals.main.settings.sections.date.short_separator.dots')}
"modals.main.settings.sections.date.short_separator.dots"
)}
</option> </option>
<option value="gaps"> <option value="gaps">
{getMessage( {getMessage('modals.main.settings.sections.date.short_separator.gaps')}
"modals.main.settings.sections.date.short_separator.gaps"
)}
</option> </option>
<option value="slashes"> <option value="slashes">
{getMessage( {getMessage('modals.main.settings.sections.date.short_separator.slashes')}
"modals.main.settings.sections.date.short_separator.slashes"
)}
</option> </option>
</Dropdown> </Dropdown>
</> </>
); );
if (this.state.dateType === "long") { if (this.state.dateType === 'long') {
dateSettings = longSettings; dateSettings = longSettings;
} else { } else {
dateSettings = shortSettings; dateSettings = shortSettings;
@ -96,7 +81,7 @@ export default class DateSettings extends PureComponent {
return ( return (
<> <>
<Header <Header
title={getMessage("modals.main.settings.sections.date.title")} title={getMessage('modals.main.settings.sections.date.title')}
setting="date" setting="date"
category="date" category="date"
element=".date" element=".date"
@ -105,28 +90,28 @@ export default class DateSettings extends PureComponent {
/> />
<SettingsItem title="Date Type"> <SettingsItem title="Date Type">
<Dropdown <Dropdown
label={getMessage("modals.main.settings.sections.time.type")} label={getMessage('modals.main.settings.sections.time.type')}
name="dateType" name="dateType"
onChange={(value) => this.setState({ dateType: value })} onChange={(value) => this.setState({ dateType: value })}
category="date" category="date"
> >
<option value="long"> <option value="long">
{getMessage("modals.main.settings.sections.date.type.long")} {getMessage('modals.main.settings.sections.date.type.long')}
</option> </option>
<option value="short"> <option value="short">
{getMessage("modals.main.settings.sections.date.type.short")} {getMessage('modals.main.settings.sections.date.type.short')}
</option> </option>
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
<SettingsItem title="Extra Options"> <SettingsItem title="Extra Options">
<Checkbox <Checkbox
name="weeknumber" name="weeknumber"
text={getMessage("modals.main.settings.sections.date.week_number")} text={getMessage('modals.main.settings.sections.date.week_number')}
category="date" category="date"
/> />
<Checkbox <Checkbox
name="datezero" name="datezero"
text={getMessage("modals.main.settings.sections.time.digital.zero")} text={getMessage('modals.main.settings.sections.time.digital.zero')}
category="date" category="date"
/> />
{dateSettings} {dateSettings}

View File

@ -1,25 +1,22 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { useState } from "react"; import { useState } from 'react';
import Checkbox from "../Checkbox"; import Checkbox from '../Checkbox';
import Slider from "../Slider"; import Slider from '../Slider';
import { TextField } from "@mui/material"; import { TextField } from '@mui/material';
import EventBus from "modules/helpers/eventbus"; import EventBus from 'modules/helpers/eventbus';
import { values } from "modules/helpers/settings/modals"; import { values } from 'modules/helpers/settings/modals';
export default function ExperimentalSettings() { export default function ExperimentalSettings() {
const getMessage = (text) => const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
const [eventType, setEventType] = useState(); const [eventType, setEventType] = useState();
const [eventName, setEventName] = useState(); const [eventName, setEventName] = useState();
return ( return (
<> <>
<h2>{getMessage("modals.main.settings.sections.experimental.title")}</h2> <h2>{getMessage('modals.main.settings.sections.experimental.title')}</h2>
<p>{getMessage("modals.main.settings.sections.experimental.warning")}</p> <p>{getMessage('modals.main.settings.sections.experimental.warning')}</p>
<h3> <h3>{getMessage('modals.main.settings.sections.experimental.developer')}</h3>
{getMessage("modals.main.settings.sections.experimental.developer")}
</h3>
<Checkbox name="debug" text="Debug hotkey (Ctrl + #)" element=".other" /> <Checkbox name="debug" text="Debug hotkey (Ctrl + #)" element=".other" />
<Slider <Slider
title="Debug timeout" title="Debug timeout"
@ -28,12 +25,12 @@ export default function ExperimentalSettings() {
max="5000" max="5000"
default="0" default="0"
step="100" step="100"
marks={values("experimental")} marks={values('experimental')}
element=".other" element=".other"
/> />
<p>Send Event</p> <p>Send Event</p>
<TextField <TextField
label={"Type"} label={'Type'}
value={eventType} value={eventType}
onChange={(e) => setEventType(e.target.value)} onChange={(e) => setEventType(e.target.value)}
spellCheck={false} spellCheck={false}
@ -41,7 +38,7 @@ export default function ExperimentalSettings() {
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
/> />
<TextField <TextField
label={"Name"} label={'Name'}
value={eventName} value={eventName}
onChange={(e) => setEventName(e.target.value)} onChange={(e) => setEventName(e.target.value)}
spellCheck={false} spellCheck={false}
@ -49,19 +46,12 @@ export default function ExperimentalSettings() {
InputLabelProps={{ shrink: true }} InputLabelProps={{ shrink: true }}
/> />
<br /> <br />
<button <button className="uploadbg" onClick={() => EventBus.dispatch(eventType, eventName)}>
className="uploadbg"
onClick={() => EventBus.dispatch(eventType, eventName)}
>
Send Send
</button> </button>
<br /> <br />
<br /> <br />
<button <button className="reset" style={{ marginLeft: '0px' }} onClick={() => localStorage.clear()}>
className="reset"
style={{ marginLeft: "0px" }}
onClick={() => localStorage.clear()}
>
Clear LocalStorage Clear LocalStorage
</button> </button>
</> </>

View File

@ -11,7 +11,7 @@ export default class GreetingSettings extends PureComponent {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
birthday: new Date(localStorage.getItem('birthday')) || new Date() birthday: new Date(localStorage.getItem('birthday')) || new Date(),
}; };
} }
@ -19,26 +19,64 @@ export default class GreetingSettings extends PureComponent {
localStorage.setItem('birthday', e.target.value || new Date()); localStorage.setItem('birthday', e.target.value || new Date());
this.setState({ this.setState({
birthday: e.target.value ? new Date(e.target.value) : new Date() birthday: e.target.value ? new Date(e.target.value) : new Date(),
}); });
} };
render() { render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text); const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return ( return (
<> <>
<Header title={getMessage('modals.main.settings.sections.greeting.title')} setting='greeting' category='greeting' element='.greeting' zoomSetting='zoomGreeting' switch={true}/> <Header
<SettingsItem title="Additional Settings" subtitle={getMessage('modals.main.settings.enabled')}> title={getMessage('modals.main.settings.sections.greeting.title')}
<Checkbox name='events' text={getMessage('modals.main.settings.sections.greeting.events')} category='greeting'/> setting="greeting"
<Checkbox name='defaultGreetingMessage' text={getMessage('modals.main.settings.sections.greeting.default')} category='greeting'/> category="greeting"
<Text title={getMessage('modals.main.settings.sections.greeting.name')} name='greetingName' category='greeting'/> element=".greeting"
zoomSetting="zoomGreeting"
switch={true}
/>
<SettingsItem
title="Additional Settings"
subtitle={getMessage('modals.main.settings.enabled')}
>
<Checkbox
name="events"
text={getMessage('modals.main.settings.sections.greeting.events')}
category="greeting"
/>
<Checkbox
name="defaultGreetingMessage"
text={getMessage('modals.main.settings.sections.greeting.default')}
category="greeting"
/>
<Text
title={getMessage('modals.main.settings.sections.greeting.name')}
name="greetingName"
category="greeting"
/>
</SettingsItem> </SettingsItem>
<SettingsItem title={getMessage('modals.main.settings.sections.greeting.birthday')} subtitle={getMessage('modals.main.settings.enabled')}> <SettingsItem
<Switch name='birthdayenabled' text={getMessage('modals.main.settings.enabled')} category='greeting'/> title={getMessage('modals.main.settings.sections.greeting.birthday')}
<Checkbox name='birthdayage' text={getMessage('modals.main.settings.sections.greeting.birthday_age')} category='greeting'/> subtitle={getMessage('modals.main.settings.enabled')}
<p>{getMessage('modals.main.settings.sections.greeting.birthday_date')}</p> >
<input type='date' onChange={this.changeDate} value={this.state.birthday.toISOString().substr(0, 10)} required/> <Switch
name="birthdayenabled"
text={getMessage('modals.main.settings.enabled')}
category="greeting"
/>
<Checkbox
name="birthdayage"
text={getMessage('modals.main.settings.sections.greeting.birthday_age')}
category="greeting"
/>
<p>{getMessage('modals.main.settings.sections.greeting.birthday_date')}</p>
<input
type="date"
onChange={this.changeDate}
value={this.state.birthday.toISOString().substr(0, 10)}
required
/>
</SettingsItem> </SettingsItem>
{/*<h3>{getMessage('modals.main.settings.sections.greeting.birthday')}</h3> {/*<h3>{getMessage('modals.main.settings.sections.greeting.birthday')}</h3>
<Switch name='birthdayenabled' text={getMessage('modals.main.settings.enabled')} category='greeting'/> <Switch name='birthdayenabled' text={getMessage('modals.main.settings.enabled')} category='greeting'/>

View File

@ -11,7 +11,7 @@ export default class KeybindSettings extends PureComponent {
super(); super();
this.state = { this.state = {
keybinds: JSON.parse(localStorage.getItem('keybinds')) || {}, keybinds: JSON.parse(localStorage.getItem('keybinds')) || {},
cancelled: false cancelled: false,
}; };
} }
@ -25,7 +25,7 @@ export default class KeybindSettings extends PureComponent {
currentKeybinds[type] = this.getMessage('modals.main.settings.sections.keybinds.recording'); currentKeybinds[type] = this.getMessage('modals.main.settings.sections.keybinds.recording');
this.setState({ this.setState({
keybinds: currentKeybinds, keybinds: currentKeybinds,
cancelled: false cancelled: false,
}); });
this.forceUpdate(); this.forceUpdate();
@ -42,7 +42,7 @@ export default class KeybindSettings extends PureComponent {
keys = `${keys}+${event.key}`; keys = `${keys}+${event.key}`;
} }
previouskey = event.key previouskey = event.key;
}); });
this.keyup = document.addEventListener('keyup', () => { this.keyup = document.addEventListener('keyup', () => {
@ -55,7 +55,7 @@ export default class KeybindSettings extends PureComponent {
keybinds[type] = keys.split('+').slice(0, 4).join('+'); keybinds[type] = keys.split('+').slice(0, 4).join('+');
localStorage.setItem('keybinds', JSON.stringify(keybinds)); localStorage.setItem('keybinds', JSON.stringify(keybinds));
this.setState({ this.setState({
keybinds: JSON.parse(localStorage.getItem('keybinds')) || {} keybinds: JSON.parse(localStorage.getItem('keybinds')) || {},
}); });
}); });
@ -73,7 +73,7 @@ export default class KeybindSettings extends PureComponent {
this.setState({ this.setState({
keybinds: currentKeybinds, keybinds: currentKeybinds,
cancelled: true cancelled: true,
}); });
this.forceUpdate(); this.forceUpdate();
} }
@ -85,7 +85,7 @@ export default class KeybindSettings extends PureComponent {
this.setState({ this.setState({
keybinds: JSON.parse(localStorage.getItem('keybinds')) || {}, keybinds: JSON.parse(localStorage.getItem('keybinds')) || {},
cancelled: true cancelled: true,
}); });
this.showReminder(); this.showReminder();
@ -110,35 +110,140 @@ export default class KeybindSettings extends PureComponent {
render() { render() {
return ( return (
<> <>
<Header title={this.getMessage('modals.main.settings.sections.keybinds.title')} setting='keybindsEnabled' element='.other' /> <Header
<table className='keybind-table'> title={this.getMessage('modals.main.settings.sections.keybinds.title')}
setting="keybindsEnabled"
element=".other"
/>
<table className="keybind-table">
<tbody> <tbody>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.favourite')} state={this.state.keybinds} setting='favouriteBackground' action={(type, e) => this.action(type, e)}/></th> <th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.maximise')} state={this.state.keybinds} setting='maximiseBackground' action={(type, e) => this.action(type, e)}/></th> <KeybindInput
name={this.getMessage(
'modals.main.settings.sections.keybinds.background.favourite',
)}
state={this.state.keybinds}
setting="favouriteBackground"
action={(type, e) => this.action(type, e)}
/>
</th>
<th>
<KeybindInput
name={this.getMessage(
'modals.main.settings.sections.keybinds.background.maximise',
)}
state={this.state.keybinds}
setting="maximiseBackground"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.download')} state={this.state.keybinds} setting='downloadBackground' action={(type, e) => this.action(type, e)}/></th> <th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.show_info')} state={this.state.keybinds} setting='showBackgroundInformation' action={(type, e) => this.action(type, e)}/></th> <KeybindInput
name={this.getMessage(
'modals.main.settings.sections.keybinds.background.download',
)}
state={this.state.keybinds}
setting="downloadBackground"
action={(type, e) => this.action(type, e)}
/>
</th>
<th>
<KeybindInput
name={this.getMessage(
'modals.main.settings.sections.keybinds.background.show_info',
)}
state={this.state.keybinds}
setting="showBackgroundInformation"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.background.show_info')} state={this.state.keybinds} setting='showBackgroundInformation' action={(type, e) => this.action(type, e)}/></th> <th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quote.favourite')} state={this.state.keybinds} setting='favouriteQuote' action={(type, e) => this.action(type, e)}/></th> <KeybindInput
name={this.getMessage(
'modals.main.settings.sections.keybinds.background.show_info',
)}
state={this.state.keybinds}
setting="showBackgroundInformation"
action={(type, e) => this.action(type, e)}
/>
</th>
<th>
<KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.quote.favourite')}
state={this.state.keybinds}
setting="favouriteQuote"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quote.copy')} state={this.state.keybinds} setting='copyQuote' action={(type, e) => this.action(type, e)}/></th> <th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quote.tweet')} state={this.state.keybinds} setting='tweetQuote' action={(type, e) => this.action(type, e)}/></th> <KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.quote.copy')}
state={this.state.keybinds}
setting="copyQuote"
action={(type, e) => this.action(type, e)}
/>
</th>
<th>
<KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.quote.tweet')}
state={this.state.keybinds}
setting="tweetQuote"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.notes.pin')} state={this.state.keybinds} setting='pinNotes' action={(type, e) => this.action(type, e)}/></th> <th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.notes.copy')} state={this.state.keybinds} setting='copyNotes' action={(type, e) => this.action(type, e)}/></th> <KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.notes.pin')}
state={this.state.keybinds}
setting="pinNotes"
action={(type, e) => this.action(type, e)}
/>
</th>
<th>
<KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.notes.copy')}
state={this.state.keybinds}
setting="copyNotes"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.search')} state={this.state.keybinds} setting='focusSearch' action={(type, e) => this.action(type, e)}/></th> <th>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.quicklinks')} state={this.state.keybinds} setting='toggleQuicklinks' action={(type, e) => this.action(type, e)}/></th> <KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.search')}
state={this.state.keybinds}
setting="focusSearch"
action={(type, e) => this.action(type, e)}
/>
</th>
<th>
<KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.quicklinks')}
state={this.state.keybinds}
setting="toggleQuicklinks"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
<tr> <tr>
<th><KeybindInput name={this.getMessage('modals.main.settings.sections.keybinds.modal')} state={this.state.keybinds} setting='toggleModal' action={(type, e) => this.action(type, e)}/></th> <th>
<KeybindInput
name={this.getMessage('modals.main.settings.sections.keybinds.modal')}
state={this.state.keybinds}
setting="toggleModal"
action={(type, e) => this.action(type, e)}
/>
</th>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -96,8 +96,9 @@ export default class Message extends PureComponent {
<th> <th>
{this.state.messages.length > 1 ? ( {this.state.messages.length > 1 ? (
<button <button
className='deleteButton' className="deleteButton"
onClick={() => this.modifyMessage('remove', index)}> onClick={() => this.modifyMessage('remove', index)}
>
<MdCancel /> <MdCancel />
</button> </button>
) : null} ) : null}

View File

@ -12,12 +12,38 @@ export default function QuickLinks() {
return ( return (
<> <>
<Header title={getMessage('modals.main.settings.sections.quicklinks.title')} setting='quicklinksenabled' category='quicklinks' element='.quicklinks-container' zoomSetting='zoomQuicklinks' switch={true}/> <Header
title={getMessage('modals.main.settings.sections.quicklinks.title')}
setting="quicklinksenabled"
category="quicklinks"
element=".quicklinks-container"
zoomSetting="zoomQuicklinks"
switch={true}
/>
<SettingsItem title="Extra Options" subtitle="subtitle"> <SettingsItem title="Extra Options" subtitle="subtitle">
<Checkbox name='quicklinksText' text={getMessage('modals.main.settings.sections.quicklinks.text_only')} category='quicklinks' onChange={(value) => setTextOnly(value)}/> <Checkbox
<Checkbox name='quicklinksddgProxy' text={getMessage('modals.main.settings.sections.background.ddg_image_proxy')} category='quicklinks' disabled={textOnly}/> name="quicklinksText"
<Checkbox name='quicklinksnewtab' text={getMessage('modals.main.settings.sections.quicklinks.open_new')} category='quicklinks'/> text={getMessage('modals.main.settings.sections.quicklinks.text_only')}
<Checkbox name='quicklinkstooltip' text={getMessage('modals.main.settings.sections.quicklinks.tooltip')} category='quicklinks' disabled={textOnly}/> category="quicklinks"
onChange={(value) => setTextOnly(value)}
/>
<Checkbox
name="quicklinksddgProxy"
text={getMessage('modals.main.settings.sections.background.ddg_image_proxy')}
category="quicklinks"
disabled={textOnly}
/>
<Checkbox
name="quicklinksnewtab"
text={getMessage('modals.main.settings.sections.quicklinks.open_new')}
category="quicklinks"
/>
<Checkbox
name="quicklinkstooltip"
text={getMessage('modals.main.settings.sections.quicklinks.tooltip')}
category="quicklinks"
disabled={textOnly}
/>
</SettingsItem> </SettingsItem>
</> </>
); );

View File

@ -6,7 +6,7 @@ export default class ReminderSettings extends PureComponent {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
colour: localStorage.getItem('reminderColour') || '#ffa500' colour: localStorage.getItem('reminderColour') || '#ffa500',
}; };
} }
@ -20,9 +20,24 @@ export default class ReminderSettings extends PureComponent {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text); const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return ( return (
<> <>
<Header title='Reminder' setting='reminder' category='reminder' element='.reminder' zoomSetting='zoomReminder' switch={true}/> <Header
<input type='color' name='colour' className='colour' onChange={(event) => this.updateColour(event)} value={this.state.colour}></input> title="Reminder"
<label htmlFor={'colour'} className='customBackgroundHex'>{this.state.colour}</label> setting="reminder"
category="reminder"
element=".reminder"
zoomSetting="zoomReminder"
switch={true}
/>
<input
type="color"
name="colour"
className="colour"
onChange={(event) => this.updateColour(event)}
value={this.state.colour}
></input>
<label htmlFor={'colour'} className="customBackgroundHex">
{this.state.colour}
</label>
</> </>
); );
} }

View File

@ -22,14 +22,14 @@ export default class SearchSettings extends PureComponent {
this.state = { this.state = {
customEnabled: false, customEnabled: false,
customDisplay: 'none', customDisplay: 'none',
customValue: localStorage.getItem('customSearchEngine') || '' customValue: localStorage.getItem('customSearchEngine') || '',
}; };
} }
resetSearch() { resetSearch() {
localStorage.removeItem('customSearchEngine'); localStorage.removeItem('customSearchEngine');
this.setState({ this.setState({
customValue: '' customValue: '',
}); });
toast(this.getMessage('toasts.reset')); toast(this.getMessage('toasts.reset'));
@ -39,7 +39,7 @@ export default class SearchSettings extends PureComponent {
if (localStorage.getItem('searchEngine') === 'custom') { if (localStorage.getItem('searchEngine') === 'custom') {
this.setState({ this.setState({
customDisplay: 'block', customDisplay: 'block',
customEnabled: true customEnabled: true,
}); });
} else { } else {
localStorage.removeItem('customSearchEngine'); localStorage.removeItem('customSearchEngine');
@ -58,12 +58,12 @@ export default class SearchSettings extends PureComponent {
if (input === 'custom') { if (input === 'custom') {
this.setState({ this.setState({
customDisplay: 'block', customDisplay: 'block',
customEnabled: true customEnabled: true,
}); });
} else { } else {
this.setState({ this.setState({
customDisplay: 'none', customDisplay: 'none',
customEnabled: false customEnabled: false,
}); });
localStorage.setItem('searchEngine', input); localStorage.setItem('searchEngine', input);
} }
@ -74,30 +74,78 @@ export default class SearchSettings extends PureComponent {
render() { render() {
return ( return (
<> <>
<Header title={this.getMessage('modals.main.settings.sections.search.title')} setting='searchBar' category='widgets' switch={true}/> <Header
title={this.getMessage('modals.main.settings.sections.search.title')}
setting="searchBar"
category="widgets"
switch={true}
/>
<SettingsItem title="Extra Options" subtitle="eeeee"> <SettingsItem title="Extra Options" subtitle="eeeee">
{/* not supported on firefox */} {/* not supported on firefox */}
{(navigator.userAgent.includes('Chrome') && typeof InstallTrigger === 'undefined') ? {navigator.userAgent.includes('Chrome') && typeof InstallTrigger === 'undefined' ? (
<Checkbox name='voiceSearch' text={this.getMessage('modals.main.settings.sections.search.voice_search')} category='search'/> <Checkbox
: null} name="voiceSearch"
<Checkbox name='searchDropdown' text={this.getMessage('modals.main.settings.sections.search.dropdown')} category='search' element='.other'/> text={this.getMessage('modals.main.settings.sections.search.voice_search')}
<Checkbox name='searchFocus' text={this.getMessage('modals.main.settings.sections.search.focus')} category='search' element='.other'/> category="search"
<ul style={{ display: this.state.customDisplay }}> />
<p style={{ marginTop: '0px' }}><span className='link' onClick={() => this.resetSearch()}>{this.getMessage('modals.main.settings.buttons.reset')}</span></p> ) : null}
<TextField label={this.getMessage('modals.main.settings.sections.search.custom')} value={this.state.customValue} onInput={(e) => this.setState({ customValue: e.target.value })} varient='outlined' InputLabelProps={{ shrink: true }} /> <Checkbox
</ul> name="searchDropdown"
<Checkbox name='autocomplete' text={this.getMessage('modals.main.settings.sections.search.autocomplete')} category='search' /> text={this.getMessage('modals.main.settings.sections.search.dropdown')}
category="search"
element=".other"
/>
<Checkbox
name="searchFocus"
text={this.getMessage('modals.main.settings.sections.search.focus')}
category="search"
element=".other"
/>
<ul style={{ display: this.state.customDisplay }}>
<p style={{ marginTop: '0px' }}>
<span className="link" onClick={() => this.resetSearch()}>
{this.getMessage('modals.main.settings.buttons.reset')}
</span>
</p>
<TextField
label={this.getMessage('modals.main.settings.sections.search.custom')}
value={this.state.customValue}
onInput={(e) => this.setState({ customValue: e.target.value })}
varient="outlined"
InputLabelProps={{ shrink: true }}
/>
</ul>
<Checkbox
name="autocomplete"
text={this.getMessage('modals.main.settings.sections.search.autocomplete')}
category="search"
/>
</SettingsItem> </SettingsItem>
<SettingsItem title={this.getMessage('modals.main.settings.sections.search.search_engine')} subtitle="cheese is gucci tbf"> <SettingsItem
<Dropdown label={this.getMessage('modals.main.settings.sections.search.search_engine')} name='searchEngine' onChange={(value) => this.setSearchEngine(value)} manual={true}> title={this.getMessage('modals.main.settings.sections.search.search_engine')}
{searchEngines.map((engine) => ( subtitle="cheese is gucci tbf"
<MenuItem key={engine.name} value={engine.settingsName}>{engine.name}</MenuItem> >
))} <Dropdown
<MenuItem value='custom'>{this.getMessage('modals.main.settings.sections.search.custom').split(' ')[0]}</MenuItem> label={this.getMessage('modals.main.settings.sections.search.search_engine')}
</Dropdown> name="searchEngine"
onChange={(value) => this.setSearchEngine(value)}
manual={true}
>
{searchEngines.map((engine) => (
<MenuItem key={engine.name} value={engine.settingsName}>
{engine.name}
</MenuItem>
))}
<MenuItem value="custom">
{this.getMessage('modals.main.settings.sections.search.custom').split(' ')[0]}
</MenuItem>
</Dropdown>
</SettingsItem> </SettingsItem>
<SettingsItem title={this.getMessage('modals.main.settings.sections.search.autocomplete_provider')} subtitle="cheese"> <SettingsItem
<Radio options={autocompleteProviders} name='autocompleteProvider' category='search'/> title={this.getMessage('modals.main.settings.sections.search.autocomplete_provider')}
subtitle="cheese"
>
<Radio options={autocompleteProviders} name="autocompleteProvider" category="search" />
</SettingsItem> </SettingsItem>
</> </>
); );

View File

@ -8,13 +8,12 @@ import Checkbox from '../Checkbox';
import { TextField } from '@mui/material'; import { TextField } from '@mui/material';
import SettingsItem from '../SettingsItem'; import SettingsItem from '../SettingsItem';
export default class TimeSettings extends PureComponent { export default class TimeSettings extends PureComponent {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
location: localStorage.getItem('location') || '', location: localStorage.getItem('location') || '',
windSpeed: (localStorage.getItem('windspeed') !== 'true') windSpeed: localStorage.getItem('windspeed') !== 'true',
}; };
} }
@ -29,26 +28,34 @@ export default class TimeSettings extends PureComponent {
changeLocation(e) { changeLocation(e) {
this.setState({ this.setState({
location: e.target.value location: e.target.value,
}); });
this.showReminder(); this.showReminder();
} }
getAuto() { getAuto() {
navigator.geolocation.getCurrentPosition(async (position) => { navigator.geolocation.getCurrentPosition(
const data = await (await fetch(`${variables.constants.PROXY_URL}/weather/autolocation?lat=${position.coords.latitude}&lon=${position.coords.longitude}`)).json(); async (position) => {
this.setState({ const data = await (
location: data[0].name await fetch(
}); `${variables.constants.PROXY_URL}/weather/autolocation?lat=${position.coords.latitude}&lon=${position.coords.longitude}`,
)
).json();
this.setState({
location: data[0].name,
});
this.showReminder(); this.showReminder();
}, (error) => { },
// firefox requires this 2nd function (error) => {
console.log(error); // firefox requires this 2nd function
}, { console.log(error);
enableHighAccuracy: true },
}); {
enableHighAccuracy: true,
},
);
} }
render() { render() {
@ -57,62 +64,151 @@ export default class TimeSettings extends PureComponent {
const tempFormat = [ const tempFormat = [
{ {
name: getMessage('modals.main.settings.sections.weather.temp_format.celsius') + ' (°C)', name: getMessage('modals.main.settings.sections.weather.temp_format.celsius') + ' (°C)',
value: 'celsius' value: 'celsius',
}, },
{ {
name: getMessage('modals.main.settings.sections.weather.temp_format.fahrenheit') + ' (°F)', name: getMessage('modals.main.settings.sections.weather.temp_format.fahrenheit') + ' (°F)',
value: 'fahrenheit' value: 'fahrenheit',
}, },
{ {
name: getMessage('modals.main.settings.sections.weather.temp_format.kelvin') + ' (K)', name: getMessage('modals.main.settings.sections.weather.temp_format.kelvin') + ' (K)',
value: 'kelvin' value: 'kelvin',
} },
]; ];
return ( return (
<> <>
<Header title={getMessage('modals.main.settings.sections.weather.title')} setting='weatherEnabled' category='widgets' zoomSetting='zoomWeather' zoomCategory='weather' switch={true}/> <Header
title={getMessage('modals.main.settings.sections.weather.title')}
setting="weatherEnabled"
category="widgets"
zoomSetting="zoomWeather"
zoomCategory="weather"
switch={true}
/>
<SettingsItem title="Widget Type"> <SettingsItem title="Widget Type">
<Dropdown label="Type" name="weatherType"> <Dropdown label="Type" name="weatherType">
<option value='1'>Basic</option> <option value="1">Basic</option>
<option value='2'>Standard</option> <option value="2">Standard</option>
<option value='3'>Expanded</option> <option value="3">Expanded</option>
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
<SettingsItem title={getMessage('modals.main.settings.sections.weather.location')}> <SettingsItem title={getMessage('modals.main.settings.sections.weather.location')}>
<TextField label={getMessage('modals.main.settings.sections.weather.location')} value={this.state.location} onChange={(e) => this.changeLocation(e)} placeholder='London' varient='outlined' InputLabelProps={{ shrink: true }} /> <TextField
<span className='link' onClick={() => this.getAuto()}>{getMessage('modals.main.settings.sections.weather.auto')}</span> label={getMessage('modals.main.settings.sections.weather.location')}
value={this.state.location}
onChange={(e) => this.changeLocation(e)}
placeholder="London"
varient="outlined"
InputLabelProps={{ shrink: true }}
/>
<span className="link" onClick={() => this.getAuto()}>
{getMessage('modals.main.settings.sections.weather.auto')}
</span>
</SettingsItem> </SettingsItem>
<SettingsItem title={getMessage('modals.main.settings.sections.weather.temp_format.title')}> <SettingsItem title={getMessage('modals.main.settings.sections.weather.temp_format.title')}>
<Radio name='tempformat' options={tempFormat} category='weather'/> <Radio name="tempformat" options={tempFormat} category="weather" />
</SettingsItem> </SettingsItem>
{ localStorage.getItem('weatherType') > 1 && {localStorage.getItem('weatherType') > 1 && (
<SettingsItem title="Active bit" subtitle="idk a better word for it sorry"> <SettingsItem title="Active bit" subtitle="idk a better word for it sorry">
<Dropdown label="Type" name="weatherActiveBit" category='weather'> <Dropdown label="Type" name="weatherActiveBit" category="weather">
<option value='weatherdescription'>{getMessage('modals.main.settings.sections.weather.extra_info.show_description')} </option> <option value="weatherdescription">
<option value='cloudiness'>{getMessage('modals.main.settings.sections.weather.extra_info.cloudiness')}</option> {getMessage('modals.main.settings.sections.weather.extra_info.show_description')}{' '}
<option value='humidity'>{getMessage('modals.main.settings.sections.weather.extra_info.humidity')}</option> </option>
<option value='visibility'>{getMessage('modals.main.settings.sections.weather.extra_info.visibility')}</option> <option value="cloudiness">
<option value='windspeed' onChange={() => this.setState({ windSpeed: (localStorage.getItem('windspeed') !== 'true') })}>{getMessage('modals.main.settings.sections.weather.extra_info.wind_speed')}</option> {getMessage('modals.main.settings.sections.weather.extra_info.cloudiness')}
<option value='windDirection' disabled={this.state.windSpeed}>{getMessage('modals.main.settings.sections.weather.extra_info.wind_direction')}</option> </option>
<option value='mintemp'>{getMessage('modals.main.settings.sections.weather.extra_info.min_temp')}</option> <option value="humidity">
<option value='maxtemp'>{getMessage('modals.main.settings.sections.weather.extra_info.max_temp')}</option> {getMessage('modals.main.settings.sections.weather.extra_info.humidity')}
<option value='feelsliketemp'>Feels like temperature</option> </option>
<option value='atmosphericpressure'>{getMessage('modals.main.settings.sections.weather.extra_info.atmospheric_pressure')}</option> <option value="visibility">
</Dropdown> {getMessage('modals.main.settings.sections.weather.extra_info.visibility')}
</option>
<option
value="windspeed"
onChange={() =>
this.setState({
windSpeed: localStorage.getItem('windspeed') !== 'true',
})
}
>
{getMessage('modals.main.settings.sections.weather.extra_info.wind_speed')}
</option>
<option value="windDirection" disabled={this.state.windSpeed}>
{getMessage('modals.main.settings.sections.weather.extra_info.wind_direction')}
</option>
<option value="mintemp">
{getMessage('modals.main.settings.sections.weather.extra_info.min_temp')}
</option>
<option value="maxtemp">
{getMessage('modals.main.settings.sections.weather.extra_info.max_temp')}
</option>
<option value="feelsliketemp">Feels like temperature</option>
<option value="atmosphericpressure">
{getMessage(
'modals.main.settings.sections.weather.extra_info.atmospheric_pressure',
)}
</option>
</Dropdown>
</SettingsItem> </SettingsItem>
} )}
<Checkbox name='showlocation' text={getMessage('modals.main.settings.sections.weather.extra_info.show_location')} category='weather'/> <Checkbox
<Checkbox name='weatherdescription' text={getMessage('modals.main.settings.sections.weather.extra_info.show_description')} category='weather'/> name="showlocation"
<Checkbox name='cloudiness' text={getMessage('modals.main.settings.sections.weather.extra_info.cloudiness')} category='weather'/> text={getMessage('modals.main.settings.sections.weather.extra_info.show_location')}
<Checkbox name='humidity' text={getMessage('modals.main.settings.sections.weather.extra_info.humidity')} category='weather'/> category="weather"
<Checkbox name='visibility' text={getMessage('modals.main.settings.sections.weather.extra_info.visibility')} category='weather'/> />
<Checkbox name='windspeed' text={getMessage('modals.main.settings.sections.weather.extra_info.wind_speed')} category='weather' onChange={() => this.setState({ windSpeed: (localStorage.getItem('windspeed') !== 'true') })}/> <Checkbox
<Checkbox name='windDirection' text={getMessage('modals.main.settings.sections.weather.extra_info.wind_direction')} category='weather' disabled={this.state.windSpeed}/> name="weatherdescription"
<Checkbox name='mintemp' text={getMessage('modals.main.settings.sections.weather.extra_info.min_temp')} category='weather'/> text={getMessage('modals.main.settings.sections.weather.extra_info.show_description')}
<Checkbox name='maxtemp' text={getMessage('modals.main.settings.sections.weather.extra_info.max_temp')} category='weather'/> category="weather"
<Checkbox name='feelsliketemp' text={'Feels like temperature'} category='weather'/> />
<Checkbox name='atmosphericpressure' text={getMessage('modals.main.settings.sections.weather.extra_info.atmospheric_pressure')} category='weather'/> <Checkbox
name="cloudiness"
text={getMessage('modals.main.settings.sections.weather.extra_info.cloudiness')}
category="weather"
/>
<Checkbox
name="humidity"
text={getMessage('modals.main.settings.sections.weather.extra_info.humidity')}
category="weather"
/>
<Checkbox
name="visibility"
text={getMessage('modals.main.settings.sections.weather.extra_info.visibility')}
category="weather"
/>
<Checkbox
name="windspeed"
text={getMessage('modals.main.settings.sections.weather.extra_info.wind_speed')}
category="weather"
onChange={() =>
this.setState({
windSpeed: localStorage.getItem('windspeed') !== 'true',
})
}
/>
<Checkbox
name="windDirection"
text={getMessage('modals.main.settings.sections.weather.extra_info.wind_direction')}
category="weather"
disabled={this.state.windSpeed}
/>
<Checkbox
name="mintemp"
text={getMessage('modals.main.settings.sections.weather.extra_info.min_temp')}
category="weather"
/>
<Checkbox
name="maxtemp"
text={getMessage('modals.main.settings.sections.weather.extra_info.max_temp')}
category="weather"
/>
<Checkbox name="feelsliketemp" text={'Feels like temperature'} category="weather" />
<Checkbox
name="atmosphericpressure"
text={getMessage('modals.main.settings.sections.weather.extra_info.atmospheric_pressure')}
category="weather"
/>
</> </>
); );
} }

View File

@ -1,38 +1,37 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { MenuItem } from "@mui/material"; import { MenuItem } from '@mui/material';
import Header from "../../Header"; import Header from '../../Header';
import Checkbox from "../../Checkbox"; import Checkbox from '../../Checkbox';
import Dropdown from "../../Dropdown"; import Dropdown from '../../Dropdown';
import Slider from "../../Slider"; import Slider from '../../Slider';
import Radio from "../../Radio"; import Radio from '../../Radio';
import SettingsItem from "../../SettingsItem"; import SettingsItem from '../../SettingsItem';
import ColourSettings from "./Colour"; import ColourSettings from './Colour';
import CustomSettings from "./Custom"; import CustomSettings from './Custom';
import { values } from "modules/helpers/settings/modals"; import { values } from 'modules/helpers/settings/modals';
export default class BackgroundSettings extends PureComponent { export default class BackgroundSettings extends PureComponent {
getMessage = (text) => getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
constructor() { constructor() {
super(); super();
this.state = { this.state = {
backgroundType: localStorage.getItem("backgroundType") || "api", backgroundType: localStorage.getItem('backgroundType') || 'api',
backgroundFilter: localStorage.getItem("backgroundFilter") || "none", backgroundFilter: localStorage.getItem('backgroundFilter') || 'none',
backgroundCategories: [this.getMessage("modals.main.loading")], backgroundCategories: [this.getMessage('modals.main.loading')],
backgroundAPI: localStorage.getItem("backgroundAPI") || "mue", backgroundAPI: localStorage.getItem('backgroundAPI') || 'mue',
marketplaceEnabled: localStorage.getItem("photo_packs"), marketplaceEnabled: localStorage.getItem('photo_packs'),
}; };
this.controller = new AbortController(); this.controller = new AbortController();
} }
async getBackgroundCategories() { async getBackgroundCategories() {
const data = await ( const data = await (
await fetch(variables.constants.API_URL + "/images/categories", { await fetch(variables.constants.API_URL + '/images/categories', {
signal: this.controller.signal, signal: this.controller.signal,
}) })
).json(); ).json();
@ -47,12 +46,9 @@ export default class BackgroundSettings extends PureComponent {
} }
componentDidMount() { componentDidMount() {
if ( if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') {
navigator.onLine === false ||
localStorage.getItem("offlineMode") === "true"
) {
return this.setState({ return this.setState({
backgroundCategories: [this.getMessage("modals.update.offline.title")], backgroundCategories: [this.getMessage('modals.update.offline.title')],
}); });
} }
@ -71,53 +67,41 @@ export default class BackgroundSettings extends PureComponent {
const apiOptions = [ const apiOptions = [
{ {
name: "Mue", name: 'Mue',
value: "mue", value: 'mue',
}, },
{ {
name: "Unsplash", name: 'Unsplash',
value: "unsplash", value: 'unsplash',
}, },
{ {
name: "Pexels", name: 'Pexels',
value: "pexels", value: 'pexels',
}, },
]; ];
const interval = ( const interval = (
<SettingsItem> <SettingsItem>
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.background.interval.title')}
"modals.main.settings.sections.background.interval.title"
)}
name="backgroundchange" name="backgroundchange"
> >
<option value="refresh">{getMessage("tabname")}</option> <option value="refresh">{getMessage('tabname')}</option>
<option value="60000"> <option value="60000">
{getMessage( {getMessage('modals.main.settings.sections.background.interval.minute')}
"modals.main.settings.sections.background.interval.minute"
)}
</option> </option>
<option value="1800000"> <option value="1800000">
{getMessage( {getMessage('modals.main.settings.sections.background.interval.half_hour')}
"modals.main.settings.sections.background.interval.half_hour"
)}
</option> </option>
<option value="3600000"> <option value="3600000">
{getMessage( {getMessage('modals.main.settings.sections.background.interval.hour')}
"modals.main.settings.sections.background.interval.hour"
)}
</option> </option>
<option value="86400000"> <option value="86400000">
{getMessage( {getMessage('modals.main.settings.sections.background.interval.day')}
"modals.main.settings.sections.background.interval.day"
)}
</option> </option>
<option value="604800000">{getMessage("widgets.date.week")}</option> <option value="604800000">{getMessage('widgets.date.week')}</option>
<option value="2628000000"> <option value="2628000000">
{getMessage( {getMessage('modals.main.settings.sections.background.interval.month')}
"modals.main.settings.sections.background.interval.month"
)}
</option> </option>
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
@ -127,37 +111,30 @@ export default class BackgroundSettings extends PureComponent {
<> <>
<SettingsItem> <SettingsItem>
<Radio <Radio
title={getMessage( title={getMessage('modals.main.settings.sections.background.source.api')}
"modals.main.settings.sections.background.source.api"
)}
options={apiOptions} options={apiOptions}
name="backgroundAPI" name="backgroundAPI"
category="background" category="background"
element="#backgroundImage" element="#backgroundImage"
onChange={(e) => this.setState({ backgroundAPI: e })} onChange={(e) => this.setState({ backgroundAPI: e })}
/> />
{this.state.backgroundCategories[0] === {this.state.backgroundCategories[0] === getMessage('modals.main.loading') ? (
getMessage("modals.main.loading") ? (
<> <>
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.background.category')}
"modals.main.settings.sections.background.category"
)}
name="apiCategory" name="apiCategory"
> >
<MenuItem value="loading" key="loading"> <MenuItem value="loading" key="loading">
{getMessage("modals.main.loading")} {getMessage('modals.main.loading')}
</MenuItem> </MenuItem>
<MenuItem value="loading" key="loading"> <MenuItem value="loading" key="loading">
{getMessage("modals.main.loading")} {getMessage('modals.main.loading')}
</MenuItem> </MenuItem>
</Dropdown> </Dropdown>
</> </>
) : ( ) : (
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.background.category')}
"modals.main.settings.sections.background.category"
)}
name="apiCategory" name="apiCategory"
> >
{this.state.backgroundCategories.map((category) => ( {this.state.backgroundCategories.map((category) => (
@ -168,31 +145,21 @@ export default class BackgroundSettings extends PureComponent {
</Dropdown> </Dropdown>
)} )}
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.background.source.quality.title')}
"modals.main.settings.sections.background.source.quality.title"
)}
name="apiQuality" name="apiQuality"
element=".other" element=".other"
> >
<option value="original"> <option value="original">
{getMessage( {getMessage('modals.main.settings.sections.background.source.quality.original')}
"modals.main.settings.sections.background.source.quality.original"
)}
</option> </option>
<option value="high"> <option value="high">
{getMessage( {getMessage('modals.main.settings.sections.background.source.quality.high')}
"modals.main.settings.sections.background.source.quality.high"
)}
</option> </option>
<option value="normal"> <option value="normal">
{getMessage( {getMessage('modals.main.settings.sections.background.source.quality.normal')}
"modals.main.settings.sections.background.source.quality.normal"
)}
</option> </option>
<option value="datasaver"> <option value="datasaver">
{getMessage( {getMessage('modals.main.settings.sections.background.source.quality.datasaver')}
"modals.main.settings.sections.background.source.quality.datasaver"
)}
</option> </option>
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
@ -201,16 +168,16 @@ export default class BackgroundSettings extends PureComponent {
); );
switch (this.state.backgroundType) { switch (this.state.backgroundType) {
case "custom": case 'custom':
backgroundSettings = <CustomSettings interval={interval} />; backgroundSettings = <CustomSettings interval={interval} />;
break; break;
case "colour": case 'colour':
backgroundSettings = <ColourSettings />; backgroundSettings = <ColourSettings />;
break; break;
case "random_colour": case 'random_colour':
backgroundSettings = <></>; backgroundSettings = <></>;
break; break;
case "random_gradient": case 'random_gradient':
backgroundSettings = <></>; backgroundSettings = <></>;
break; break;
default: default:
@ -219,23 +186,23 @@ export default class BackgroundSettings extends PureComponent {
} }
if ( if (
localStorage.getItem("photo_packs") && localStorage.getItem('photo_packs') &&
this.state.backgroundType !== "custom" && this.state.backgroundType !== 'custom' &&
this.state.backgroundType !== "colour" && this.state.backgroundType !== 'colour' &&
this.state.backgroundType !== "api" this.state.backgroundType !== 'api'
) { ) {
backgroundSettings = null; backgroundSettings = null;
} }
const usingImage = const usingImage =
this.state.backgroundType !== "colour" && this.state.backgroundType !== 'colour' &&
this.state.backgroundType !== "random_colour" && this.state.backgroundType !== 'random_colour' &&
this.state.backgroundType !== "random_gradient"; this.state.backgroundType !== 'random_gradient';
return ( return (
<> <>
<Header <Header
title={getMessage("modals.main.settings.sections.background.title")} title={getMessage('modals.main.settings.sections.background.title')}
setting="background" setting="background"
category="background" category="background"
element="#backgroundImage" element="#backgroundImage"
@ -243,171 +210,130 @@ export default class BackgroundSettings extends PureComponent {
<SettingsItem title="cheese" subtitle="cheese"> <SettingsItem title="cheese" subtitle="cheese">
<Checkbox <Checkbox
name="ddgProxy" name="ddgProxy"
text={getMessage( text={getMessage('modals.main.settings.sections.background.ddg_image_proxy')}
"modals.main.settings.sections.background.ddg_image_proxy"
)}
element=".other" element=".other"
disabled={!usingImage} disabled={!usingImage}
/> />
<Checkbox <Checkbox
name="bgtransition" name="bgtransition"
text={getMessage( text={getMessage('modals.main.settings.sections.background.transition')}
"modals.main.settings.sections.background.transition"
)}
element=".other" element=".other"
disabled={!usingImage} disabled={!usingImage}
/> />
<Checkbox <Checkbox
name="photoInformation" name="photoInformation"
text={getMessage( text={getMessage('modals.main.settings.sections.background.photo_information')}
"modals.main.settings.sections.background.photo_information"
)}
element=".other" element=".other"
disabled={ disabled={
this.state.backgroundType !== "api" && this.state.backgroundType !== 'api' && this.state.backgroundType !== 'marketplace'
this.state.backgroundType !== "marketplace"
} }
/> />
<Checkbox <Checkbox
name="photoMap" name="photoMap"
text={getMessage( text={getMessage('modals.main.settings.sections.background.show_map')}
"modals.main.settings.sections.background.show_map"
)}
element=".other" element=".other"
disabled={this.state.backgroundAPI !== "unsplash"} disabled={this.state.backgroundAPI !== 'unsplash'}
/> />
</SettingsItem> </SettingsItem>
<SettingsItem <SettingsItem
title={getMessage( title={getMessage('modals.main.settings.sections.background.source.title')}
"modals.main.settings.sections.background.source.title"
)}
subtitle="mucho gracias" subtitle="mucho gracias"
> >
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.background.type.title')}
"modals.main.settings.sections.background.type.title"
)}
name="backgroundType" name="backgroundType"
onChange={(value) => this.setState({ backgroundType: value })} onChange={(value) => this.setState({ backgroundType: value })}
category="background" category="background"
> >
{this.state.marketplaceEnabled ? ( {this.state.marketplaceEnabled ? (
<option value="photo_pack"> <option value="photo_pack">
{this.getMessage("modals.main.navbar.marketplace")} {this.getMessage('modals.main.navbar.marketplace')}
</option> </option>
) : null} ) : null}
<option value="api"> <option value="api">
{getMessage("modals.main.settings.sections.background.type.api")} {getMessage('modals.main.settings.sections.background.type.api')}
</option> </option>
<option value="custom"> <option value="custom">
{getMessage( {getMessage('modals.main.settings.sections.background.type.custom_image')}
"modals.main.settings.sections.background.type.custom_image"
)}
</option> </option>
<option value="colour"> <option value="colour">
{getMessage( {getMessage('modals.main.settings.sections.background.type.custom_colour')}
"modals.main.settings.sections.background.type.custom_colour"
)}
</option> </option>
<option value="random_colour"> <option value="random_colour">
{getMessage( {getMessage('modals.main.settings.sections.background.type.random_colour')}
"modals.main.settings.sections.background.type.random_colour"
)}
</option> </option>
<option value="random_gradient"> <option value="random_gradient">
{getMessage( {getMessage('modals.main.settings.sections.background.type.random_gradient')}
"modals.main.settings.sections.background.type.random_gradient"
)}
</option> </option>
</Dropdown> </Dropdown>
</SettingsItem> </SettingsItem>
{backgroundSettings} {backgroundSettings}
{this.state.backgroundType === "api" || {this.state.backgroundType === 'api' ||
this.state.backgroundType === "custom" || this.state.backgroundType === 'custom' ||
this.state.marketplaceEnabled ? ( this.state.marketplaceEnabled ? (
<SettingsItem <SettingsItem
title={getMessage( title={getMessage('modals.main.settings.sections.background.effects.title')}
"modals.main.settings.sections.background.effects.title"
)}
subtitle="cheese" subtitle="cheese"
> >
<Slider <Slider
title={getMessage( title={getMessage('modals.main.settings.sections.background.effects.blur')}
"modals.main.settings.sections.background.effects.blur"
)}
name="blur" name="blur"
min="0" min="0"
max="100" max="100"
default="0" default="0"
display="%" display="%"
marks={values("background")} marks={values('background')}
category="background" category="background"
element="#backgroundImage" element="#backgroundImage"
/> />
<Slider <Slider
title={getMessage( title={getMessage('modals.main.settings.sections.background.effects.brightness')}
"modals.main.settings.sections.background.effects.brightness"
)}
name="brightness" name="brightness"
min="0" min="0"
max="100" max="100"
default="90" default="90"
display="%" display="%"
marks={values("background")} marks={values('background')}
category="background" category="background"
element="#backgroundImage" element="#backgroundImage"
/> />
<Dropdown <Dropdown
label={getMessage( label={getMessage('modals.main.settings.sections.background.effects.filters.title')}
"modals.main.settings.sections.background.effects.filters.title"
)}
name="backgroundFilter" name="backgroundFilter"
onChange={(value) => this.setState({ backgroundFilter: value })} onChange={(value) => this.setState({ backgroundFilter: value })}
category="background" category="background"
element="#backgroundImage" element="#backgroundImage"
> >
<option value="none"> <option value="none">
{getMessage( {getMessage('modals.main.settings.sections.appearance.navbar.refresh_options.none')}
"modals.main.settings.sections.appearance.navbar.refresh_options.none"
)}
</option> </option>
<option value="grayscale"> <option value="grayscale">
{getMessage( {getMessage('modals.main.settings.sections.background.effects.filters.grayscale')}
"modals.main.settings.sections.background.effects.filters.grayscale"
)}
</option> </option>
<option value="sepia"> <option value="sepia">
{getMessage( {getMessage('modals.main.settings.sections.background.effects.filters.sepia')}
"modals.main.settings.sections.background.effects.filters.sepia"
)}
</option> </option>
<option value="invert"> <option value="invert">
{getMessage( {getMessage('modals.main.settings.sections.background.effects.filters.invert')}
"modals.main.settings.sections.background.effects.filters.invert"
)}
</option> </option>
<option value="saturate"> <option value="saturate">
{getMessage( {getMessage('modals.main.settings.sections.background.effects.filters.saturate')}
"modals.main.settings.sections.background.effects.filters.saturate"
)}
</option> </option>
<option value="contrast"> <option value="contrast">
{getMessage( {getMessage('modals.main.settings.sections.background.effects.filters.contrast')}
"modals.main.settings.sections.background.effects.filters.contrast"
)}
</option> </option>
</Dropdown> </Dropdown>
{this.state.backgroundFilter !== "none" ? ( {this.state.backgroundFilter !== 'none' ? (
<Slider <Slider
title={getMessage( title={getMessage(
"modals.main.settings.sections.background.effects.filters.amount" 'modals.main.settings.sections.background.effects.filters.amount',
)} )}
name="backgroundFilterAmount" name="backgroundFilterAmount"
min="0" min="0"
max="100" max="100"
default="0" default="0"
display="%" display="%"
marks={values("background")} marks={values('background')}
category="background" category="background"
element="#backgroundImage" element="#backgroundImage"
/> />

View File

@ -1,25 +1,24 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent, Fragment } from "react"; import { PureComponent, Fragment } from 'react';
import { ColorPicker } from "react-color-gradient-picker"; import { ColorPicker } from 'react-color-gradient-picker';
import { toast } from "react-toastify"; import { toast } from 'react-toastify';
import SettingsItem from "../../SettingsItem"; import SettingsItem from '../../SettingsItem';
import hexToRgb from "modules/helpers/background/hexToRgb"; import hexToRgb from 'modules/helpers/background/hexToRgb';
import rgbToHex from "modules/helpers/background/rgbToHex"; import rgbToHex from 'modules/helpers/background/rgbToHex';
import "react-color-gradient-picker/dist/index.css"; import 'react-color-gradient-picker/dist/index.css';
import "../../../scss/settings/react-color-picker-gradient-picker-custom-styles.scss"; import '../../../scss/settings/react-color-picker-gradient-picker-custom-styles.scss';
export default class ColourSettings extends PureComponent { export default class ColourSettings extends PureComponent {
DefaultGradientSettings = { DefaultGradientSettings = {
angle: "180", angle: '180',
gradient: [{ colour: "#ffb032", stop: 0 }], gradient: [{ colour: '#ffb032', stop: 0 }],
type: "linear", type: 'linear',
}; };
GradientPickerInitialState = undefined; GradientPickerInitialState = undefined;
getMessage = (text) => getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
constructor() { constructor() {
super(); super();
@ -29,11 +28,11 @@ export default class ColourSettings extends PureComponent {
} }
resetColour() { resetColour() {
localStorage.setItem("customBackgroundColour", ""); localStorage.setItem('customBackgroundColour', '');
this.setState({ this.setState({
gradientSettings: this.DefaultGradientSettings, gradientSettings: this.DefaultGradientSettings,
}); });
toast(this.getMessage("toasts.reset")); toast(this.getMessage('toasts.reset'));
} }
initialiseColourPickerState(gradientSettings) { initialiseColourPickerState(gradientSettings) {
@ -54,10 +53,10 @@ export default class ColourSettings extends PureComponent {
} }
componentDidMount() { componentDidMount() {
const hex = localStorage.getItem("customBackgroundColour"); const hex = localStorage.getItem('customBackgroundColour');
let gradientSettings = undefined; let gradientSettings = undefined;
if (hex !== "") { if (hex !== '') {
try { try {
gradientSettings = JSON.parse(hex); gradientSettings = JSON.parse(hex);
} catch (e) { } catch (e) {
@ -75,10 +74,7 @@ export default class ColourSettings extends PureComponent {
} }
componentDidUpdate() { componentDidUpdate() {
localStorage.setItem( localStorage.setItem('customBackgroundColour', this.currentGradientSettings());
"customBackgroundColour",
this.currentGradientSettings()
);
} }
onGradientChange = (event, index) => { onGradientChange = (event, index) => {
@ -89,7 +85,7 @@ export default class ColourSettings extends PureComponent {
gradientSettings: { gradientSettings: {
...s.gradientSettings, ...s.gradientSettings,
gradient: s.gradientSettings.gradient.map((g, i) => gradient: s.gradientSettings.gradient.map((g, i) =>
i === index ? { ...g, [name]: newValue } : g i === index ? { ...g, [name]: newValue } : g,
), ),
}, },
}); });
@ -100,8 +96,7 @@ export default class ColourSettings extends PureComponent {
addColour = () => { addColour = () => {
this.setState((s) => { this.setState((s) => {
const [lastGradient, ...initGradients] = const [lastGradient, ...initGradients] = s.gradientSettings.gradient.reverse();
s.gradientSettings.gradient.reverse();
return { return {
gradientSettings: { gradientSettings: {
...s.gradientSettings, ...s.gradientSettings,
@ -109,10 +104,7 @@ export default class ColourSettings extends PureComponent {
...initGradients, ...initGradients,
lastGradient, lastGradient,
{ {
colour: colour: localStorage.getItem('theme') === 'dark' ? '#000000' : '#ffffff',
localStorage.getItem("theme") === "dark"
? "#000000"
: "#ffffff",
stop: 100, stop: 100,
}, },
].sort((a, b) => (a.stop > b.stop ? 1 : -1)), ].sort((a, b) => (a.stop > b.stop ? 1 : -1)),
@ -120,25 +112,18 @@ export default class ColourSettings extends PureComponent {
}; };
}); });
variables.stats.postEvent( variables.stats.postEvent('setting', 'Changed backgroundType from colour to gradient');
"setting",
"Changed backgroundType from colour to gradient"
);
}; };
currentGradientSettings = () => { currentGradientSettings = () => {
if ( if (
typeof this.state.gradientSettings === "object" && typeof this.state.gradientSettings === 'object' &&
this.state.gradientSettings.gradient.every( this.state.gradientSettings.gradient.every(
(g) => (g) =>
g.colour !== g.colour !== this.getMessage('modals.main.settings.sections.background.source.disabled'),
this.getMessage(
"modals.main.settings.sections.background.source.disabled"
)
) )
) { ) {
const clampNumber = (num, a, b) => const clampNumber = (num, a, b) => Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b));
return JSON.stringify({ return JSON.stringify({
...this.state.gradientSettings, ...this.state.gradientSettings,
gradient: [ gradient: [
@ -148,13 +133,11 @@ export default class ColourSettings extends PureComponent {
].sort((a, b) => (a.stop > b.stop ? 1 : -1)), ].sort((a, b) => (a.stop > b.stop ? 1 : -1)),
}); });
} }
return this.getMessage( return this.getMessage('modals.main.settings.sections.background.source.disabled');
"modals.main.settings.sections.background.source.disabled"
);
}; };
onColourPickerChange = (attrs, name) => { onColourPickerChange = (attrs, name) => {
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === 'development') {
console.log(attrs, name); console.log(attrs, name);
} }
@ -163,7 +146,7 @@ export default class ColourSettings extends PureComponent {
angle: attrs.degree, angle: attrs.degree,
gradient: attrs.points.map((p) => { gradient: attrs.points.map((p) => {
return { return {
colour: "#" + rgbToHex(p.red, p.green, p.blue), colour: '#' + rgbToHex(p.red, p.green, p.blue),
stop: p.left, stop: p.left,
}; };
}), }),
@ -175,18 +158,17 @@ export default class ColourSettings extends PureComponent {
}; };
showReminder() { showReminder() {
const reminderInfo = document.querySelector(".reminder-info"); const reminderInfo = document.querySelector('.reminder-info');
if (reminderInfo.style.display !== "block") { if (reminderInfo.style.display !== 'block') {
reminderInfo.style.display = "block"; reminderInfo.style.display = 'block';
localStorage.setItem("showReminder", true); localStorage.setItem('showReminder', true);
} }
} }
render() { render() {
let colourSettings = null; let colourSettings = null;
if (typeof this.state.gradientSettings === "object") { if (typeof this.state.gradientSettings === 'object') {
const gradientHasMoreThanOneColour = const gradientHasMoreThanOneColour = this.state.gradientSettings.gradient.length > 1;
this.state.gradientSettings.gradient.length > 1;
let gradientInputs; let gradientInputs;
if (gradientHasMoreThanOneColour) { if (gradientHasMoreThanOneColour) {
@ -196,11 +178,9 @@ export default class ColourSettings extends PureComponent {
gradientInputs = ( gradientInputs = (
<ColorPicker <ColorPicker
onStartChange={(colour) => onStartChange={(colour) => this.onColourPickerChange(colour, 'start')}
this.onColourPickerChange(colour, "start") onChange={(colour) => this.onColourPickerChange(colour, 'change')}
} onEndChange={(colour) => this.onColourPickerChange(colour, 'end')}
onChange={(colour) => this.onColourPickerChange(colour, "change")}
onEndChange={(colour) => this.onColourPickerChange(colour, "end")}
gradient={this.GradientPickerInitialState} gradient={this.GradientPickerInitialState}
isGradient isGradient
/> />
@ -210,14 +190,14 @@ export default class ColourSettings extends PureComponent {
return ( return (
<Fragment key={i}> <Fragment key={i}>
<input <input
id={"colour_" + i} id={'colour_' + i}
type="color" type="color"
name="colour" name="colour"
className="colour" className="colour"
onChange={(event) => this.onGradientChange(event, i)} onChange={(event) => this.onGradientChange(event, i)}
value={g.colour} value={g.colour}
></input> ></input>
<label htmlFor={"colour_" + i} className="customBackgroundHex"> <label htmlFor={'colour_' + i} className="customBackgroundHex">
{g.colour} {g.colour}
</label> </label>
</Fragment> </Fragment>
@ -231,9 +211,7 @@ export default class ColourSettings extends PureComponent {
{!gradientHasMoreThanOneColour ? ( {!gradientHasMoreThanOneColour ? (
<> <>
<button type="button" className="add" onClick={this.addColour}> <button type="button" className="add" onClick={this.addColour}>
{this.getMessage( {this.getMessage('modals.main.settings.sections.background.source.add_colour')}
"modals.main.settings.sections.background.source.add_colour"
)}
</button> </button>
</> </>
) : null} ) : null}
@ -244,12 +222,10 @@ export default class ColourSettings extends PureComponent {
return ( return (
<> <>
<SettingsItem <SettingsItem
title={this.getMessage( title={this.getMessage('modals.main.settings.sections.background.source.custom_colour')}
"modals.main.settings.sections.background.source.custom_colour"
)}
> >
<span className="link" onClick={() => this.resetColour()}> <span className="link" onClick={() => this.resetColour()}>
{this.getMessage("modals.main.settings.buttons.reset")} {this.getMessage('modals.main.settings.buttons.reset')}
</span> </span>
{colourSettings} {colourSettings}
</SettingsItem> </SettingsItem>

View File

@ -1,25 +1,19 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { toast } from "react-toastify"; import { toast } from 'react-toastify';
import { import { MdCancel, MdAddLink, MdAddPhotoAlternate, MdPersonalVideo } from 'react-icons/md';
MdCancel, import EventBus from 'modules/helpers/eventbus';
MdAddLink,
MdAddPhotoAlternate,
MdPersonalVideo,
} from "react-icons/md";
import EventBus from "modules/helpers/eventbus";
import Checkbox from "../../Checkbox"; import Checkbox from '../../Checkbox';
import FileUpload from "../../FileUpload"; import FileUpload from '../../FileUpload';
import SettingsItem from "../../SettingsItem"; import SettingsItem from '../../SettingsItem';
import Modal from "react-modal"; import Modal from 'react-modal';
import CustomURLModal from "./CustomURLModal"; import CustomURLModal from './CustomURLModal';
export default class CustomSettings extends PureComponent { export default class CustomSettings extends PureComponent {
getMessage = (text) => getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
constructor() { constructor() {
super(); super();
@ -30,12 +24,12 @@ export default class CustomSettings extends PureComponent {
} }
resetCustom = () => { resetCustom = () => {
localStorage.setItem("customBackground", "[]"); localStorage.setItem('customBackground', '[]');
this.setState({ this.setState({
customBackground: [], customBackground: [],
}); });
toast(this.getMessage("toasts.reset")); toast(this.getMessage('toasts.reset'));
EventBus.dispatch("refresh", "background"); EventBus.dispatch('refresh', 'background');
}; };
customBackground(e, text, index) { customBackground(e, text, index) {
@ -48,15 +42,15 @@ export default class CustomSettings extends PureComponent {
}); });
this.forceUpdate(); this.forceUpdate();
localStorage.setItem("customBackground", JSON.stringify(customBackground)); localStorage.setItem('customBackground', JSON.stringify(customBackground));
document.querySelector(".reminder-info").style.display = "flex"; document.querySelector('.reminder-info').style.display = 'flex';
localStorage.setItem("showReminder", true); localStorage.setItem('showReminder', true);
} }
modifyCustomBackground(type, index) { modifyCustomBackground(type, index) {
const customBackground = this.state.customBackground; const customBackground = this.state.customBackground;
if (type === "add") { if (type === 'add') {
customBackground.push(""); customBackground.push('');
} else { } else {
customBackground.splice(index, 1); customBackground.splice(index, 1);
} }
@ -66,39 +60,33 @@ export default class CustomSettings extends PureComponent {
}); });
this.forceUpdate(); this.forceUpdate();
localStorage.setItem("customBackground", JSON.stringify(customBackground)); localStorage.setItem('customBackground', JSON.stringify(customBackground));
document.querySelector(".reminder-info").style.display = "flex"; document.querySelector('.reminder-info').style.display = 'flex';
localStorage.setItem("showReminder", true); localStorage.setItem('showReminder', true);
} }
videoCheck(url) { videoCheck(url) {
return ( return (
url.startsWith("data:video/") || url.startsWith('data:video/') ||
url.endsWith(".mp4") || url.endsWith('.mp4') ||
url.endsWith(".webm") || url.endsWith('.webm') ||
url.endsWith(".ogg") url.endsWith('.ogg')
); );
} }
videoCustomSettings = () => { videoCustomSettings = () => {
const hasVideo = this.state.customBackground.filter((bg) => const hasVideo = this.state.customBackground.filter((bg) => this.videoCheck(bg));
this.videoCheck(bg)
);
if (hasVideo.length > 0) { if (hasVideo.length > 0) {
return ( return (
<> <>
<Checkbox <Checkbox
name="backgroundVideoLoop" name="backgroundVideoLoop"
text={this.getMessage( text={this.getMessage('modals.main.settings.sections.background.source.loop_video')}
"modals.main.settings.sections.background.source.loop_video"
)}
/> />
<Checkbox <Checkbox
name="backgroundVideoMute" name="backgroundVideoMute"
text={this.getMessage( text={this.getMessage('modals.main.settings.sections.background.source.mute_video')}
"modals.main.settings.sections.background.source.mute_video"
)}
/> />
</> </>
); );
@ -110,19 +98,17 @@ export default class CustomSettings extends PureComponent {
getCustom() { getCustom() {
let data; let data;
try { try {
data = JSON.parse(localStorage.getItem("customBackground")); data = JSON.parse(localStorage.getItem('customBackground'));
} catch (e) { } catch (e) {
data = [localStorage.getItem("customBackground")]; data = [localStorage.getItem('customBackground')];
} }
return data; return data;
} }
uploadCustomBackground() { uploadCustomBackground() {
document document.getElementById('bg-input').setAttribute('index', this.state.customBackground.length);
.getElementById("bg-input") document.getElementById('bg-input').click();
.setAttribute("index", this.state.customBackground.length);
document.getElementById("bg-input").click();
// to fix loadFunction // to fix loadFunction
this.setState({ this.setState({
currentBackgroundIndex: this.state.customBackground.length, currentBackgroundIndex: this.state.customBackground.length,
@ -134,39 +120,27 @@ export default class CustomSettings extends PureComponent {
customURLModal: false, customURLModal: false,
currentBackgroundIndex: this.state.customBackground.length, currentBackgroundIndex: this.state.customBackground.length,
}); });
this.customBackground( this.customBackground({ target: { value: e } }, true, this.state.customBackground.length);
{ target: { value: e } },
true,
this.state.customBackground.length
);
} }
render() { render() {
return ( return (
<> <>
{this.props.interval} {this.props.interval}
<div className="settingsRow" style={{ alignItems: "flex-start" }}> <div className="settingsRow" style={{ alignItems: 'flex-start' }}>
<div className="content"> <div className="content">
<div className="images-row"> <div className="images-row">
{this.state.customBackground.map((url, index) => ( {this.state.customBackground.map((url, index) => (
<div key={index}> <div key={index}>
<img <img
alt={"Custom background " + (index || 0)} alt={'Custom background ' + (index || 0)}
src={`${ src={`${!this.videoCheck(url) ? this.state.customBackground[index] : ''}`}
!this.videoCheck(url)
? this.state.customBackground[index]
: ""
}`}
/> />
{this.videoCheck(url) ? ( {this.videoCheck(url) ? <MdPersonalVideo className="customvideoicon" /> : null}
<MdPersonalVideo className="customvideoicon" />
) : null}
{this.state.customBackground.length > 0 ? ( {this.state.customBackground.length > 0 ? (
<button <button
className="iconButton" className="iconButton"
onClick={() => onClick={() => this.modifyCustomBackground('remove', index)}
this.modifyCustomBackground("remove", index)
}
> >
<MdCancel /> <MdCancel />
</button> </button>
@ -183,14 +157,10 @@ export default class CustomSettings extends PureComponent {
<span className="subtitle"> <span className="subtitle">
Available formats, jpeg, png, webp, webm, gif, mp4, webm, ogg Available formats, jpeg, png, webp, webm, gif, mp4, webm, ogg
</span> </span>
<button onClick={() => this.uploadCustomBackground()}> <button onClick={() => this.uploadCustomBackground()}>Or Select</button>
Or Select
</button>
</div> </div>
<button onClick={() => this.setState({ customURLModal: true })}> <button onClick={() => this.setState({ customURLModal: true })}>
{this.getMessage( {this.getMessage('modals.main.settings.sections.background.source.add_url')}{' '}
"modals.main.settings.sections.background.source.add_url"
)}{" "}
<MdAddLink /> <MdAddLink />
</button> </button>
{/*<span className='subtitle'> {/*<span className='subtitle'>
@ -204,9 +174,7 @@ export default class CustomSettings extends PureComponent {
<FileUpload <FileUpload
id="bg-input" id="bg-input"
accept="image/jpeg, image/png, image/webp, image/webm, image/gif, video/mp4, video/webm, video/ogg" accept="image/jpeg, image/png, image/webp, image/webm, image/gif, video/mp4, video/webm, video/ogg"
loadFunction={(e) => loadFunction={(e) => this.customBackground(e, false, this.state.currentBackgroundIndex)}
this.customBackground(e, false, this.state.currentBackgroundIndex)
}
/> />
{this.videoCustomSettings()} {this.videoCustomSettings()}
<Modal <Modal

View File

@ -1,7 +1,7 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { useState } from "react"; import { useState } from 'react';
import { MdAdd } from "react-icons/md"; import { MdAdd } from 'react-icons/md';
import { TextField } from "@mui/material"; import { TextField } from '@mui/material';
export default function CustomURLModal({ modalClose, modalCloseOnly }) { export default function CustomURLModal({ modalClose, modalCloseOnly }) {
const [url, setURL] = useState(); const [url, setURL] = useState();
@ -14,18 +14,14 @@ export default function CustomURLModal({ modalClose, modalCloseOnly }) {
<h1> <h1>
{variables.language.getMessage( {variables.language.getMessage(
variables.languagecode, variables.languagecode,
"modals.main.settings.sections.background.source.add_url" 'modals.main.settings.sections.background.source.add_url',
)} )}
</h1> </h1>
<TextField <TextField value={url} onChange={(e) => setURL(e.target.value)} varient="outlined" />
value={url}
onChange={(e) => setURL(e.target.value)}
varient="outlined"
/>
<div className="resetFooter"> <div className="resetFooter">
<button <button
className="round import" className="round import"
style={{ marginLeft: "5px" }} style={{ marginLeft: '5px' }}
onClick={() => modalClose(url)} onClick={() => modalClose(url)}
> >
<MdAdd /> <MdAdd />

View File

@ -9,10 +9,16 @@ export default function Addons(props) {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text); const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return ( return (
<Tabs changeTab={(type) => props.changeTab(type)} current='addons'> <Tabs changeTab={(type) => props.changeTab(type)} current="addons">
<div label={getMessage('modals.main.addons.added')} name='added'><Added/></div> <div label={getMessage('modals.main.addons.added')} name="added">
<div label={getMessage('modals.main.addons.sideload.title')} name='sideload'><Sideload/></div> <Added />
<div label={getMessage('modals.main.addons.create.title')} name='create'><Create/></div> </div>
<div label={getMessage('modals.main.addons.sideload.title')} name="sideload">
<Sideload />
</div>
<div label={getMessage('modals.main.addons.create.title')} name="create">
<Create />
</div>
</Tabs> </Tabs>
); );
} }

View File

@ -7,11 +7,19 @@ export default function Marketplace(props) {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text); const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return ( return (
<Tabs changeTab={(type) => props.changeTab(type)} current='marketplace'> <Tabs changeTab={(type) => props.changeTab(type)} current="marketplace">
<div label='All' name='all'><MarketplaceTab type='all'/></div> <div label="All" name="all">
<div label={getMessage('modals.main.marketplace.photo_packs')} name='photo_packs'><MarketplaceTab type='photo_packs'/></div> <MarketplaceTab type="all" />
<div label={getMessage('modals.main.marketplace.quote_packs')} name='quote_packs'><MarketplaceTab type='quote_packs'/></div> </div>
<div label={getMessage('modals.main.marketplace.preset_settings')} name='preset_settings'><MarketplaceTab type='preset_settings'/></div> <div label={getMessage('modals.main.marketplace.photo_packs')} name="photo_packs">
<MarketplaceTab type="photo_packs" />
</div>
<div label={getMessage('modals.main.marketplace.quote_packs')} name="quote_packs">
<MarketplaceTab type="quote_packs" />
</div>
<div label={getMessage('modals.main.marketplace.preset_settings')} name="preset_settings">
<MarketplaceTab type="preset_settings" />
</div>
</Tabs> </Tabs>
); );
} }

View File

@ -26,28 +26,72 @@ export default function Settings(props) {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text); const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
return ( return (
<Tabs changeTab={(type) => props.changeTab(type)} current='settings'> <Tabs changeTab={(type) => props.changeTab(type)} current="settings">
<div label={getMessage('modals.main.settings.sections.appearance.navbar.title')} name='navbar'><Navbar/></div> <div
<div label={getMessage('modals.main.settings.sections.greeting.title')} name='greeting'><Greeting/></div> label={getMessage('modals.main.settings.sections.appearance.navbar.title')}
<div label={getMessage('modals.main.settings.sections.time.title')} name='time'><Time/></div> name="navbar"
<div label={getMessage('modals.main.settings.sections.quicklinks.title')} name='quicklinks'><QuickLinks/></div> >
<div label={getMessage('modals.main.settings.sections.quote.title')} name='quote'><Quote/></div> <Navbar />
<div label={getMessage('modals.main.settings.sections.date.title')} name='date'><Date/></div> </div>
<div label='Reminder' name='reminder'><Reminder/></div> <div label={getMessage('modals.main.settings.sections.greeting.title')} name="greeting">
<div label={getMessage('modals.main.settings.sections.message.title')} name='message'><Message/></div> <Greeting />
<div label={getMessage('modals.main.settings.sections.background.title')} name='background'><Background/></div> </div>
<div label={getMessage('modals.main.settings.sections.search.title')} name='search'><Search/></div> <div label={getMessage('modals.main.settings.sections.time.title')} name="time">
<div label={getMessage('modals.main.settings.sections.weather.title')} name='weather'><Weather/></div> <Time />
</div>
<div label={getMessage('modals.main.settings.sections.order.title')} name='order'><Order/></div> <div label={getMessage('modals.main.settings.sections.quicklinks.title')} name="quicklinks">
<div label={getMessage('modals.main.settings.sections.appearance.title')} name='appearance'><Appearance/></div> <QuickLinks />
<div label={getMessage('modals.main.settings.sections.language.title')} name='language'><Language/></div> </div>
<div label={getMessage('modals.main.settings.sections.advanced.title')} name='advanced'><Advanced/></div> <div label={getMessage('modals.main.settings.sections.quote.title')} name="quote">
{/*<div label={getMessage('modals.main.settings.sections.keybinds.title')} name='keybinds'><Keybinds/></div>*/} <Quote />
<div label={getMessage('modals.main.settings.sections.stats.title')} name='stats'><Stats/></div> </div>
<div label={getMessage('modals.main.settings.sections.experimental.title')} name='experimental'><Experimental/></div> <div label={getMessage('modals.main.settings.sections.date.title')} name="date">
<div label={getMessage('modals.main.settings.sections.changelog.title')} name='changelog'><Changelog/></div> <Date />
<div label={getMessage('modals.main.settings.sections.about.title')} name='about'><About/></div> </div>
</Tabs> <div label="Reminder" name="reminder">
<Reminder />
</div>
<div label={getMessage('modals.main.settings.sections.message.title')} name="message">
<Message />
</div>
<div label={getMessage('modals.main.settings.sections.background.title')} name="background">
<Background />
</div>
<div label={getMessage('modals.main.settings.sections.search.title')} name="search">
<Search />
</div>
<div label={getMessage('modals.main.settings.sections.weather.title')} name="weather">
<Weather />
</div>
<div label={getMessage('modals.main.settings.sections.order.title')} name="order">
<Order />
</div>
<div label={getMessage('modals.main.settings.sections.appearance.title')} name="appearance">
<Appearance />
</div>
<div label={getMessage('modals.main.settings.sections.language.title')} name="language">
<Language />
</div>
<div label={getMessage('modals.main.settings.sections.advanced.title')} name="advanced">
<Advanced />
</div>
{/*<div label={getMessage('modals.main.settings.sections.keybinds.title')} name='keybinds'><Keybinds/></div>*/}
<div label={getMessage('modals.main.settings.sections.stats.title')} name="stats">
<Stats />
</div>
<div
label={getMessage('modals.main.settings.sections.experimental.title')}
name="experimental"
>
<Experimental />
</div>
<div label={getMessage('modals.main.settings.sections.changelog.title')} name="changelog">
<Changelog />
</div>
<div label={getMessage('modals.main.settings.sections.about.title')} name="about">
<About />
</div>
</Tabs>
); );
} }

View File

@ -26,7 +26,7 @@ import {
MdEvent as Reminder, MdEvent as Reminder,
MdCode as Sideload, MdCode as Sideload,
MdAddCircleOutline as Added, MdAddCircleOutline as Added,
MdAddCircleOutline as Create MdAddCircleOutline as Create,
} from 'react-icons/md'; } from 'react-icons/md';
function Tab({ label, currentTab, onClick, navbarTab }) { function Tab({ label, currentTab, onClick, navbarTab }) {
@ -46,56 +46,119 @@ function Tab({ label, currentTab, onClick, navbarTab }) {
let icon, divider; let icon, divider;
switch (label) { switch (label) {
case getMessage('modals.main.navbar.settings'): icon = <Settings/>; break; case getMessage('modals.main.navbar.settings'):
case getMessage('modals.main.navbar.addons'): icon = <Addons/>; break; icon = <Settings />;
case getMessage('modals.main.navbar.marketplace'): icon = <Marketplace/>; break; break;
case getMessage('modals.main.navbar.addons'):
icon = <Addons />;
break;
case getMessage('modals.main.navbar.marketplace'):
icon = <Marketplace />;
break;
case getMessage('modals.main.settings.sections.appearance.navbar.title'): icon = <Navbar/>; break; case getMessage('modals.main.settings.sections.appearance.navbar.title'):
case getMessage('modals.main.settings.sections.greeting.title'): icon = <Greeting/>; break; icon = <Navbar />;
case getMessage('modals.main.settings.sections.time.title'): icon = <Time/>; break; break;
case getMessage('modals.main.settings.sections.quicklinks.title'): icon = <QuickLinks/>; break; case getMessage('modals.main.settings.sections.greeting.title'):
case getMessage('modals.main.settings.sections.quote.title'): icon = <Quote/>; break; icon = <Greeting />;
case getMessage('modals.main.settings.sections.date.title'): icon = <Date/>; break; break;
case getMessage('modals.main.settings.sections.message.title'): icon = <Message/>; break; case getMessage('modals.main.settings.sections.time.title'):
case getMessage('modals.main.settings.sections.background.title'): icon = <Background/>; break; icon = <Time />;
case getMessage('modals.main.settings.sections.search.title'): icon = <MdSearch/>; break; break;
case getMessage('modals.main.settings.sections.weather.title'): icon = <Weather/>; divider = true; break; case getMessage('modals.main.settings.sections.quicklinks.title'):
case getMessage('modals.main.settings.sections.order.title'): icon = <Order/>; break; icon = <QuickLinks />;
case 'Reminder': icon = <Reminder/>; break; break;
case getMessage('modals.main.settings.sections.quote.title'):
icon = <Quote />;
break;
case getMessage('modals.main.settings.sections.date.title'):
icon = <Date />;
break;
case getMessage('modals.main.settings.sections.message.title'):
icon = <Message />;
break;
case getMessage('modals.main.settings.sections.background.title'):
icon = <Background />;
break;
case getMessage('modals.main.settings.sections.search.title'):
icon = <MdSearch />;
break;
case getMessage('modals.main.settings.sections.weather.title'):
icon = <Weather />;
divider = true;
break;
case getMessage('modals.main.settings.sections.order.title'):
icon = <Order />;
break;
case 'Reminder':
icon = <Reminder />;
break;
case getMessage('modals.main.settings.sections.appearance.title'): icon = <Appearance/>; break; case getMessage('modals.main.settings.sections.appearance.title'):
case getMessage('modals.main.settings.sections.language.title'): icon = <Language/>; divider = true; break; icon = <Appearance />;
case getMessage('modals.main.settings.sections.advanced.title'): icon = <Advanced/>; break; break;
case getMessage('modals.main.settings.sections.language.title'):
icon = <Language />;
divider = true;
break;
case getMessage('modals.main.settings.sections.advanced.title'):
icon = <Advanced />;
break;
//case getMessage('modals.main.settings.sections.keybinds.title'): icon = <Keybinds/>; break; //case getMessage('modals.main.settings.sections.keybinds.title'): icon = <Keybinds/>; break;
case getMessage('modals.main.settings.sections.stats.title'): icon = <Stats/>; break; case getMessage('modals.main.settings.sections.stats.title'):
case getMessage('modals.main.settings.sections.experimental.title'): icon = <Experimental/>; divider = true; break; icon = <Stats />;
case getMessage('modals.main.settings.sections.changelog.title'): icon = <Changelog/>; break; break;
case getMessage('modals.main.settings.sections.about.title'): icon = <About/>; break; case getMessage('modals.main.settings.sections.experimental.title'):
icon = <Experimental />;
divider = true;
break;
case getMessage('modals.main.settings.sections.changelog.title'):
icon = <Changelog />;
break;
case getMessage('modals.main.settings.sections.about.title'):
icon = <About />;
break;
case getMessage('modals.main.addons.added'): icon = <Added/>; break; case getMessage('modals.main.addons.added'):
case getMessage('modals.main.addons.sideload.title'): icon = <Sideload/>; break; icon = <Added />;
case getMessage('modals.main.addons.create.title'): icon = <Create/>; break; break;
case getMessage('modals.main.addons.sideload.title'):
icon = <Sideload />;
break;
case getMessage('modals.main.addons.create.title'):
icon = <Create />;
break;
case 'All': icon = <Addons/>; divider = true; break; case 'All':
case getMessage('modals.main.marketplace.photo_packs'): icon = <Background/>; break; icon = <Addons />;
case getMessage('modals.main.marketplace.quote_packs'): icon = <Quote/>; break; divider = true;
case getMessage('modals.main.marketplace.preset_settings'): icon = <Advanced/>; break; break;
case getMessage('modals.main.marketplace.photo_packs'):
icon = <Background />;
break;
case getMessage('modals.main.marketplace.quote_packs'):
icon = <Quote />;
break;
case getMessage('modals.main.marketplace.preset_settings'):
icon = <Advanced />;
break;
default: break; default:
break;
} }
if (label === getMessage('modals.main.settings.sections.experimental.title')) { if (label === getMessage('modals.main.settings.sections.experimental.title')) {
if (localStorage.getItem('experimental') === 'false') { if (localStorage.getItem('experimental') === 'false') {
return <hr/>; return <hr />;
} }
} }
return ( return (
<> <>
<button className={className} onClick={() => onClick(label)}> <button className={className} onClick={() => onClick(label)}>
{icon} <span>{label}</span> {icon} <span>{label}</span>
</button> </button>
{(divider === true) ? <hr/> : null} {divider === true ? <hr /> : null}
</> </>
); );
} }

View File

@ -1,12 +1,8 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { import { MdSettings, MdOutlineShoppingBasket, MdOutlineExtension } from 'react-icons/md';
MdSettings, import Tab from './Tab';
MdOutlineShoppingBasket, import ErrorBoundary from '../../../ErrorBoundary';
MdOutlineExtension,
} from "react-icons/md";
import Tab from "./Tab";
import ErrorBoundary from "../../../ErrorBoundary";
export default class Tabs extends PureComponent { export default class Tabs extends PureComponent {
constructor(props) { constructor(props) {
@ -20,7 +16,7 @@ export default class Tabs extends PureComponent {
onClick = (tab, name) => { onClick = (tab, name) => {
if (name !== this.state.currentName) { if (name !== this.state.currentName) {
variables.stats.postEvent("tab", `Opened ${name}`); variables.stats.postEvent('tab', `Opened ${name}`);
} }
this.setState({ this.setState({
@ -31,48 +27,48 @@ export default class Tabs extends PureComponent {
render() { render() {
const reminderInfo = ( const reminderInfo = (
<div className="reminder-info" style={{ display: "none" }}> <div className="reminder-info" style={{ display: 'none' }}>
<span className="title"> <span className="title">
{variables.language.getMessage( {variables.language.getMessage(
variables.languagecode, variables.languagecode,
"modals.main.settings.reminder.title" 'modals.main.settings.reminder.title',
)} )}
</span> </span>
<span className="subtitle"> <span className="subtitle">
{variables.language.getMessage( {variables.language.getMessage(
variables.languagecode, variables.languagecode,
"modals.main.settings.reminder.message" 'modals.main.settings.reminder.message',
)} )}
</span> </span>
<button onClick={() => window.location.reload()}> <button onClick={() => window.location.reload()}>
{variables.language.getMessage( {variables.language.getMessage(
variables.languagecode, variables.languagecode,
"modals.main.error_boundary.refresh" 'modals.main.error_boundary.refresh',
)} )}
</button> </button>
</div> </div>
); );
let settingsActive = ""; let settingsActive = '';
let addonsActive = ""; let addonsActive = '';
let marketplaceActive = ""; let marketplaceActive = '';
switch (this.props.current) { switch (this.props.current) {
case "settings": case 'settings':
settingsActive = " navbar-item-active"; settingsActive = ' navbar-item-active';
break; break;
case "addons": case 'addons':
addonsActive = " navbar-item-active"; addonsActive = ' navbar-item-active';
break; break;
case "marketplace": case 'marketplace':
marketplaceActive = " navbar-item-active"; marketplaceActive = ' navbar-item-active';
break; break;
default: default:
break; break;
} }
return ( return (
<div style={{ display: "flex", width: "100%" }}> <div style={{ display: 'flex', width: '100%' }}>
<ul className="sidebar"> <ul className="sidebar">
{reminderInfo} {reminderInfo}
{this.props.children.map((tab, index) => ( {this.props.children.map((tab, index) => (
@ -85,26 +81,26 @@ export default class Tabs extends PureComponent {
/> />
))} ))}
</ul> </ul>
<div className="tab-content" style={{ width: "100%" }}> <div className="tab-content" style={{ width: '100%' }}>
<ErrorBoundary> <ErrorBoundary>
<div className="modalNavbar"> <div className="modalNavbar">
<button <button
className={"navbar-item" + settingsActive} className={'navbar-item' + settingsActive}
onClick={() => this.props.changeTab("settings")} onClick={() => this.props.changeTab('settings')}
> >
<MdSettings /> <MdSettings />
<span>Settings</span> <span>Settings</span>
</button> </button>
<button <button
className={"navbar-item" + addonsActive} className={'navbar-item' + addonsActive}
onClick={() => this.props.changeTab("addons")} onClick={() => this.props.changeTab('addons')}
> >
<MdOutlineExtension /> <MdOutlineExtension />
<span>Add-ons</span> <span>Add-ons</span>
</button> </button>
<button <button
className={"navbar-item" + marketplaceActive} className={'navbar-item' + marketplaceActive}
onClick={() => this.props.changeTab("marketplace")} onClick={() => this.props.changeTab('marketplace')}
> >
<MdOutlineShoppingBasket /> <MdOutlineShoppingBasket />
<span>Marketplace</span> <span>Marketplace</span>

View File

@ -1,33 +1,27 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { import { MdCloudUpload, MdAutoAwesome, MdLightMode, MdDarkMode } from 'react-icons/md';
MdCloudUpload,
MdAutoAwesome,
MdLightMode,
MdDarkMode,
} from "react-icons/md";
import Radio from "../main/settings/Radio"; import Radio from '../main/settings/Radio';
import Checkbox from "../main/settings/Checkbox"; import Checkbox from '../main/settings/Checkbox';
import FileUpload from "../main/settings/FileUpload"; import FileUpload from '../main/settings/FileUpload';
import { loadSettings } from "modules/helpers/settings"; import { loadSettings } from 'modules/helpers/settings';
import { importSettings } from "modules/helpers/settings/modals"; import { importSettings } from 'modules/helpers/settings/modals';
const languages = require("modules/languages.json"); const languages = require('modules/languages.json');
const default_settings = require("modules/default_settings.json"); const default_settings = require('modules/default_settings.json');
export default class WelcomeSections extends PureComponent { export default class WelcomeSections extends PureComponent {
getMessage = (text) => getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
variables.language.getMessage(variables.languagecode, text);
constructor() { constructor() {
super(); super();
this.state = { this.state = {
// themes // themes
autoClass: "toggle auto active", autoClass: 'toggle auto active',
lightClass: "toggle lightTheme", lightClass: 'toggle lightTheme',
darkClass: "toggle darkTheme", darkClass: 'toggle darkTheme',
// welcome // welcome
welcomeImage: 0, welcomeImage: 0,
// final // final
@ -39,22 +33,17 @@ export default class WelcomeSections extends PureComponent {
changeTheme(type) { changeTheme(type) {
this.setState({ this.setState({
autoClass: type === "auto" ? "toggle auto active" : "toggle auto", autoClass: type === 'auto' ? 'toggle auto active' : 'toggle auto',
lightClass: lightClass: type === 'light' ? 'toggle lightTheme active' : 'toggle lightTheme',
type === "light" ? "toggle lightTheme active" : "toggle lightTheme", darkClass: type === 'dark' ? 'toggle darkTheme active' : 'toggle darkTheme',
darkClass:
type === "dark" ? "toggle darkTheme active" : "toggle darkTheme",
}); });
localStorage.setItem("theme", type); localStorage.setItem('theme', type);
loadSettings(true); loadSettings(true);
} }
getSetting(name) { getSetting(name) {
const value = localStorage const value = localStorage.getItem(name).replace('false', 'Off').replace('true', 'On');
.getItem(name)
.replace("false", "Off")
.replace("true", "On");
return value.charAt(0).toUpperCase() + value.slice(1); return value.charAt(0).toUpperCase() + value.slice(1);
} }
@ -66,11 +55,11 @@ export default class WelcomeSections extends PureComponent {
Object.keys(data).forEach((setting) => { Object.keys(data).forEach((setting) => {
// language and theme already shown, the others are only used internally // language and theme already shown, the others are only used internally
if ( if (
setting === "language" || setting === 'language' ||
setting === "theme" || setting === 'theme' ||
setting === "firstRun" || setting === 'firstRun' ||
setting === "showWelcome" || setting === 'showWelcome' ||
setting === "showReminder" setting === 'showReminder'
) { ) {
return; return;
} }
@ -131,10 +120,8 @@ export default class WelcomeSections extends PureComponent {
render() { render() {
const intro = ( const intro = (
<> <>
<span className="mainTitle"> <span className="mainTitle">{this.getMessage('modals.welcome.sections.intro.title')}</span>
{this.getMessage("modals.welcome.sections.intro.title")} <p>{this.getMessage('modals.welcome.sections.intro.description')}</p>
</span>
<p>{this.getMessage("modals.welcome.sections.intro.description")}</p>
<h3 className="quicktip">#shareyourmue</h3> <h3 className="quicktip">#shareyourmue</h3>
<div className="examples"> <div className="examples">
<img <img
@ -149,10 +136,10 @@ export default class WelcomeSections extends PureComponent {
const chooseLanguage = ( const chooseLanguage = (
<> <>
<span className="mainTitle"> <span className="mainTitle">
{this.getMessage("modals.welcome.sections.language.title")} {this.getMessage('modals.welcome.sections.language.title')}
</span> </span>
<p> <p>
{this.getMessage("modals.welcome.sections.language.description")}{" "} {this.getMessage('modals.welcome.sections.language.description')}{' '}
<a <a
href={variables.constants.TRANSLATIONS_URL} href={variables.constants.TRANSLATIONS_URL}
className="resetLink" className="resetLink"
@ -169,48 +156,25 @@ export default class WelcomeSections extends PureComponent {
const theme = ( const theme = (
<> <>
<span className="mainTitle"> <span className="mainTitle">{this.getMessage('modals.welcome.sections.theme.title')}</span>
{this.getMessage("modals.welcome.sections.theme.title")} <p>{this.getMessage('modals.welcome.sections.theme.description')}</p>
</span>
<p>{this.getMessage("modals.welcome.sections.theme.description")}</p>
<div className="themesToggleArea"> <div className="themesToggleArea">
<div <div className={this.state.autoClass} onClick={() => this.changeTheme('auto')}>
className={this.state.autoClass}
onClick={() => this.changeTheme("auto")}
>
<MdAutoAwesome /> <MdAutoAwesome />
<span> <span>{this.getMessage('modals.main.settings.sections.appearance.theme.auto')}</span>
{this.getMessage(
"modals.main.settings.sections.appearance.theme.auto"
)}
</span>
</div> </div>
<div className="options"> <div className="options">
<div <div className={this.state.lightClass} onClick={() => this.changeTheme('light')}>
className={this.state.lightClass}
onClick={() => this.changeTheme("light")}
>
<MdLightMode /> <MdLightMode />
<span> <span>{this.getMessage('modals.main.settings.sections.appearance.theme.light')}</span>
{this.getMessage(
"modals.main.settings.sections.appearance.theme.light"
)}
</span>
</div> </div>
<div <div className={this.state.darkClass} onClick={() => this.changeTheme('dark')}>
className={this.state.darkClass}
onClick={() => this.changeTheme("dark")}
>
<MdDarkMode /> <MdDarkMode />
<span> <span>{this.getMessage('modals.main.settings.sections.appearance.theme.dark')}</span>
{this.getMessage(
"modals.main.settings.sections.appearance.theme.dark"
)}
</span>
</div> </div>
</div> </div>
<h3 className="quicktip">{this.getMessage("modals.welcome.tip")}</h3> <h3 className="quicktip">{this.getMessage('modals.welcome.tip')}</h3>
<p>{this.getMessage("modals.welcome.sections.theme.tip")}</p> <p>{this.getMessage('modals.welcome.sections.theme.tip')}</p>
</div> </div>
</> </>
); );
@ -218,16 +182,13 @@ export default class WelcomeSections extends PureComponent {
const settings = ( const settings = (
<> <>
<span className="mainTitle"> <span className="mainTitle">
{this.getMessage("modals.welcome.sections.settings.title")} {this.getMessage('modals.welcome.sections.settings.title')}
</span> </span>
<p>{this.getMessage("modals.welcome.sections.settings.description")}</p> <p>{this.getMessage('modals.welcome.sections.settings.description')}</p>
<button <button className="upload" onClick={() => document.getElementById('file-input').click()}>
className="upload"
onClick={() => document.getElementById("file-input").click()}
>
<MdCloudUpload /> <MdCloudUpload />
<br /> <br />
<span>{this.getMessage("modals.main.settings.buttons.import")}</span> <span>{this.getMessage('modals.main.settings.buttons.import')}</span>
</button> </button>
<FileUpload <FileUpload
id="file-input" id="file-input"
@ -235,58 +196,44 @@ export default class WelcomeSections extends PureComponent {
type="settings" type="settings"
loadFunction={(e) => this.importSettings(e)} loadFunction={(e) => this.importSettings(e)}
/> />
<h3 className="quicktip">{this.getMessage("modals.welcome.tip")}</h3> <h3 className="quicktip">{this.getMessage('modals.welcome.tip')}</h3>
<p>{this.getMessage("modals.welcome.sections.settings.tip")}</p> <p>{this.getMessage('modals.welcome.sections.settings.tip')}</p>
</> </>
); );
const privacy = ( const privacy = (
<> <>
<span className="mainTitle"> <span className="mainTitle">
{this.getMessage("modals.welcome.sections.privacy.title")} {this.getMessage('modals.welcome.sections.privacy.title')}
</span> </span>
<p>{this.getMessage("modals.welcome.sections.privacy.description")}</p> <p>{this.getMessage('modals.welcome.sections.privacy.description')}</p>
<Checkbox <Checkbox
name="offlineMode" name="offlineMode"
text={this.getMessage( text={this.getMessage('modals.main.settings.sections.advanced.offline_mode')}
"modals.main.settings.sections.advanced.offline_mode"
)}
element=".other" element=".other"
/> />
<p> <p>{this.getMessage('modals.welcome.sections.privacy.offline_mode_description')}</p>
{this.getMessage(
"modals.welcome.sections.privacy.offline_mode_description"
)}
</p>
<Checkbox <Checkbox
name="quicklinksddgProxy" name="quicklinksddgProxy"
text={ text={
this.getMessage( this.getMessage('modals.main.settings.sections.background.ddg_image_proxy') +
"modals.main.settings.sections.background.ddg_image_proxy" ' (' +
) + this.getMessage('modals.main.settings.sections.quicklinks.title') +
" (" + ')'
this.getMessage("modals.main.settings.sections.quicklinks.title") +
")"
} }
/> />
<Checkbox <Checkbox
name="ddgProxy" name="ddgProxy"
text={ text={
this.getMessage( this.getMessage('modals.main.settings.sections.background.ddg_image_proxy') +
"modals.main.settings.sections.background.ddg_image_proxy" ' (' +
) + this.getMessage('modals.main.settings.sections.background.title') +
" (" + ')'
this.getMessage("modals.main.settings.sections.background.title") +
")"
} }
/> />
<p> <p>{this.getMessage('modals.welcome.sections.privacy.ddg_proxy_description')}</p>
{this.getMessage(
"modals.welcome.sections.privacy.ddg_proxy_description"
)}
</p>
<h3 className="quicktip"> <h3 className="quicktip">
{this.getMessage("modals.welcome.sections.privacy.links.title")} {this.getMessage('modals.welcome.sections.privacy.links.title')}
</h3> </h3>
<a <a
className="privacy" className="privacy"
@ -294,59 +241,45 @@ export default class WelcomeSections extends PureComponent {
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
{this.getMessage( {this.getMessage('modals.welcome.sections.privacy.links.privacy_policy')}
"modals.welcome.sections.privacy.links.privacy_policy"
)}
</a> </a>
<br /> <br />
<br /> <br />
<a <a
className="privacy" className="privacy"
href={"https://github.com/" + variables.constants.ORG_NAME} href={'https://github.com/' + variables.constants.ORG_NAME}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
{this.getMessage("modals.welcome.sections.privacy.links.source_code")} {this.getMessage('modals.welcome.sections.privacy.links.source_code')}
</a> </a>
</> </>
); );
const final = ( const final = (
<> <>
<span className="mainTitle"> <span className="mainTitle">{this.getMessage('modals.welcome.sections.final.title')}</span>
{this.getMessage("modals.welcome.sections.final.title")} <p>{this.getMessage('modals.welcome.sections.final.description')}</p>
</span> <h3 className="quicktip">{this.getMessage('modals.welcome.sections.final.changes')}</h3>
<p>{this.getMessage("modals.welcome.sections.final.description")}</p> <p>{this.getMessage('modals.welcome.sections.final.changes_description')}</p>
<h3 className="quicktip">
{this.getMessage("modals.welcome.sections.final.changes")}
</h3>
<p>
{this.getMessage("modals.welcome.sections.final.changes_description")}
</p>
<div className="themesToggleArea"> <div className="themesToggleArea">
<div className="toggle" onClick={() => this.props.switchTab(1)}> <div className="toggle" onClick={() => this.props.switchTab(1)}>
<span> <span>
{this.getMessage("modals.main.settings.sections.language.title")}:{" "} {this.getMessage('modals.main.settings.sections.language.title')}:{' '}
{ {languages.find((i) => i.value === localStorage.getItem('language')).name}
languages.find(
(i) => i.value === localStorage.getItem("language")
).name
}
</span> </span>
</div> </div>
<div className="toggle" onClick={() => this.props.switchTab(3)}> <div className="toggle" onClick={() => this.props.switchTab(3)}>
<span> <span>
{this.getMessage( {this.getMessage('modals.main.settings.sections.appearance.theme.title')}:{' '}
"modals.main.settings.sections.appearance.theme.title" {this.getSetting('theme')}
)}
: {this.getSetting("theme")}
</span> </span>
</div> </div>
{this.state.importedSettings.length !== 0 ? ( {this.state.importedSettings.length !== 0 ? (
<div className="toggle" onClick={() => this.props.switchTab(2)}> <div className="toggle" onClick={() => this.props.switchTab(2)}>
{this.getMessage("modals.main.settings.sections.final.imported", { {this.getMessage('modals.main.settings.sections.final.imported', {
amount: this.state.importedSettings.length, amount: this.state.importedSettings.length,
})}{" "} })}{' '}
{this.state.importedSettings.length} {this.state.importedSettings.length}
</div> </div>
) : null} ) : null}

View File

@ -1,67 +1,64 @@
import { PureComponent, Fragment, Suspense, lazy } from "react"; import { PureComponent, Fragment, Suspense, lazy } from 'react';
import Clock from "./time/Clock"; import Clock from './time/Clock';
import Greeting from "./greeting/Greeting"; import Greeting from './greeting/Greeting';
import Quote from "./quote/Quote"; import Quote from './quote/Quote';
import Search from "./search/Search"; import Search from './search/Search';
import QuickLinks from "./quicklinks/QuickLinks"; import QuickLinks from './quicklinks/QuickLinks';
import Date from "./time/Date"; import Date from './time/Date';
import Message from "./message/Message"; import Message from './message/Message';
import Reminder from "./reminder/Reminder"; import Reminder from './reminder/Reminder';
import EventBus from "modules/helpers/eventbus"; import EventBus from 'modules/helpers/eventbus';
const Weather = lazy(() => import("./weather/Weather")); const Weather = lazy(() => import('./weather/Weather'));
const renderLoader = () => <></>; const renderLoader = () => <></>;
export default class Widgets extends PureComponent { export default class Widgets extends PureComponent {
online = localStorage.getItem("offlineMode") === "false"; online = localStorage.getItem('offlineMode') === 'false';
constructor() { constructor() {
super(); super();
this.state = { this.state = {
order: JSON.parse(localStorage.getItem("order")), order: JSON.parse(localStorage.getItem('order')),
welcome: localStorage.getItem("showWelcome"), welcome: localStorage.getItem('showWelcome'),
}; };
// widgets we can re-order // widgets we can re-order
this.widgets = { this.widgets = {
time: this.enabled("time") ? <Clock /> : null, time: this.enabled('time') ? <Clock /> : null,
greeting: this.enabled("greeting") ? <Greeting /> : null, greeting: this.enabled('greeting') ? <Greeting /> : null,
quote: this.enabled("quote") ? <Quote /> : null, quote: this.enabled('quote') ? <Quote /> : null,
date: this.enabled("date") ? <Date /> : null, date: this.enabled('date') ? <Date /> : null,
quicklinks: quicklinks: this.enabled('quicklinksenabled') && this.online ? <QuickLinks /> : null,
this.enabled("quicklinksenabled") && this.online ? ( message: this.enabled('message') ? <Message /> : null,
<QuickLinks /> reminder: this.enabled('reminder') ? <Reminder /> : null,
) : null,
message: this.enabled("message") ? <Message /> : null,
reminder: this.enabled("reminder") ? <Reminder /> : null,
}; };
} }
enabled(key) { enabled(key) {
return localStorage.getItem(key) === "true"; return localStorage.getItem(key) === 'true';
} }
componentDidMount() { componentDidMount() {
EventBus.on("refresh", (data) => { EventBus.on('refresh', (data) => {
if (data === "widgets") { if (data === 'widgets') {
this.setState({ this.setState({
order: JSON.parse(localStorage.getItem("order")), order: JSON.parse(localStorage.getItem('order')),
}); });
} }
if (data === "widgetsWelcome") { if (data === 'widgetsWelcome') {
this.setState({ this.setState({
welcome: localStorage.getItem("showWelcome"), welcome: localStorage.getItem('showWelcome'),
}); });
localStorage.setItem("showWelcome", true); localStorage.setItem('showWelcome', true);
window.onbeforeunload = () => { window.onbeforeunload = () => {
localStorage.clear(); localStorage.clear();
}; };
} }
if (data === "widgetsWelcomeDone") { if (data === 'widgetsWelcomeDone') {
this.setState({ this.setState({
welcome: localStorage.getItem("showWelcome"), welcome: localStorage.getItem('showWelcome'),
}); });
window.onbeforeunload = null; window.onbeforeunload = null;
} }
@ -70,7 +67,7 @@ export default class Widgets extends PureComponent {
render() { render() {
// don't show when welcome is there // don't show when welcome is there
if (this.state.welcome !== "false") { if (this.state.welcome !== 'false') {
return <div id="widgets"></div>; return <div id="widgets"></div>;
} }
@ -79,9 +76,7 @@ export default class Widgets extends PureComponent {
if (this.state.order) { if (this.state.order) {
this.state.order.forEach((element) => { this.state.order.forEach((element) => {
elements.push( elements.push(<Fragment key={element}>{this.widgets[element]}</Fragment>);
<Fragment key={element}>{this.widgets[element]}</Fragment>
);
}); });
} else { } else {
// prevent error // prevent error
@ -99,9 +94,9 @@ export default class Widgets extends PureComponent {
return ( return (
<div id="widgets"> <div id="widgets">
<Suspense fallback={renderLoader()}> <Suspense fallback={renderLoader()}>
{this.enabled("searchBar") ? <Search /> : null} {this.enabled('searchBar') ? <Search /> : null}
{elements} {elements}
{this.enabled("weatherEnabled") && this.online ? <Weather /> : null} {this.enabled('weatherEnabled') && this.online ? <Weather /> : null}
</Suspense> </Suspense>
</div> </div>
); );

View File

@ -50,6 +50,7 @@
} }
} }
.photoInformation-content { .photoInformation-content {
padding: 20px;
padding-left: 0; padding-left: 0;
} }
.map-concept { .map-concept {
@ -183,13 +184,14 @@
font-size: 0.8em; font-size: 0.8em;
font-weight: 300; font-weight: 300;
z-index: 99; z-index: 99;
padding: 20px;
display: flex; display: flex;
flex-flow: row; flex-flow: row;
align-items: center; align-items: center;
transition: 0.8s cubic-bezier(0.075, 0.82, 0.165, 1); transition: 0.8s cubic-bezier(0.075, 0.82, 0.165, 1);
width: 380px; width: 300px;
padding: 10px;
&:hover { &:hover {
padding: 20px;
height: auto; height: auto;
align-items: flex-start; align-items: flex-start;
flex-flow: column; flex-flow: column;
@ -240,15 +242,15 @@
} }
.map-concept { .map-concept {
@extend %basic; @extend %basic;
height: 80px; height: 50px;
width: 80px; width: 50px;
border-radius: 12px; border-radius: 12px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border: none !important; border: none !important;
svg { svg {
font-size: 25px; font-size: 24px;
} }
img { img {
width: 100%; width: 100%;
@ -281,7 +283,7 @@
.photoInformation-content { .photoInformation-content {
display: flex; display: flex;
flex-flow: column; flex-flow: column;
padding: 20px; padding-left: 20px;
a { a {
color: #5352ed; color: #5352ed;
text-decoration: none; text-decoration: none;

View File

@ -89,14 +89,16 @@ export default class Navbar extends PureComponent {
linkText={'Learn more'} linkText={'Learn more'}
> >
</InfoTooltip>*/} </InfoTooltip>*/}
<Tooltip <Tooltip
title={variables.language.getMessage( title={variables.language.getMessage(
variables.languagecode, variables.languagecode,
'modals.main.navbar.settings', 'modals.main.navbar.settings',
)} )}
><button onClick={() => this.props.openModal('mainModal')}> >
<MdSettings className="settings-icon topicons" /> <button onClick={() => this.props.openModal('mainModal')}>
</button></Tooltip> <MdSettings className="settings-icon topicons" />
</button>
</Tooltip>
</div> </div>
{/*<div className="notification"> {/*<div className="notification">
<span className="title">New Update</span> <span className="title">New Update</span>

View File

@ -57,7 +57,6 @@
} }
} }
.flexNotes { .flexNotes {
display: flex; display: flex;
flex-flow: column; flex-flow: column;

View File

@ -61,4 +61,3 @@
cursor: not-allowed; cursor: not-allowed;
} }
} }

View File

@ -30,7 +30,6 @@
border-radius: 12px; border-radius: 12px;
} }
::placeholder { ::placeholder {
color: #636e72; color: #636e72;
opacity: 1; opacity: 1;

View File

@ -63,7 +63,7 @@ export default class Quote extends PureComponent {
copy: localStorage.getItem('copyButton') === 'false' ? null : this.buttons.copy, copy: localStorage.getItem('copyButton') === 'false' ? null : this.buttons.copy,
quoteLanguage: '', quoteLanguage: '',
type: localStorage.getItem('quoteType') || 'api', type: localStorage.getItem('quoteType') || 'api',
shareModal: false shareModal: false,
}; };
this.quote = createRef(); this.quote = createRef();
this.quotediv = createRef(); this.quotediv = createRef();
@ -398,7 +398,7 @@ export default class Quote extends PureComponent {
<span className="quote" ref={this.quote}> <span className="quote" ref={this.quote}>
{this.state.quote} {this.state.quote}
</span> </span>
{localStorage.getItem('widgetStyle') === 'legacy' ? ( {(localStorage.getItem('widgetStyle') === 'legacy') ? (
<> <>
<div> <div>
<h1 className="quoteauthor" ref={this.quoteauthor}> <h1 className="quoteauthor" ref={this.quoteauthor}>
@ -417,38 +417,42 @@ export default class Quote extends PureComponent {
</div> </div>
</> </>
) : ( ) : (
<div className="author-holder"> <>
<div className="author"> {this.state.author !== '' ? (
<div <div className="author-holder">
className="author-img" <div className="author">
style={{ backgroundImage: `url(${this.state.authorimg})` }} <div
> className="author-img"
{this.state.authorimg === undefined || this.state.authorimg ? '' : <MdPerson />} style={{ backgroundImage: `url(${this.state.authorimg})` }}
>
{this.state.authorimg === undefined || this.state.authorimg ? '' : <MdPerson />}
</div>
<div className="author-content" ref={this.quoteauthor}>
<span className="title">{this.state.author}</span>
{this.state.authorOccupation !== 'Unknown' ? (
<span className="subtitle">{this.state.authorOccupation}</span>
) : null}
<span className="author-license">{this.state.authorimglicense}</span>
</div>
<div className="quote-buttons">
{this.state.authorOccupation !== 'Unknown' ? (
<Tooltip title="Open">
<a
href={this.state.authorlink}
className="quoteAuthorLink"
target="_blank"
rel="noopener noreferrer"
>
<MdOpenInNew />
</a>{' '}
</Tooltip>
) : null}
{this.state.copy} {this.state.share} {this.state.favourited}
</div>
</div>
</div> </div>
<div className="author-content" ref={this.quoteauthor}> ) : <div ref={this.quoteauthor}></div> }
<span className="title">{this.state.author}</span> </>
{this.state.authorOccupation !== 'Unknown' ? (
<span className="subtitle">{this.state.authorOccupation}</span>
) : null}
<span className="author-license">{this.state.authorimglicense}</span>
</div>
<div className="quote-buttons">
{this.state.authorOccupation !== 'Unknown' ? (
<Tooltip title="Open">
<a
href={this.state.authorlink}
className="quoteAuthorLink"
target="_blank"
rel="noopener noreferrer"
>
<MdOpenInNew />
</a>{' '}
</Tooltip>
) : null}
{this.state.copy} {this.state.share} {this.state.favourited}
</div>
</div>
</div>
)} )}
{/*variables.keybinds.favouriteQuote && variables.keybinds.favouriteQuote !== '' ? <Hotkeys keyName={variables.keybinds.favouriteQuote} onKeyDown={() => this.favourite()} /> : null*/} {/*variables.keybinds.favouriteQuote && variables.keybinds.favouriteQuote !== '' ? <Hotkeys keyName={variables.keybinds.favouriteQuote} onKeyDown={() => this.favourite()} /> : null*/}
{/*variables.keybinds.tweetQuote && variables.keybinds.tweetQuote !== '' ? <Hotkeys keyName={variables.keybinds.tweetQuote} onKeyDown={() => this.tweetQuote()} /> : null*/} {/*variables.keybinds.tweetQuote && variables.keybinds.tweetQuote !== '' ? <Hotkeys keyName={variables.keybinds.tweetQuote} onKeyDown={() => this.tweetQuote()} /> : null*/}

View File

@ -93,6 +93,16 @@ h1.quoteauthor {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-flow: column; flex-flow: column;
animation: fadeIn 1s;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
} }
.quote-buttons { .quote-buttons {
@ -110,6 +120,7 @@ h1.quoteauthor {
} }
.quotediv { .quotediv {
animation: fadeIn 1s;
width: 40vw; width: 40vw;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -5,21 +5,26 @@ import './reminder.scss';
import { MdClose, MdSnooze, MdWork } from 'react-icons/md'; import { MdClose, MdSnooze, MdWork } from 'react-icons/md';
export default class Reminder extends React.PureComponent { export default class Reminder extends React.PureComponent {
render() { render() {
return ( return (
<div className='reminder'> <div className="reminder">
<div className='identifier' style={{ backgroundColor: localStorage.getItem('reminderColour') || 'orange' }}> <div
<MdWork /> className="identifier"
</div> style={{
<div className='content'> backgroundColor: localStorage.getItem('reminderColour') || 'orange',
<span className='title'>Reminder</span> }}
<span className='subtitle'>Time</span> >
</div> <MdWork />
<div className='icons'> </div>
<MdClose /> <div className="content">
<MdSnooze /> <span className="title">Reminder</span>
</div> <span className="subtitle">Time</span>
</div> </div>
) <div className="icons">
} <MdClose />
} <MdSnooze />
</div>
</div>
);
}
}

View File

@ -14,4 +14,3 @@
"query": "&query=" "query": "&query="
} }
] ]

View File

@ -1,11 +1,11 @@
import { PureComponent, Suspense, lazy } from "react"; import { PureComponent, Suspense, lazy } from 'react';
import { convertTimezone } from "modules/helpers/date"; import { convertTimezone } from 'modules/helpers/date';
import EventBus from "modules/helpers/eventbus"; import EventBus from 'modules/helpers/eventbus';
import "./clock.scss"; import './clock.scss';
const Analog = lazy(() => import("react-clock")); const Analog = lazy(() => import('react-clock'));
const renderLoader = () => <></>; const renderLoader = () => <></>;
export default class Clock extends PureComponent { export default class Clock extends PureComponent {
@ -14,34 +14,34 @@ export default class Clock extends PureComponent {
this.timer = undefined; this.timer = undefined;
this.state = { this.state = {
time: "", time: '',
ampm: "", ampm: '',
}; };
} }
startTime( startTime(
time = localStorage.getItem("seconds") === "true" || time = localStorage.getItem('seconds') === 'true' ||
localStorage.getItem("timeType") === "analogue" localStorage.getItem('timeType') === 'analogue'
? 1000 - (Date.now() % 1000) ? 1000 - (Date.now() % 1000)
: 60000 - (Date.now() % 60000) : 60000 - (Date.now() % 60000),
) { ) {
this.timer = setTimeout(() => { this.timer = setTimeout(() => {
let now = new Date(); let now = new Date();
const timezone = localStorage.getItem("timezone"); const timezone = localStorage.getItem('timezone');
if (timezone && timezone !== "auto") { if (timezone && timezone !== 'auto') {
now = convertTimezone(now, timezone); now = convertTimezone(now, timezone);
} }
switch (localStorage.getItem("timeType")) { switch (localStorage.getItem('timeType')) {
case "percentageComplete": case 'percentageComplete':
this.setState({ this.setState({
time: (now.getHours() / 24).toFixed(2).replace("0.", "") + "%", time: (now.getHours() / 24).toFixed(2).replace('0.', '') + '%',
ampm: "", ampm: '',
}); });
break; break;
case "analogue": case 'analogue':
// load analog clock css // load analog clock css
require("react-clock/dist/Clock.css"); require('react-clock/dist/Clock.css');
this.setState({ this.setState({
time: now, time: now,
@ -50,27 +50,25 @@ export default class Clock extends PureComponent {
default: default:
// Default clock // Default clock
let time, let time,
sec = ""; sec = '';
const zero = localStorage.getItem("zero"); const zero = localStorage.getItem('zero');
if (localStorage.getItem("seconds") === "true") { if (localStorage.getItem('seconds') === 'true') {
sec = `:${("00" + now.getSeconds()).slice(-2)}`; sec = `:${('00' + now.getSeconds()).slice(-2)}`;
} }
if (localStorage.getItem("timeformat") === "twentyfourhour") { if (localStorage.getItem('timeformat') === 'twentyfourhour') {
if (zero === "false") { if (zero === 'false') {
time = `${now.getHours()}:${("00" + now.getMinutes()).slice( time = `${now.getHours()}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
-2
)}${sec}`;
} else { } else {
time = `${("00" + now.getHours()).slice(-2)}:${( time = `${('00' + now.getHours()).slice(-2)}:${('00' + now.getMinutes()).slice(
"00" + now.getMinutes() -2,
).slice(-2)}${sec}`; )}${sec}`;
} }
this.setState({ this.setState({
time, time,
ampm: "", ampm: '',
}); });
} else { } else {
// 12 hour // 12 hour
@ -82,17 +80,15 @@ export default class Clock extends PureComponent {
hours = 12; hours = 12;
} }
if (zero === "false") { if (zero === 'false') {
time = `${hours}:${("00" + now.getMinutes()).slice(-2)}${sec}`; time = `${hours}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
} else { } else {
time = `${("00" + hours).slice(-2)}:${( time = `${('00' + hours).slice(-2)}:${('00' + now.getMinutes()).slice(-2)}${sec}`;
"00" + now.getMinutes()
).slice(-2)}${sec}`;
} }
this.setState({ this.setState({
time, time,
ampm: now.getHours() > 11 ? "PM" : "AM", ampm: now.getHours() > 11 ? 'PM' : 'AM',
}); });
} }
break; break;
@ -103,27 +99,27 @@ export default class Clock extends PureComponent {
} }
componentDidMount() { componentDidMount() {
EventBus.on("refresh", (data) => { EventBus.on('refresh', (data) => {
if (data === "clock" || data === "timezone") { if (data === 'clock' || data === 'timezone') {
const element = document.querySelector(".clock-container"); const element = document.querySelector('.clock-container');
if (localStorage.getItem("time") === "false") { if (localStorage.getItem('time') === 'false') {
return (element.style.display = "none"); return (element.style.display = 'none');
} }
this.timer = null; this.timer = null;
this.startTime(0); this.startTime(0);
element.style.display = "block"; element.style.display = 'block';
element.style.fontSize = `${ element.style.fontSize = `${
4 * Number((localStorage.getItem("zoomClock") || 100) / 100) 4 * Number((localStorage.getItem('zoomClock') || 100) / 100)
}em`; }em`;
} }
}); });
if (localStorage.getItem("timeType") !== "analogue") { if (localStorage.getItem('timeType') !== 'analogue') {
document.querySelector(".clock-container").style.fontSize = `${ document.querySelector('.clock-container').style.fontSize = `${
4 * Number((localStorage.getItem("zoomClock") || 100) / 100) 4 * Number((localStorage.getItem('zoomClock') || 100) / 100)
}em`; }em`;
} }
@ -131,7 +127,7 @@ export default class Clock extends PureComponent {
} }
componentWillUnmount() { componentWillUnmount() {
EventBus.off("refresh"); EventBus.off('refresh');
} }
render() { render() {
@ -143,21 +139,21 @@ export default class Clock extends PureComponent {
); );
const enabled = (setting) => { const enabled = (setting) => {
return localStorage.getItem(setting) === "true"; return localStorage.getItem(setting) === 'true';
}; };
if (localStorage.getItem("timeType") === "analogue") { if (localStorage.getItem('timeType') === 'analogue') {
clockHTML = ( clockHTML = (
<Suspense fallback={renderLoader()}> <Suspense fallback={renderLoader()}>
<div className="clockBackground"> <div className="clockBackground">
<Analog <Analog
className="analogclock clock-container" className="analogclock clock-container"
value={this.state.time} value={this.state.time}
renderMinuteMarks={enabled("minuteMarks")} renderMinuteMarks={enabled('minuteMarks')}
renderHourMarks={enabled("hourMarks")} renderHourMarks={enabled('hourMarks')}
renderSecondHand={enabled("secondHand")} renderSecondHand={enabled('secondHand')}
renderMinuteHand={enabled("minuteHand")} renderMinuteHand={enabled('minuteHand')}
renderHourHand={enabled("hourHand")} renderHourHand={enabled('hourHand')}
/> />
</div> </div>
</Suspense> </Suspense>

View File

@ -1,16 +1,16 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent, createRef } from "react"; import { PureComponent, createRef } from 'react';
import { nth, convertTimezone } from "modules/helpers/date"; import { nth, convertTimezone } from 'modules/helpers/date';
import EventBus from "modules/helpers/eventbus"; import EventBus from 'modules/helpers/eventbus';
import "./date.scss"; import './date.scss';
export default class DateWidget extends PureComponent { export default class DateWidget extends PureComponent {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
date: "", date: '',
weekNumber: null, weekNumber: null,
}; };
this.date = createRef(); this.date = createRef();
@ -29,21 +29,20 @@ export default class DateWidget extends PureComponent {
} }
this.setState({ this.setState({
weekNumber: `${variables.language.getMessage( weekNumber: `${variables.language.getMessage(variables.languagecode, 'widgets.date.week')} ${
variables.languagecode, 1 + Math.ceil((firstThursday - dateToday) / 604800000)
"widgets.date.week" }`,
)} ${1 + Math.ceil((firstThursday - dateToday) / 604800000)}`,
}); });
} }
getDate() { getDate() {
let date = new Date(); let date = new Date();
const timezone = localStorage.getItem("timezone"); const timezone = localStorage.getItem('timezone');
if (timezone && timezone !== "auto") { if (timezone && timezone !== 'auto') {
date = convertTimezone(date, timezone); date = convertTimezone(date, timezone);
} }
if (localStorage.getItem("weeknumber") === "true") { if (localStorage.getItem('weeknumber') === 'true') {
this.getWeekNumber(date); this.getWeekNumber(date);
} else if (this.state.weekNumber !== null) { } else if (this.state.weekNumber !== null) {
this.setState({ this.setState({
@ -51,23 +50,23 @@ export default class DateWidget extends PureComponent {
}); });
} }
if (localStorage.getItem("dateType") === "short") { if (localStorage.getItem('dateType') === 'short') {
const dateDay = date.getDate(); const dateDay = date.getDate();
const dateMonth = date.getMonth() + 1; const dateMonth = date.getMonth() + 1;
const dateYear = date.getFullYear(); const dateYear = date.getFullYear();
const zero = localStorage.getItem("datezero") === "true"; const zero = localStorage.getItem('datezero') === 'true';
let day = zero ? ("00" + dateDay).slice(-2) : dateDay; let day = zero ? ('00' + dateDay).slice(-2) : dateDay;
let month = zero ? ("00" + dateMonth).slice(-2) : dateMonth; let month = zero ? ('00' + dateMonth).slice(-2) : dateMonth;
let year = dateYear; let year = dateYear;
switch (localStorage.getItem("dateFormat")) { switch (localStorage.getItem('dateFormat')) {
case "MDY": case 'MDY':
day = dateMonth; day = dateMonth;
month = dateDay; month = dateDay;
break; break;
case "YMD": case 'YMD':
day = dateYear; day = dateYear;
year = dateDay; year = dateDay;
break; break;
@ -77,17 +76,17 @@ export default class DateWidget extends PureComponent {
} }
let format; let format;
switch (localStorage.getItem("shortFormat")) { switch (localStorage.getItem('shortFormat')) {
case "dots": case 'dots':
format = `${day}.${month}.${year}`; format = `${day}.${month}.${year}`;
break; break;
case "dash": case 'dash':
format = `${day}-${month}-${year}`; format = `${day}-${month}-${year}`;
break; break;
case "gaps": case 'gaps':
format = `${day} - ${month} - ${year}`; format = `${day} - ${month} - ${year}`;
break; break;
case "slashes": case 'slashes':
format = `${day}/${month}/${year}`; format = `${day}/${month}/${year}`;
break; break;
default: default:
@ -99,31 +98,29 @@ export default class DateWidget extends PureComponent {
}); });
} else { } else {
// Long date // Long date
const lang = variables.languagecode.split("_")[0]; const lang = variables.languagecode.split('_')[0];
const datenth = const datenth =
localStorage.getItem("datenth") === "true" localStorage.getItem('datenth') === 'true' ? nth(date.getDate()) : date.getDate();
? nth(date.getDate())
: date.getDate();
const dateDay = const dateDay =
localStorage.getItem("dayofweek") === "true" localStorage.getItem('dayofweek') === 'true'
? date.toLocaleDateString(lang, { weekday: "long" }) ? date.toLocaleDateString(lang, { weekday: 'long' })
: ""; : '';
const dateMonth = date.toLocaleDateString(lang, { month: "long" }); const dateMonth = date.toLocaleDateString(lang, { month: 'long' });
const dateYear = date.getFullYear(); const dateYear = date.getFullYear();
let day = dateDay + " " + datenth; let day = dateDay + ' ' + datenth;
let month = dateMonth; let month = dateMonth;
let year = dateYear; let year = dateYear;
switch (localStorage.getItem("longFormat")) { switch (localStorage.getItem('longFormat')) {
case "MDY": case 'MDY':
day = dateMonth; day = dateMonth;
month = dateDay + " " + datenth;; month = dateDay + ' ' + datenth;
break; break;
case "YMD": case 'YMD':
day = dateYear; day = dateYear;
year = dateDay + " " + datenth;; year = dateDay + ' ' + datenth;
break; break;
// DMY // DMY
default: default:
@ -137,28 +134,28 @@ export default class DateWidget extends PureComponent {
} }
componentDidMount() { componentDidMount() {
EventBus.on("refresh", (data) => { EventBus.on('refresh', (data) => {
if (data === "date" || data === "timezone") { if (data === 'date' || data === 'timezone') {
if (localStorage.getItem("date") === "false") { if (localStorage.getItem('date') === 'false') {
return (this.date.current.style.display = "none"); return (this.date.current.style.display = 'none');
} }
this.date.current.style.display = "block"; this.date.current.style.display = 'block';
this.date.current.style.fontSize = `${Number( this.date.current.style.fontSize = `${Number(
(localStorage.getItem("zoomDate") || 100) / 100 (localStorage.getItem('zoomDate') || 100) / 100,
)}em`; )}em`;
this.getDate(); this.getDate();
} }
}); });
this.date.current.style.fontSize = `${Number( this.date.current.style.fontSize = `${Number(
(localStorage.getItem("zoomDate") || 100) / 100 (localStorage.getItem('zoomDate') || 100) / 100,
)}em`; )}em`;
this.getDate(); this.getDate();
} }
componentWillUnmount() { componentWillUnmount() {
EventBus.off("refresh"); EventBus.off('refresh');
} }
render() { render() {

View File

@ -1,43 +1,41 @@
import variables from "modules/variables"; import variables from 'modules/variables';
import { PureComponent } from "react"; import { PureComponent } from 'react';
import { WiHumidity, WiWindy, WiBarometer, WiCloud } from "react-icons/wi"; import { WiHumidity, WiWindy, WiBarometer, WiCloud } from 'react-icons/wi';
import { MdDisabledVisible } from "react-icons/md"; import { MdDisabledVisible } from 'react-icons/md';
import WeatherIcon from "./WeatherIcon"; import WeatherIcon from './WeatherIcon';
import WindDirectionIcon from "./WindDirectionIcon"; import WindDirectionIcon from './WindDirectionIcon';
import EventBus from "modules/helpers/eventbus"; import EventBus from 'modules/helpers/eventbus';
import "./weather.scss"; import './weather.scss';
export default class Weather extends PureComponent { export default class Weather extends PureComponent {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
location: localStorage.getItem("location") || "London", location: localStorage.getItem('location') || 'London',
icon: "", icon: '',
temp_text: "", temp_text: '',
weather: { weather: {
temp: "", temp: '',
description: "", description: '',
temp_min: "", temp_min: '',
temp_max: "", temp_max: '',
temp_feels_like: "", temp_feels_like: '',
humidity: "", humidity: '',
wind_speed: "", wind_speed: '',
wind_degrees: "", wind_degrees: '',
cloudiness: "", cloudiness: '',
visibility: "", visibility: '',
pressure: "", pressure: '',
}, },
}; };
} }
async getWeather() { async getWeather() {
const zoomWeather = `${Number( const zoomWeather = `${Number((localStorage.getItem('zoomWeather') || 100) / 100)}em`;
(localStorage.getItem("zoomWeather") || 100) / 100 document.querySelector('.weather').style.fontSize = zoomWeather;
)}em`;
document.querySelector(".weather").style.fontSize = zoomWeather;
let data = { let data = {
weather: [ weather: [
@ -68,16 +66,16 @@ export default class Weather extends PureComponent {
data = await ( data = await (
await fetch( await fetch(
variables.constants.PROXY_URL + variables.constants.PROXY_URL +
`/weather/current?city=${this.state.location}&lang=${variables.languagecode}` `/weather/current?city=${this.state.location}&lang=${variables.languagecode}`,
) )
).json(); ).json();
} }
if (data.cod === "404") { if (data.cod === '404') {
return this.setState({ return this.setState({
location: variables.language.getMessage( location: variables.language.getMessage(
variables.languagecode, variables.languagecode,
"widgets.weather.not_found" 'widgets.weather.not_found',
), ),
}); });
} }
@ -86,22 +84,22 @@ export default class Weather extends PureComponent {
let temp_min = data.main.temp_min; let temp_min = data.main.temp_min;
let temp_max = data.main.temp_max; let temp_max = data.main.temp_max;
let temp_feels_like = data.main.temp_feels_like; let temp_feels_like = data.main.temp_feels_like;
let temp_text = "K"; let temp_text = 'K';
switch (localStorage.getItem("tempformat")) { switch (localStorage.getItem('tempformat')) {
case "celsius": case 'celsius':
temp -= 273.15; temp -= 273.15;
temp_min -= 273.15; temp_min -= 273.15;
temp_max -= 273.15; temp_max -= 273.15;
temp_feels_like -= 273.15; temp_feels_like -= 273.15;
temp_text = "°C"; temp_text = '°C';
break; break;
case "fahrenheit": case 'fahrenheit':
temp = (temp - 273.15) * 1.8 + 32; temp = (temp - 273.15) * 1.8 + 32;
temp_min = (temp_min - 273.15) * 1.8 + 32; temp_min = (temp_min - 273.15) * 1.8 + 32;
temp_max = (temp_max - 273.15) * 1.8 + 32; temp_max = (temp_max - 273.15) * 1.8 + 32;
temp_feels_like = (temp_feels_like - 273.15) * 1.8 + 32; temp_feels_like = (temp_feels_like - 273.15) * 1.8 + 32;
temp_text = "°F"; temp_text = '°F';
break; break;
// kelvin // kelvin
default: default:
@ -130,12 +128,12 @@ export default class Weather extends PureComponent {
}, },
}); });
document.querySelector(".weather svg").style.fontSize = zoomWeather; document.querySelector('.weather svg').style.fontSize = zoomWeather;
} }
componentDidMount() { componentDidMount() {
EventBus.on("refresh", (data) => { EventBus.on('refresh', (data) => {
if (data === "weather") { if (data === 'weather') {
this.getWeather(); this.getWeather();
} }
}); });
@ -144,17 +142,17 @@ export default class Weather extends PureComponent {
} }
componentWillUnmount() { componentWillUnmount() {
EventBus.off("refresh"); EventBus.off('refresh');
} }
render() { render() {
const enabled = (setting) => { const enabled = (setting) => {
return localStorage.getItem(setting) === "true"; return localStorage.getItem(setting) === 'true';
}; };
if ( if (
this.state.location === this.state.location ===
variables.language.getMessage(variables.languagecode, "weather.not_found") variables.language.getMessage(variables.languagecode, 'weather.not_found')
) { ) {
return ( return (
<div className="weather"> <div className="weather">
@ -164,33 +162,24 @@ export default class Weather extends PureComponent {
} }
const minmax = () => { const minmax = () => {
const mintemp = enabled("mintemp"); const mintemp = enabled('mintemp');
const maxtemp = enabled("maxtemp"); const maxtemp = enabled('maxtemp');
if (!mintemp && !maxtemp) { if (!mintemp && !maxtemp) {
return null; return null;
} else if (mintemp && !maxtemp) { } else if (mintemp && !maxtemp) {
return ( return (
<span className="subtitle"> <span className="subtitle">{this.state.weather.temp_min + this.state.temp_text}</span>
{this.state.weather.temp_min + this.state.temp_text}
</span>
); );
} else if (maxtemp && !mintemp) { } else if (maxtemp && !mintemp) {
return ( return (
<span className="subtitle"> <span className="subtitle">{this.state.weather.temp_max + this.state.temp_text}</span>
{this.state.weather.temp_max + this.state.temp_text}
</span>
); );
} else { } else {
return ( return (
<> <>
<span className="subtitle"> <span className="subtitle">{this.state.weather.temp_min + this.state.temp_text}</span>{' '}
{this.state.weather.temp_min + this.state.temp_text} <span className="subtitle"> {this.state.weather.temp_max + this.state.temp_text}</span>
</span>{" "}
<span className="subtitle">
{" "}
{this.state.weather.temp_max + this.state.temp_text}
</span>
</> </>
); );
} }
@ -208,15 +197,10 @@ export default class Weather extends PureComponent {
</div> </div>
<div className="extra-info"> <div className="extra-info">
{/*{enabled('humidity') ? <span><WiHumidity/>{this.state.weather.humidity}%</span> : null}*/} {/*{enabled('humidity') ? <span><WiHumidity/>{this.state.weather.humidity}%</span> : null}*/}
{enabled("feelsliketemp") ? ( {enabled('feelsliketemp') ? (
<span> <span>Feels like {this.state.weather.temp_feels_like + this.state.temp_text}</span>
Feels like{" "}
{this.state.weather.temp_feels_like + this.state.temp_text}
</span>
) : null}
{enabled("showlocation") ? (
<span className="loc">{this.state.location}</span>
) : null} ) : null}
{enabled('showlocation') ? <span className="loc">{this.state.location}</span> : null}
</div> </div>
<div className="expanded-info"> <div className="expanded-info">
<span className="subtitle">Upcoming Forecast</span> <span className="subtitle">Upcoming Forecast</span>
@ -238,18 +222,18 @@ export default class Weather extends PureComponent {
</div> </div>
</div> </div>
<span className="subtitle">Extra Information</span> <span className="subtitle">Extra Information</span>
{enabled("cloudiness") ? ( {enabled('cloudiness') ? (
<span> <span>
<WiCloud className="weatherIcon" /> <WiCloud className="weatherIcon" />
{this.state.weather.cloudiness}% {this.state.weather.cloudiness}%
</span> </span>
) : null} ) : null}
{enabled("windspeed") ? ( {enabled('windspeed') ? (
<span> <span>
<WiWindy className="weatherIcon" /> <WiWindy className="weatherIcon" />
{this.state.weather.wind_speed} {this.state.weather.wind_speed}
<span className="minmax"> m/s</span>{" "} <span className="minmax"> m/s</span>{' '}
{enabled("windDirection") ? ( {enabled('windDirection') ? (
<div className="weatherIcon"> <div className="weatherIcon">
<WindDirectionIcon <WindDirectionIcon
className="weatherIcon" className="weatherIcon"
@ -259,14 +243,14 @@ export default class Weather extends PureComponent {
) : null} ) : null}
</span> </span>
) : null} ) : null}
{enabled("atmosphericpressure") ? ( {enabled('atmosphericpressure') ? (
<span> <span>
<WiBarometer className="weatherIcon" /> <WiBarometer className="weatherIcon" />
{this.state.weather.pressure} {this.state.weather.pressure}
<span className="minmax"> hPa</span> <span className="minmax"> hPa</span>
</span> </span>
) : null} ) : null}
{enabled("weatherdescription") ? ( {enabled('weatherdescription') ? (
<span> <span>
<div className="weatherIcon"> <div className="weatherIcon">
<WeatherIcon name={this.state.icon} /> <WeatherIcon name={this.state.icon} />
@ -274,16 +258,12 @@ export default class Weather extends PureComponent {
{this.state.weather.description} {this.state.weather.description}
</span> </span>
) : null} ) : null}
{enabled("visibility") ? ( {enabled('visibility') ? (
<span> <span>
<MdDisabledVisible style={{ padding: "3px" }} /> <MdDisabledVisible style={{ padding: '3px' }} />
{variables.language.getMessage( {variables.language.getMessage(variables.languagecode, 'widgets.weather.meters', {
variables.languagecode, amount: this.state.weather.visibility,
"widgets.weather.meters", })}
{
amount: this.state.weather.visibility,
}
)}
</span> </span>
) : null} ) : null}
</div> </div>

View File

@ -11,53 +11,53 @@ import {
WiThunderstorm, WiThunderstorm,
WiSnow, WiSnow,
WiFog, WiFog,
} from "react-icons/wi"; } from 'react-icons/wi';
export default function WeatherIcon({ name }) { export default function WeatherIcon({ name }) {
let icon; let icon;
// name is the openweathermap icon name, see https://openweathermap.org/weather-conditions // name is the openweathermap icon name, see https://openweathermap.org/weather-conditions
switch (name) { switch (name) {
case "01d": case '01d':
icon = <WiDaySunny />; icon = <WiDaySunny />;
break; break;
case "01n": case '01n':
icon = <WiNightClear />; icon = <WiNightClear />;
break; break;
case "02d": case '02d':
icon = <WiDayCloudy />; icon = <WiDayCloudy />;
break; break;
case "02n": case '02n':
icon = <WiNightCloudy />; icon = <WiNightCloudy />;
break; break;
case "03d": case '03d':
case "03n": case '03n':
icon = <WiCloud />; icon = <WiCloud />;
break; break;
case "04d": case '04d':
case "04n": case '04n':
icon = <WiCloudy />; icon = <WiCloudy />;
break; break;
case "09d": case '09d':
icon = <WiDayShowers />; icon = <WiDayShowers />;
break; break;
case "09n": case '09n':
icon = <WiNightShowers />; icon = <WiNightShowers />;
break; break;
case "10d": case '10d':
case "10n": case '10n':
icon = <WiRain />; icon = <WiRain />;
break; break;
case "11d": case '11d':
case "11n": case '11n':
icon = <WiThunderstorm />; icon = <WiThunderstorm />;
break; break;
case "13d": case '13d':
case "13n": case '13n':
icon = <WiSnow />; icon = <WiSnow />;
break; break;
case "50d": case '50d':
case "50n": case '50n':
icon = <WiFog />; icon = <WiFog />;
break; break;
default: default:

View File

@ -7,7 +7,7 @@ import {
WiDirectionUpLeft, WiDirectionUpLeft,
WiDirectionUpRight, WiDirectionUpRight,
WiDirectionUp, WiDirectionUp,
} from "react-icons/wi"; } from 'react-icons/wi';
// degrees are imported because of a potential bug, IDK what causes it, but now it is fixed // degrees are imported because of a potential bug, IDK what causes it, but now it is fixed
export default function WindDirectionIcon({ degrees }) { export default function WindDirectionIcon({ degrees }) {
@ -15,43 +15,41 @@ export default function WindDirectionIcon({ degrees }) {
// convert the number OpenWeatherMap gives us to the closest direction or something // convert the number OpenWeatherMap gives us to the closest direction or something
const directions = [ const directions = [
"North", 'North',
"North-West", 'North-West',
"West", 'West',
"South-West", 'South-West',
"South", 'South',
"South-East", 'South-East',
"East", 'East',
"North-East", 'North-East',
]; ];
const direction = const direction =
directions[ directions[Math.round(((degrees %= 360) < 0 ? degrees + 360 : degrees) / 45) % 8];
Math.round(((degrees %= 360) < 0 ? degrees + 360 : degrees) / 45) % 8
];
switch (direction) { switch (direction) {
case "North": case 'North':
icon = <WiDirectionUp />; icon = <WiDirectionUp />;
break; break;
case "North-West": case 'North-West':
icon = <WiDirectionUpLeft />; icon = <WiDirectionUpLeft />;
break; break;
case "West": case 'West':
icon = <WiDirectionLeft />; icon = <WiDirectionLeft />;
break; break;
case "South-West": case 'South-West':
icon = <WiDirectionDownLeft />; icon = <WiDirectionDownLeft />;
break; break;
case "South": case 'South':
icon = <WiDirectionDown />; icon = <WiDirectionDown />;
break; break;
case "South-East": case 'South-East':
icon = <WiDirectionDownRight />; icon = <WiDirectionDownRight />;
break; break;
case "East": case 'East':
icon = <WiDirectionRight />; icon = <WiDirectionRight />;
break; break;
case "North-East": case 'North-East':
icon = <WiDirectionUpRight />; icon = <WiDirectionUpRight />;
break; break;
default: default:

View File

@ -31,7 +31,7 @@ variables.language = new I18n(variables.languagecode, {
no: require('./translations/no.json'), no: require('./translations/no.json'),
ru: require('./translations/ru.json'), ru: require('./translations/ru.json'),
zh_CN: require('./translations/zh_CN.json'), zh_CN: require('./translations/zh_CN.json'),
id_ID: require('./translations/id_ID.json') id_ID: require('./translations/id_ID.json'),
}); });
// set html language tag // set html language tag
@ -50,4 +50,4 @@ if (localStorage.getItem('stats') === 'true') {
const container = document.getElementById('root'); const container = document.getElementById('root');
const root = createRoot(container); const root = createRoot(container);
root.render(<App/>); root.render(<App />);

View File

@ -13,8 +13,10 @@ export const WEBSITE_URL = 'https://muetab.com';
export const PRIVACY_URL = 'https://muetab.com/privacy'; export const PRIVACY_URL = 'https://muetab.com/privacy';
export const BLOG_POST = 'https://blog.muetab.com/posts/version-6-0'; export const BLOG_POST = 'https://blog.muetab.com/posts/version-6-0';
export const TRANSLATIONS_URL = 'https://docs.muetab.com/translations/'; export const TRANSLATIONS_URL = 'https://docs.muetab.com/translations/';
export const REPORT_ITEM = 'https://github.com/mue/marketplace/issues/new?assignees=&labels=item+report&template=item-report.md&title=%5BItem+Report%5D+'; export const REPORT_ITEM =
export const BUG_REPORT = 'https://github.com/mue/mue/issues/new?assignees=&labels=issue+report&template=bug-report.md&title=%5BBug%5D+'; 'https://github.com/mue/marketplace/issues/new?assignees=&labels=item+report&template=item-report.md&title=%5BItem+Report%5D+';
export const BUG_REPORT =
'https://github.com/mue/mue/issues/new?assignees=&labels=issue+report&template=bug-report.md&title=%5BBug%5D+';
export const DONATE_LINK = 'https://muetab.com/donate'; export const DONATE_LINK = 'https://muetab.com/donate';
// Mue Info // Mue Info

View File

@ -21,9 +21,9 @@ export default function rgbToHSv({ red, green, blue }) {
if (rabs === v) { if (rabs === v) {
h = bb - gg; h = bb - gg;
} else if (gabs === v) { } else if (gabs === v) {
h = (1 / 3) + rr - bb; h = 1 / 3 + rr - bb;
} else if (babs === v) { } else if (babs === v) {
h = (2 / 3) + gg - rr; h = 2 / 3 + gg - rr;
} }
if (h < 0) { if (h < 0) {

View File

@ -1,5 +1,5 @@
const isValidRGBValue = (value) => { const isValidRGBValue = (value) => {
return (typeof (value) === 'number' && Number.isNaN(value) === false && value >= 0 && value <= 255); return typeof value === 'number' && Number.isNaN(value) === false && value >= 0 && value <= 255;
}; };
export default function setRGBA(red, green, blue, alpha) { export default function setRGBA(red, green, blue, alpha) {

View File

@ -1,6 +1,11 @@
// since there is so much code in the component, we have moved it to a separate file // since there is so much code in the component, we have moved it to a separate file
export function videoCheck(url) { export function videoCheck(url) {
return url.startsWith('data:video/') || url.endsWith('.mp4') || url.endsWith('.webm') || url.endsWith('.ogg'); return (
url.startsWith('data:video/') ||
url.endsWith('.mp4') ||
url.endsWith('.webm') ||
url.endsWith('.ogg')
);
} }
export function offlineBackground() { export function offlineBackground() {
@ -10,16 +15,17 @@ export function offlineBackground() {
const photographers = Object.keys(offlineImages); const photographers = Object.keys(offlineImages);
const photographer = photographers[Math.floor(Math.random() * photographers.length)]; const photographer = photographers[Math.floor(Math.random() * photographers.length)];
const randomImage = offlineImages[photographer].photo[ const randomImage =
Math.floor(Math.random() * offlineImages[photographer].photo.length) offlineImages[photographer].photo[
]; Math.floor(Math.random() * offlineImages[photographer].photo.length)
];
const object = { const object = {
url: `./offline-images/${randomImage}.webp`, url: `./offline-images/${randomImage}.webp`,
photoInfo: { photoInfo: {
offline: true, offline: true,
credit: photographer credit: photographer,
} },
}; };
localStorage.setItem('currentBackground', JSON.stringify(object)); localStorage.setItem('currentBackground', JSON.stringify(object));
@ -33,12 +39,16 @@ function gradientStyleBuilder({ type, angle, gradient }) {
return { return {
type: 'colour', type: 'colour',
style: `background:${gradient[0]?.colour};${grad}` style: `background:${gradient[0]?.colour};${grad}`,
}; };
} }
export function getGradient() { export function getGradient() {
const customBackgroundColour = localStorage.getItem('customBackgroundColour') || {'angle':'180','gradient':[{'colour':'#ffb032','stop':0}],'type':'linear'}; const customBackgroundColour = localStorage.getItem('customBackgroundColour') || {
angle: '180',
gradient: [{ colour: '#ffb032', stop: 0 }],
type: 'linear',
};
let gradientSettings = ''; let gradientSettings = '';
try { try {
@ -47,7 +57,11 @@ export function getGradient() {
const hexColorRegex = /#[0-9a-fA-F]{6}/s; const hexColorRegex = /#[0-9a-fA-F]{6}/s;
if (hexColorRegex.exec(customBackgroundColour)) { if (hexColorRegex.exec(customBackgroundColour)) {
// Colour used to be simply a hex colour or a NULL value before it was a JSON object. This automatically upgrades the hex colour value to the new standard. (NULL would not trigger an exception) // Colour used to be simply a hex colour or a NULL value before it was a JSON object. This automatically upgrades the hex colour value to the new standard. (NULL would not trigger an exception)
gradientSettings = { 'type': 'linear', 'angle': '180', 'gradient': [{ 'colour': customBackgroundColour, 'stop': 0 }] }; gradientSettings = {
type: 'linear',
angle: '180',
gradient: [{ colour: customBackgroundColour, stop: 0 }],
};
localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings)); localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings));
} }
} }
@ -59,16 +73,30 @@ export function getGradient() {
export function randomColourStyleBuilder(type) { export function randomColourStyleBuilder(type) {
// randomColour based on https://stackoverflow.com/a/5092872 // randomColour based on https://stackoverflow.com/a/5092872
const randomColour = () => '#000000'.replace(/0/g, () => { return (~~(Math.random()*16)).toString(16) }); const randomColour = () =>
'#000000'.replace(/0/g, () => {
return (~~(Math.random() * 16)).toString(16);
});
let style = `background:${randomColour()};`; let style = `background:${randomColour()};`;
if (type === 'random_gradient') { if (type === 'random_gradient') {
const directions = ['to right', 'to left', 'to bottom', 'to top', 'to bottom right', 'to bottom left', 'to top right', 'to top left']; const directions = [
style = `background:linear-gradient(${directions[Math.floor(Math.random() * directions.length)]}, ${randomColour()}, ${randomColour()});`; 'to right',
'to left',
'to bottom',
'to top',
'to bottom right',
'to bottom left',
'to top right',
'to top left',
];
style = `background:linear-gradient(${
directions[Math.floor(Math.random() * directions.length)]
}, ${randomColour()}, ${randomColour()});`;
} }
return { return {
type: 'colour', type: 'colour',
style style,
} };
} }

View File

@ -16,5 +16,9 @@ export function nth(d) {
} }
export function convertTimezone(date, tz) { export function convertTimezone(date, tz) {
return new Date((typeof date === 'string' ? new Date(date) : date).toLocaleString('en-US', { timeZone: tz })); return new Date(
(typeof date === 'string' ? new Date(date) : date).toLocaleString('en-US', {
timeZone: tz,
}),
);
} }

View File

@ -6,9 +6,11 @@ export default class EventBus {
} }
static dispatch(event, data) { static dispatch(event, data) {
document.dispatchEvent(new CustomEvent(event, { document.dispatchEvent(
detail: data new CustomEvent(event, {
})); detail: data,
}),
);
} }
static off(event, callback) { static off(event, callback) {

View File

@ -22,7 +22,8 @@ export default function ExperimentalInit() {
debugger; debugger;
} }
break; break;
default: break; default:
break;
} }
}; };
} }

View File

@ -7,7 +7,8 @@ function showReminder() {
// based on https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links // based on https://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
export function urlParser(input) { export function urlParser(input) {
const 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, '<br/><a href="$&" target="_blank">$&</a>'); return input.replace(urlPattern, '<br/><a href="$&" target="_blank">$&</a>');
} }
@ -20,7 +21,7 @@ export function install(type, input, sideload) {
Object.keys(localStorage).forEach((key) => { Object.keys(localStorage).forEach((key) => {
oldSettings.push({ oldSettings.push({
name: key, name: key,
value: localStorage.getItem(key) value: localStorage.getItem(key),
}); });
}); });
@ -33,7 +34,7 @@ export function install(type, input, sideload) {
case 'photos': case 'photos':
const currentPhotos = JSON.parse(localStorage.getItem('photo_packs')) || []; const currentPhotos = JSON.parse(localStorage.getItem('photo_packs')) || [];
input.photos.forEach(photo => { input.photos.forEach((photo) => {
currentPhotos.push(photo); currentPhotos.push(photo);
}); });
localStorage.setItem('photo_packs', JSON.stringify(currentPhotos)); localStorage.setItem('photo_packs', JSON.stringify(currentPhotos));
@ -63,8 +64,8 @@ export function install(type, input, sideload) {
installed.push({ installed.push({
content: { content: {
updated: 'Unpublished', updated: 'Unpublished',
data: input data: input,
} },
}); });
} else { } else {
installed.push(input); installed.push(input);
@ -94,9 +95,11 @@ export function uninstall(type, name) {
case 'photos': case 'photos':
const installedContents = JSON.parse(localStorage.getItem('photo_packs')); const installedContents = JSON.parse(localStorage.getItem('photo_packs'));
const packContents = JSON.parse(localStorage.getItem('installed')).find(content => content.name === name); const packContents = JSON.parse(localStorage.getItem('installed')).find(
(content) => content.name === name,
);
// todo: make it find in photo_packs all the ones in installed for that pack and remove // todo: make it find in photo_packs all the ones in installed for that pack and remove
console.log(packContents) console.log(packContents);
installedContents.forEach((item, index) => { installedContents.forEach((item, index) => {
if (packContents.photos.includes(item)) { if (packContents.photos.includes(item)) {
installedContents.splice(index, 1); installedContents.splice(index, 1);
@ -121,4 +124,4 @@ export function uninstall(type, name) {
} }
localStorage.setItem('installed', JSON.stringify(installed)); localStorage.setItem('installed', JSON.stringify(installed));
}; }

View File

@ -12,7 +12,10 @@ export function setDefaultSettings(reset) {
// Languages // Languages
const languageCodes = languages.map(({ value }) => value); const languageCodes = languages.map(({ value }) => value);
const browserLanguage = (navigator.languages && navigator.languages.find((lang) => lang.replace('-', '_') && languageCodes.includes(lang))) || navigator.language.replace('-', '_'); const browserLanguage =
(navigator.languages &&
navigator.languages.find((lang) => lang.replace('-', '_') && languageCodes.includes(lang))) ||
navigator.language.replace('-', '_');
if (languageCodes.includes(browserLanguage)) { if (languageCodes.includes(browserLanguage)) {
localStorage.setItem('language', browserLanguage); localStorage.setItem('language', browserLanguage);
@ -63,7 +66,7 @@ export function loadSettings(hotreload) {
}); });
} }
if (localStorage.getItem('animations') === 'false') { if (localStorage.getItem('animations') === 'false') {
document.body.classList.add('no-animations'); document.body.classList.add('no-animations');
} else { } else {
document.body.classList.remove('no-animations'); document.body.classList.remove('no-animations');
@ -79,7 +82,7 @@ export function loadSettings(hotreload) {
try { try {
document.querySelector('.' + element).classList.add('textBorder'); document.querySelector('.' + element).classList.add('textBorder');
} catch (e) { } catch (e) {
// Disregard exception // Disregard exception
} }
}); });
} else { } else {
@ -88,7 +91,7 @@ export function loadSettings(hotreload) {
try { try {
document.querySelector('.' + element).classList.remove('textBorder'); document.querySelector('.' + element).classList.remove('textBorder');
} catch (e) { } catch (e) {
// Disregard exception // Disregard exception
} }
}); });
} }
@ -112,7 +115,9 @@ export function loadSettings(hotreload) {
url = `@import url('https://fonts.googleapis.com/css2?family=${font}&display=swap');`; url = `@import url('https://fonts.googleapis.com/css2?family=${font}&display=swap');`;
} }
document.head.insertAdjacentHTML('beforeend', ` document.head.insertAdjacentHTML(
'beforeend',
`
<style id='customfont'> <style id='customfont'>
${url} ${url}
* { * {
@ -121,7 +126,8 @@ export function loadSettings(hotreload) {
font-style: ${localStorage.getItem('fontstyle')}; font-style: ${localStorage.getItem('fontstyle')};
} }
</style> </style>
`); `,
);
} }
// everything below this shouldn't run on a hot reload event // everything below this shouldn't run on a hot reload event
@ -153,7 +159,7 @@ export function loadSettings(hotreload) {
`); `);
} }
// in a nutshell, this function saves all of the current settings, resets them, sets the defaults and then overrides // in a nutshell, this function saves all of the current settings, resets them, sets the defaults and then overrides
// the new settings with the old saved messages where they exist // the new settings with the old saved messages where they exist
export function moveSettings() { export function moveSettings() {
const currentSettings = Object.keys(localStorage); const currentSettings = Object.keys(localStorage);

View File

@ -7,17 +7,33 @@ export function saveFile(data, filename = 'file', type = 'text/json') {
if (typeof data === 'object') { if (typeof data === 'object') {
data = JSON.stringify(data, undefined, 4); data = JSON.stringify(data, undefined, 4);
} }
const blob = new Blob([data], { type }); const blob = new Blob([data], { type });
const event = document.createEvent('MouseEvents'); const event = document.createEvent('MouseEvents');
const a = document.createElement('a'); const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob); a.href = window.URL.createObjectURL(blob);
a.download = filename; a.download = filename;
a.dataset.downloadurl = [type, a.download, a.href].join(':'); a.dataset.downloadurl = [type, a.download, a.href].join(':');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); event.initMouseEvent(
'click',
true,
false,
window,
0,
0,
0,
0,
0,
false,
false,
false,
false,
0,
null,
);
a.dispatchEvent(event); a.dispatchEvent(event);
} }
@ -44,39 +60,39 @@ export function importSettings(e) {
export function values(type) { export function values(type) {
const marks = { const marks = {
zoom: [ zoom: [
{ value: 10, label: '0.1x' }, { value: 10, label: '0.1x' },
{ value: 100, label: '1x' }, { value: 100, label: '1x' },
{ value: 200, label: '2x' }, { value: 200, label: '2x' },
{ value: 400, label: '4x' } { value: 400, label: '4x' },
], ],
toast: [ toast: [
{ value: 500, label: '0.5s' }, { value: 500, label: '0.5s' },
{ value: 1000, label: '1s' }, { value: 1000, label: '1s' },
{ value: 1500, label: '1.5s' }, { value: 1500, label: '1.5s' },
{ value: 2000, label: '2s' }, { value: 2000, label: '2s' },
{ value: 2500, label: '2.5s' }, { value: 2500, label: '2.5s' },
{ value: 3000, label: '3s' }, { value: 3000, label: '3s' },
{ value: 4000, label: '4s' }, { value: 4000, label: '4s' },
{ value: 5000, label: '5s'} { value: 5000, label: '5s' },
], ],
background: [ background: [
{ value: 0, label: '0%'}, { value: 0, label: '0%' },
{ value: 25, label: '25%' }, { value: 25, label: '25%' },
{ value: 50, label: '50%' }, { value: 50, label: '50%' },
{ value: 75, label: '75%' }, { value: 75, label: '75%' },
{ value: 100, label: '100%' } { value: 100, label: '100%' },
], ],
experimental: [ experimental: [
{ value: 0, label: '0s' }, { value: 0, label: '0s' },
{ value: 500, label: '0.5s' }, { value: 500, label: '0.5s' },
{ value: 1000, label: '1s' }, { value: 1000, label: '1s' },
{ value: 1500, label: '1.5s' }, { value: 1500, label: '1.5s' },
{ value: 2000, label: '2s' }, { value: 2000, label: '2s' },
{ value: 2500, label: '2.5s' }, { value: 2500, label: '2.5s' },
{ value: 3000, label: '3s' }, { value: 3000, label: '3s' },
{ value: 4000, label: '4s' }, { value: 4000, label: '4s' },
{ value: 5000, label: '5s'} { value: 5000, label: '5s' },
] ],
}; };
return marks[type]; return marks[type];

View File

@ -21,7 +21,7 @@ export default class Stats {
static async tabLoad() { static async tabLoad() {
const data = JSON.parse(localStorage.getItem('statsData')); const data = JSON.parse(localStorage.getItem('statsData'));
data['tabs-opened'] = data['tabs-opened'] + 1 || 1; data['tabs-opened'] = data['tabs-opened'] + 1 || 1;
localStorage.setItem('statsData', JSON.stringify(data)); localStorage.setItem('statsData', JSON.stringify(data));
} }
} }

View File

@ -5,10 +5,10 @@ const variables = {
languagecode: '', languagecode: '',
stats: { stats: {
tabLoad: () => '', tabLoad: () => '',
postEvent: () => '' postEvent: () => '',
}, },
//keybinds: {}, //keybinds: {},
constants: Constants constants: Constants,
}; };
export default variables; export default variables;

View File

@ -61,7 +61,7 @@ $themes: (
'color': rgb(0, 0, 0), 'color': rgb(0, 0, 0),
'subColor': #333333, 'subColor': #333333,
'borderRadius': 12px, 'borderRadius': 12px,
'boxShadow': 0 0 0 1px #E7E3E9, 'boxShadow': 0 0 0 1px #e7e3e9,
'btn-background': #fff, 'btn-background': #fff,
'btn-backgroundHover': rgba(247, 250, 252, 0.9), 'btn-backgroundHover': rgba(247, 250, 252, 0.9),
'modal-background': #fff, 'modal-background': #fff,

File diff suppressed because it is too large Load Diff

View File

@ -7,36 +7,38 @@ module.exports = {
entry: path.resolve(__dirname, './src/index.js'), entry: path.resolve(__dirname, './src/index.js'),
mode: 'development', mode: 'development',
performance: { performance: {
hints: false hints: false,
}, },
module: { module: {
rules: [{ rules: [
test: /\.(js|jsx)$/, {
exclude: /node_modules/, test: /\.(js|jsx)$/,
use: ['babel-loader'] exclude: /node_modules/,
}, use: ['babel-loader'],
{ },
test: /\.(|sc|c)ss$/, {
use: [ test: /\.(|sc|c)ss$/,
{ use: [
loader: MiniCssExtractPlugin.loader, {
options: { loader: MiniCssExtractPlugin.loader,
publicPath: '' options: {
publicPath: '',
},
}, },
}, 'css-loader',
'css-loader', 'sass-loader',
'sass-loader' ],
], },
}, {
{ test: /\.(woff|woff2|svg)$/,
test: /\.(woff|woff2|svg)$/, type: 'asset/resource',
type: 'asset/resource' },
}, {
{ test: /\.js$/,
test: /\.js$/, enforce: 'pre',
enforce: 'pre', use: ['source-map-loader'],
use: ['source-map-loader'] },
}] ],
}, },
resolve: { resolve: {
extensions: ['.js', '.jsx'], extensions: ['.js', '.jsx'],
@ -44,42 +46,43 @@ module.exports = {
components: path.resolve(__dirname, './src/components'), components: path.resolve(__dirname, './src/components'),
modules: path.resolve(__dirname, './src/modules'), modules: path.resolve(__dirname, './src/modules'),
translations: path.resolve(__dirname, './src/translations'), translations: path.resolve(__dirname, './src/translations'),
scss: path.resolve(__dirname, './src/scss') scss: path.resolve(__dirname, './src/scss'),
} },
}, },
output: { output: {
path: path.resolve(__dirname, './build'), path: path.resolve(__dirname, './build'),
filename: '[name].[chunkhash].js', filename: '[name].[chunkhash].js',
chunkFilename: '[id].[chunkhash].chunk.js', chunkFilename: '[id].[chunkhash].chunk.js',
clean: true clean: true,
}, },
devServer: { devServer: {
static: path.resolve(__dirname, './build'), static: path.resolve(__dirname, './build'),
open: true, open: true,
port: 3000 port: 3000,
}, },
plugins: [ plugins: [
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html') template: path.resolve(__dirname, './public/index.html'),
}), }),
new CopyPlugin({ new CopyPlugin({
patterns: [{ patterns: [
{
from: 'public/icons', from: 'public/icons',
to: 'icons' to: 'icons',
}, },
{ {
from: 'public/offline-images', from: 'public/offline-images',
to: 'offline-images' to: 'offline-images',
}, },
{ {
from: 'public/welcome-images', from: 'public/welcome-images',
to: 'welcome-images' to: 'welcome-images',
} },
] ],
}), }),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: '[name].[chunkhash].css', filename: '[name].[chunkhash].css',
chunkFilename: '[id].[chunkhash].chunk.css' chunkFilename: '[id].[chunkhash].chunk.css',
}), }),
] ],
}; };