mirror of https://github.com/mue/mue.git
feat(dev): jsdoc and prop-types
This commit is contained in:
parent
f892c4c690
commit
c81c01d484
|
@ -23,6 +23,7 @@
|
|||
"embla-carousel-react": "^7.1.0",
|
||||
"fast-blurhash": "^1.1.2",
|
||||
"image-conversion": "^2.1.1",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
"react-clock": "4.1.0",
|
||||
"react-color-gradient-picker": "0.1.2",
|
||||
|
|
|
@ -23,6 +23,7 @@ specifiers:
|
|||
husky: ^8.0.3
|
||||
image-conversion: ^2.1.1
|
||||
prettier: ^2.8.4
|
||||
prop-types: ^15.8.1
|
||||
react: ^18.2.0
|
||||
react-clock: 4.1.0
|
||||
react-color-gradient-picker: 0.1.2
|
||||
|
@ -52,13 +53,14 @@ dependencies:
|
|||
embla-carousel-react: 7.1.0_react@18.2.0
|
||||
fast-blurhash: 1.1.2
|
||||
image-conversion: 2.1.1
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
react-clock: 4.1.0_biqbaboplfbrettd7655fr4n2y
|
||||
react-color-gradient-picker: 0.1.2_biqbaboplfbrettd7655fr4n2y
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
react-icons: 4.8.0_react@18.2.0
|
||||
react-modal: 3.16.1_biqbaboplfbrettd7655fr4n2y
|
||||
react-sortable-hoc: 2.0.0_biqbaboplfbrettd7655fr4n2y
|
||||
react-sortable-hoc: 2.0.0_v2m5e27vhdewzwhryxwfaorcca
|
||||
react-toastify: 9.1.1_biqbaboplfbrettd7655fr4n2y
|
||||
|
||||
devDependencies:
|
||||
|
@ -5207,9 +5209,10 @@ packages:
|
|||
warning: 4.0.3
|
||||
dev: false
|
||||
|
||||
/react-sortable-hoc/2.0.0_biqbaboplfbrettd7655fr4n2y:
|
||||
/react-sortable-hoc/2.0.0_v2m5e27vhdewzwhryxwfaorcca:
|
||||
resolution: {integrity: sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg==}
|
||||
peerDependencies:
|
||||
prop-types: ^15.5.7
|
||||
react: ^16.3.0 || ^17.0.0
|
||||
react-dom: ^16.3.0 || ^17.0.0
|
||||
dependencies:
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
const fs = require('fs');
|
||||
const merge = require('@eartharoid/deep-merge');
|
||||
|
||||
/**
|
||||
* It recursively compares the keys of two JSON objects and removes the keys from the first object that
|
||||
* are not present in the second object
|
||||
* @param json1 - The JSON object that you want to remove keys from.
|
||||
* @param json2 - The JSON object that you want to compare against.
|
||||
*/
|
||||
const compareAndRemoveKeys = (json1, json2) => {
|
||||
for (let key in json1) {
|
||||
if (json2.hasOwnProperty(key)) {
|
||||
|
@ -12,7 +18,7 @@ const compareAndRemoveKeys = (json1, json2) => {
|
|||
delete json1[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fs.readdirSync('../src/translations').forEach((file) => {
|
||||
if (file === 'en_GB.json') {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
import './autocomplete.scss';
|
||||
|
||||
export default class Autocomplete extends PureComponent {
|
||||
class Autocomplete extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -91,3 +92,12 @@ export default class Autocomplete extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Autocomplete.propTypes = {
|
||||
suggestions: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
placeholder: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Autocomplete;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect, useCallback, useRef, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MdOutlineArrowForwardIos, MdOutlineArrowBackIos } from 'react-icons/md';
|
||||
import useEmblaCarousel from 'embla-carousel-react';
|
||||
import Autoplay from 'embla-carousel-autoplay';
|
||||
|
@ -77,4 +78,8 @@ function EmblaCarousel({ data }) {
|
|||
);
|
||||
}
|
||||
|
||||
EmblaCarousel.propTypes = {
|
||||
data: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
};
|
||||
|
||||
export default memo(EmblaCarousel);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import variables from 'modules/variables';
|
||||
import './preview.scss';
|
||||
|
||||
|
@ -14,4 +15,8 @@ function Preview(props) {
|
|||
);
|
||||
}
|
||||
|
||||
Preview.propTypes = {
|
||||
setup: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Preview);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import variables from 'modules/variables';
|
||||
import { MdClose, MdEmail, MdContentCopy } from 'react-icons/md';
|
||||
import { FaTwitter, FaFacebookF } from 'react-icons/fa';
|
||||
|
@ -118,4 +119,9 @@ function ShareModal({ modalClose, data }) {
|
|||
);
|
||||
}
|
||||
|
||||
ShareModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
data: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(ShareModal);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { useState, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useFloating, flip, offset, shift } from '@floating-ui/react-dom';
|
||||
import './tooltip.scss';
|
||||
|
||||
|
@ -42,4 +43,12 @@ function Tooltip({ children, title, style, placement, subtitle }) {
|
|||
);
|
||||
}
|
||||
|
||||
Tooltip.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
style: PropTypes.object,
|
||||
placement: PropTypes.string,
|
||||
subtitle: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Tooltip);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { useState, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useFloating, flip, offset, shift } from '@floating-ui/react-dom';
|
||||
import { MdClose, MdInfo, MdOpenInNew } from 'react-icons/md';
|
||||
import Tooltip from './Tooltip';
|
||||
|
@ -44,4 +45,11 @@ function InfoTooltip({ title, style, placement, subtitle }) {
|
|||
);
|
||||
}
|
||||
|
||||
InfoTooltip.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
style: PropTypes.object,
|
||||
placement: PropTypes.string,
|
||||
subtitle: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(InfoTooltip);
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { MdErrorOutline } from 'react-icons/md';
|
||||
import { captureException } from '@sentry/react';
|
||||
|
||||
export default class ErrorBoundary extends PureComponent {
|
||||
class ErrorBoundary extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -13,6 +15,11 @@ export default class ErrorBoundary extends PureComponent {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* If an error occurs, log the error, and set the state to error: true, and errorData: error.
|
||||
* @param {Error} error The error that occurred.
|
||||
* @returns An object with two properties: error and errorData.
|
||||
*/
|
||||
static getDerivedStateFromError(error) {
|
||||
console.log(error);
|
||||
variables.stats.postEvent('modal', 'Error occurred');
|
||||
|
@ -63,3 +70,9 @@ export default class ErrorBoundary extends PureComponent {
|
|||
return this.props.children;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorBoundary.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
};
|
||||
|
||||
export default ErrorBoundary;
|
||||
|
|
|
@ -35,8 +35,8 @@ export default class Modals extends PureComponent {
|
|||
if (window.location.search === '?nointro=true') {
|
||||
if (localStorage.getItem('showWelcome') === 'true') {
|
||||
localStorage.setItem('showWelcome', false);
|
||||
EventBus.dispatch('refresh', 'widgets');
|
||||
EventBus.dispatch('refresh', 'backgroundwelcome');
|
||||
EventBus.emit('refresh', 'widgets');
|
||||
EventBus.emit('refresh', 'backgroundwelcome');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,9 +49,9 @@ export default class Modals extends PureComponent {
|
|||
this.setState({
|
||||
welcomeModal: false,
|
||||
});
|
||||
EventBus.dispatch('refresh', 'widgetsWelcomeDone');
|
||||
EventBus.dispatch('refresh', 'widgets');
|
||||
EventBus.dispatch('refresh', 'backgroundwelcome');
|
||||
EventBus.emit('refresh', 'widgetsWelcomeDone');
|
||||
EventBus.emit('refresh', 'widgets');
|
||||
EventBus.emit('refresh', 'backgroundwelcome');
|
||||
}
|
||||
|
||||
previewWelcome() {
|
||||
|
@ -61,7 +61,7 @@ export default class Modals extends PureComponent {
|
|||
welcomeModal: false,
|
||||
preview: true,
|
||||
});
|
||||
EventBus.dispatch('refresh', 'widgetsWelcome');
|
||||
EventBus.emit('refresh', 'widgetsWelcome');
|
||||
}
|
||||
|
||||
toggleModal(type, action) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
import { Suspense, lazy, useState } from 'react';
|
||||
import { Suspense, lazy, useState, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { memo } from 'react';
|
||||
import { MdClose } from 'react-icons/md';
|
||||
|
||||
import './scss/index.scss';
|
||||
|
@ -69,4 +69,8 @@ function MainModal({ modalClose }) {
|
|||
);
|
||||
}
|
||||
|
||||
MainModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(MainModal);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
import ImageCarousel from 'components/helpers/carousel/Carousel';
|
||||
import { toast } from 'react-toastify';
|
||||
|
@ -22,7 +23,7 @@ import { install, uninstall } from 'modules/helpers/marketplace';
|
|||
|
||||
import ShareModal from 'components/helpers/sharemodal/ShareModal';
|
||||
|
||||
export default class Item extends PureComponent {
|
||||
class Item extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -327,3 +328,12 @@ export default class Item extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Item.propTypes = {
|
||||
data: PropTypes.object,
|
||||
addonInstalled: PropTypes.bool,
|
||||
addonInstalledVersion: PropTypes.string,
|
||||
toggleFunction: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Item;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import React, { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MdAutoFixHigh, MdOutlineArrowForward, MdOutlineOpenInNew } from 'react-icons/md';
|
||||
|
||||
function Items({
|
||||
|
@ -118,4 +119,14 @@ function Items({
|
|||
);
|
||||
}
|
||||
|
||||
Items.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
collection: PropTypes.object,
|
||||
toggleFunction: PropTypes.func.isRequired,
|
||||
collectionFunction: PropTypes.func.isRequired,
|
||||
onCollection: PropTypes.bool.isRequired,
|
||||
filter: PropTypes.string,
|
||||
};
|
||||
|
||||
export default memo(Items);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import variables from 'modules/variables';
|
||||
|
||||
function Lightbox({ modalClose, img }) {
|
||||
|
@ -14,4 +15,9 @@ function Lightbox({ modalClose, img }) {
|
|||
);
|
||||
}
|
||||
|
||||
Lightbox.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
img: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Lightbox);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import variables from 'modules/variables';
|
||||
import { MdClose } from 'react-icons/md';
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
|
@ -22,4 +23,9 @@ function SideloadFailedModal({ modalClose, reason }) {
|
|||
);
|
||||
}
|
||||
|
||||
SideloadFailedModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
reason: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(SideloadFailedModal);
|
||||
|
|
|
@ -13,8 +13,8 @@ import Dropdown from '../../settings/Dropdown';
|
|||
import { install, uninstall, urlParser } from 'modules/helpers/marketplace';
|
||||
|
||||
export default class Added extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
installed: JSON.parse(localStorage.getItem('installed')),
|
||||
item: {},
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { toast } from 'react-toastify';
|
||||
import {
|
||||
MdWifiOff,
|
||||
|
@ -16,7 +17,7 @@ import Dropdown from '../../settings/Dropdown';
|
|||
|
||||
import { install, urlParser, uninstall } from 'modules/helpers/marketplace';
|
||||
|
||||
export default class Marketplace extends PureComponent {
|
||||
class Marketplace extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
|
@ -470,3 +471,9 @@ export default class Marketplace extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Marketplace.propTypes = {
|
||||
type: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Marketplace;
|
||||
|
|
|
@ -98,7 +98,7 @@ legend,
|
|||
color: t($color);
|
||||
}
|
||||
|
||||
li{
|
||||
li {
|
||||
&:hover {
|
||||
@include themed {
|
||||
background-color: t($modal-sidebarActive);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Checkbox as CheckboxUI, FormControlLabel } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
export default class Checkbox extends PureComponent {
|
||||
class Checkbox extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -36,7 +37,7 @@ export default class Checkbox extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', this.props.category);
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -57,3 +58,14 @@ export default class Checkbox extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Checkbox.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
category: PropTypes.string,
|
||||
element: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Checkbox;
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import { useState, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
|
@ -53,4 +55,10 @@ function ChipSelect({ label, options, name }) {
|
|||
);
|
||||
}
|
||||
|
||||
ChipSelect.propTypes = {
|
||||
label: PropTypes.string,
|
||||
options: PropTypes.array,
|
||||
name: PropTypes.string,
|
||||
};
|
||||
|
||||
export default memo(ChipSelect);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent, createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { InputLabel, MenuItem, FormControl, Select } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
export default class Dropdown extends PureComponent {
|
||||
class Dropdown extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -43,7 +44,7 @@ export default class Dropdown extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', this.props.category);
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -76,3 +77,17 @@ export default class Dropdown extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Dropdown.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
label: PropTypes.string,
|
||||
category: PropTypes.string,
|
||||
element: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
noSetting: PropTypes.bool,
|
||||
manual: PropTypes.bool,
|
||||
value2: PropTypes.string,
|
||||
name2: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Dropdown;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { toast } from 'react-toastify';
|
||||
import { compressAccurately, filetoDataURL } from 'image-conversion';
|
||||
import { videoCheck } from 'modules/helpers/background/widget';
|
||||
|
||||
export default class FileUpload extends PureComponent {
|
||||
class FileUpload extends PureComponent {
|
||||
componentDidMount() {
|
||||
document.getElementById(this.props.id).onchange = (e) => {
|
||||
const reader = new FileReader();
|
||||
|
@ -61,3 +62,12 @@ export default class FileUpload extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
FileUpload.propTypes = {
|
||||
id: PropTypes.string.isRequired,
|
||||
type: PropTypes.string.isRequired,
|
||||
loadFunction: PropTypes.func.isRequired,
|
||||
accept: PropTypes.string,
|
||||
};
|
||||
|
||||
export default FileUpload;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { /*MdHelpOutline,*/ MdFlag, MdArrowBack } from 'react-icons/md';
|
||||
|
||||
import Slider from './Slider';
|
||||
|
@ -10,7 +11,7 @@ import SettingsItem from './SettingsItem';
|
|||
import { values } from 'modules/helpers/settings/modals';
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
|
||||
export default class Header extends PureComponent {
|
||||
class Header extends PureComponent {
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
|
@ -89,3 +90,17 @@ export default class Header extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
setting: PropTypes.string.isRequired,
|
||||
category: PropTypes.string.isRequired,
|
||||
element: PropTypes.string,
|
||||
backButton: PropTypes.bool,
|
||||
clickEffect: PropTypes.func,
|
||||
switch: PropTypes.bool,
|
||||
zoomSetting: PropTypes.string,
|
||||
zoomCategory: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Radio as RadioUI,
|
||||
RadioGroup,
|
||||
|
@ -11,7 +12,7 @@ import {
|
|||
import EventBus from 'modules/helpers/eventbus';
|
||||
import translations from 'modules/translations';
|
||||
|
||||
export default class Radio extends PureComponent {
|
||||
class Radio extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -52,7 +53,7 @@ export default class Radio extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', this.props.category);
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -83,3 +84,20 @@ export default class Radio extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Radio.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
options: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
name: PropTypes.string.isRequired,
|
||||
value: PropTypes.string.isRequired,
|
||||
}),
|
||||
).isRequired,
|
||||
onChange: PropTypes.func,
|
||||
category: PropTypes.string,
|
||||
element: PropTypes.string,
|
||||
smallTitle: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Radio;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import variables from 'modules/variables';
|
||||
import { MdClose, MdRestartAlt } from 'react-icons/md';
|
||||
import { setDefaultSettings } from 'modules/helpers/settings';
|
||||
|
@ -45,4 +46,8 @@ function ResetModal({ modalClose }) {
|
|||
);
|
||||
}
|
||||
|
||||
ResetModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(ResetModal);
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
function SettingsItem(props) {
|
||||
function SettingsItem({ final, title, subtitle, children }) {
|
||||
return (
|
||||
<div className={props.final ? 'settingsRow settingsNoBorder' : 'settingsRow'}>
|
||||
<div className={final ? 'settingsRow settingsNoBorder' : 'settingsRow'}>
|
||||
<div className="content">
|
||||
<span className="title">{props.title}</span>
|
||||
<span className="subtitle">{props.subtitle}</span>
|
||||
<span className="title">{title}</span>
|
||||
<span className="subtitle">{subtitle}</span>
|
||||
</div>
|
||||
<div className="action">{props.children}</div>
|
||||
<div className="action">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
SettingsItem.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
subtitle: PropTypes.string.isRequired,
|
||||
children: PropTypes.node.isRequired,
|
||||
final: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default memo(SettingsItem);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Slider } from '@mui/material';
|
||||
import { MdRefresh } from 'react-icons/md';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
export default class SliderComponent extends PureComponent {
|
||||
class SliderComponent extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -46,7 +47,7 @@ export default class SliderComponent extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', this.props.category);
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
resetItem = () => {
|
||||
|
@ -84,3 +85,17 @@ export default class SliderComponent extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
SliderComponent.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
default: PropTypes.number.isRequired,
|
||||
min: PropTypes.number.isRequired,
|
||||
max: PropTypes.number.isRequired,
|
||||
step: PropTypes.number,
|
||||
marks: PropTypes.array,
|
||||
element: PropTypes.string,
|
||||
category: PropTypes.string,
|
||||
};
|
||||
|
||||
export default SliderComponent;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Switch as SwitchUI, FormControlLabel } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
export default class Switch extends PureComponent {
|
||||
class Switch extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -32,7 +33,7 @@ export default class Switch extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', this.props.category);
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -52,3 +53,13 @@ export default class Switch extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Switch.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
category: PropTypes.string,
|
||||
element: PropTypes.string,
|
||||
header: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Switch;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { toast } from 'react-toastify';
|
||||
import { TextField } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
export default class Text extends PureComponent {
|
||||
class Text extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -33,7 +34,7 @@ export default class Text extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', this.props.category);
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
resetItem = () => {
|
||||
|
@ -77,3 +78,16 @@ export default class Text extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Text.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
category: PropTypes.string.isRequired,
|
||||
default: PropTypes.string,
|
||||
element: PropTypes.string,
|
||||
customcss: PropTypes.bool,
|
||||
textarea: PropTypes.bool,
|
||||
upperCaseFirst: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default Text;
|
||||
|
|
|
@ -51,7 +51,7 @@ function ExperimentalSettings() {
|
|||
varient="outlined"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
<button className="uploadbg" onClick={() => EventBus.dispatch(eventType, eventName)}>
|
||||
<button className="uploadbg" onClick={() => EventBus.emit(eventType, eventName)}>
|
||||
Send
|
||||
</button>
|
||||
</SettingsItem>
|
||||
|
|
|
@ -23,7 +23,7 @@ export default class Message extends PureComponent {
|
|||
messages: [],
|
||||
});
|
||||
toast(variables.getMessage(this.languagecode, 'toasts.reset'));
|
||||
EventBus.dispatch('refresh', 'message');
|
||||
EventBus.emit('refresh', 'message');
|
||||
};
|
||||
|
||||
modifyMessage(type, index) {
|
||||
|
|
|
@ -124,7 +124,7 @@ export default class OrderSettings extends PureComponent {
|
|||
componentDidUpdate() {
|
||||
localStorage.setItem('order', JSON.stringify(this.state.items));
|
||||
variables.stats.postEvent('setting', 'Widget order');
|
||||
EventBus.dispatch('refresh', 'widgets');
|
||||
EventBus.emit('refresh', 'widgets');
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -46,7 +46,7 @@ export default class QuoteSettings extends PureComponent {
|
|||
],
|
||||
});
|
||||
toast(variables.getMessage('toasts.reset'));
|
||||
EventBus.dispatch('refresh', 'background');
|
||||
EventBus.emit('refresh', 'background');
|
||||
};
|
||||
|
||||
customQuote(e, text, index, type) {
|
||||
|
|
|
@ -47,7 +47,7 @@ export default class SearchSettings extends PureComponent {
|
|||
localStorage.setItem('customSearchEngine', this.state.customValue);
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', 'search');
|
||||
EventBus.emit('refresh', 'search');
|
||||
}
|
||||
|
||||
setSearchEngine(input) {
|
||||
|
@ -64,7 +64,7 @@ export default class SearchSettings extends PureComponent {
|
|||
localStorage.setItem('searchEngine', input);
|
||||
}
|
||||
|
||||
EventBus.dispatch('refresh', 'search');
|
||||
EventBus.emit('refresh', 'search');
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -40,7 +40,7 @@ export default class CustomSettings extends PureComponent {
|
|||
customBackground: [],
|
||||
});
|
||||
toast(variables.getMessage('toasts.reset'));
|
||||
EventBus.dispatch('refresh', 'background');
|
||||
EventBus.emit('refresh', 'background');
|
||||
};
|
||||
|
||||
customBackground(e, text, index) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
import { useState, memo } from 'react';
|
||||
import { MdAdd, MdClose, MdOutlineAddLink } from 'react-icons/md';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MdClose, MdOutlineAddLink } from 'react-icons/md';
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
|
||||
function CustomURLModal({ modalClose, urlError, modalCloseOnly }) {
|
||||
|
@ -20,14 +21,14 @@ function CustomURLModal({ modalClose, urlError, modalCloseOnly }) {
|
|||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
value={url}
|
||||
onChange={(e) => setURL(e.target.value.replace(/(\r\n|\n|\r)/gm, ''))}
|
||||
varient="outlined"
|
||||
/>
|
||||
<span className="dropdown-error">{urlError}</span>
|
||||
<div className="resetFooter">
|
||||
<input
|
||||
type="text"
|
||||
value={url}
|
||||
onChange={(e) => setURL(e.target.value.replace(/(\r\n|\n|\r)/gm, ''))}
|
||||
varient="outlined"
|
||||
/>
|
||||
<span className="dropdown-error">{urlError}</span>
|
||||
<div className="resetFooter">
|
||||
<button className="textButton" onClick={modalCloseOnly}>
|
||||
<MdClose />
|
||||
{variables.getMessage('modals.main.settings.sections.advanced.reset_modal.cancel')}
|
||||
|
@ -37,8 +38,14 @@ function CustomURLModal({ modalClose, urlError, modalCloseOnly }) {
|
|||
{variables.getMessage('modals.main.settings.sections.background.source.add_url')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
CustomURLModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
urlError: PropTypes.string.isRequired,
|
||||
modalCloseOnly: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(CustomURLModal);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
|
||||
import { useState, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TextareaAutosize } from '@mui/material';
|
||||
import { MdAddLink, MdClose } from 'react-icons/md';
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
|
@ -69,4 +70,14 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
|
|||
);
|
||||
}
|
||||
|
||||
AddModal.propTypes = {
|
||||
urlError: PropTypes.string.isRequired,
|
||||
iconError: PropTypes.string.isRequired,
|
||||
addLink: PropTypes.func.isRequired,
|
||||
closeModal: PropTypes.func.isRequired,
|
||||
edit: PropTypes.bool.isRequired,
|
||||
editData: PropTypes.object.isRequired,
|
||||
editLink: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(AddModal);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Tabs from './backend/Tabs';
|
||||
|
||||
import Added from '../marketplace/sections/Added';
|
||||
|
@ -18,4 +19,8 @@ function Addons(props) {
|
|||
);
|
||||
}
|
||||
|
||||
Addons.propTypes = {
|
||||
changeTab: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Addons);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import variables from 'modules/variables';
|
||||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Tabs from './backend/Tabs';
|
||||
|
||||
import MarketplaceTab from '../marketplace/sections/Marketplace';
|
||||
|
||||
function Marketplace(props) {
|
||||
|
@ -30,4 +30,8 @@ function Marketplace(props) {
|
|||
);
|
||||
}
|
||||
|
||||
Marketplace.propTypes = {
|
||||
changeTab: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Marketplace);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Tabs from './backend/Tabs';
|
||||
|
||||
|
@ -116,4 +117,8 @@ function Settings(props) {
|
|||
);
|
||||
}
|
||||
|
||||
Settings.propTypes = {
|
||||
changeTab: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Settings);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
MdSettings as Settings,
|
||||
MdWidgets as Addons,
|
||||
|
@ -162,4 +163,11 @@ function Tab({ label, currentTab, onClick, navbarTab }) {
|
|||
);
|
||||
}
|
||||
|
||||
Tab.propTypes = {
|
||||
label: PropTypes.string.isRequired,
|
||||
currentTab: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
navbarTab: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default memo(Tab);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
MdSettings,
|
||||
MdOutlineShoppingBasket,
|
||||
|
@ -10,7 +11,7 @@ import {
|
|||
import Tab from './Tab';
|
||||
import ErrorBoundary from '../../../ErrorBoundary';
|
||||
|
||||
export default class Tabs extends PureComponent {
|
||||
class Tabs extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
|
@ -129,3 +130,16 @@ export default class Tabs extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Tabs.propTypes = {
|
||||
children: PropTypes.instanceOf(Array).isRequired,
|
||||
current: PropTypes.string.isRequired,
|
||||
changeTab: PropTypes.func.isRequired,
|
||||
navbar: PropTypes.bool,
|
||||
};
|
||||
|
||||
Tabs.defaultProps = {
|
||||
navbar: false,
|
||||
};
|
||||
|
||||
export default Tabs;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
function ProgressBar({ count, currentTab, switchTab }) {
|
||||
return (
|
||||
|
@ -17,4 +18,10 @@ function ProgressBar({ count, currentTab, switchTab }) {
|
|||
);
|
||||
}
|
||||
|
||||
ProgressBar.propTypes = {
|
||||
count: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||
currentTab: PropTypes.number.isRequired,
|
||||
switchTab: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default memo(ProgressBar);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
|
@ -8,7 +9,7 @@ import ProgressBar from './ProgressBar';
|
|||
|
||||
import './welcome.scss';
|
||||
|
||||
export default class WelcomeModal extends PureComponent {
|
||||
class WelcomeModal extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
|
@ -145,3 +146,10 @@ export default class WelcomeModal extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
WelcomeModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
modalSkip: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default WelcomeModal;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
MdCloudUpload,
|
||||
MdAutoAwesome,
|
||||
|
@ -22,7 +24,7 @@ import { importSettings } from 'modules/helpers/settings/modals';
|
|||
import default_settings from 'modules/default_settings.json';
|
||||
import languages from 'modules/languages.json';
|
||||
|
||||
export default class WelcomeSections extends PureComponent {
|
||||
class WelcomeSections extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
|
@ -420,3 +422,10 @@ export default class WelcomeSections extends PureComponent {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
WelcomeSections.propTypes = {
|
||||
currentTab: PropTypes.number.isRequired,
|
||||
switchTab: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default WelcomeSections;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
import { MdClose, MdDone } from 'react-icons/md';
|
||||
|
@ -10,7 +11,7 @@ function ExcludeModal({ modalClose, info }) {
|
|||
backgroundExclude.push(info.pun);
|
||||
backgroundExclude = JSON.stringify(backgroundExclude);
|
||||
localStorage.setItem('backgroundExclude', backgroundExclude);
|
||||
EventBus.dispatch('refresh', 'background');
|
||||
EventBus.emit('refresh', 'background');
|
||||
modalClose();
|
||||
};
|
||||
|
||||
|
@ -45,4 +46,9 @@ function ExcludeModal({ modalClose, info }) {
|
|||
);
|
||||
}
|
||||
|
||||
ExcludeModal.propTypes = {
|
||||
modalClose: PropTypes.func.isRequired,
|
||||
info: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default memo(ExcludeModal);
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MdStar, MdStarBorder } from 'react-icons/md';
|
||||
|
||||
export default class Favourite extends PureComponent {
|
||||
class Favourite extends PureComponent {
|
||||
buttons = {
|
||||
favourited: <MdStar onClick={() => this.favourite()} className="topicons" />,
|
||||
unfavourited: <MdStarBorder onClick={() => this.favourite()} className="topicons" />,
|
||||
|
@ -103,3 +104,9 @@ export default class Favourite extends PureComponent {
|
|||
return this.state.favourited;
|
||||
}
|
||||
}
|
||||
|
||||
Favourite.propTypes = {
|
||||
credit: PropTypes.string,
|
||||
offline: PropTypes.bool,
|
||||
pun: PropTypes.string,
|
||||
};
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { MdCropFree } from 'react-icons/md';
|
||||
|
||||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
|
||||
export default class Maximise extends PureComponent {
|
||||
class Maximise extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
|
@ -81,3 +83,9 @@ export default class Maximise extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Maximise.propTypes = {
|
||||
fontSize: PropTypes.number,
|
||||
};
|
||||
|
||||
export default Maximise;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import variables from 'modules/variables';
|
||||
import { useState, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Favourite from './Favourite';
|
||||
import {
|
||||
MdInfo,
|
||||
|
@ -19,15 +20,29 @@ import Modal from 'react-modal';
|
|||
import ShareModal from 'components/helpers/sharemodal/ShareModal';
|
||||
import ExcludeModal from './ExcludeModal';
|
||||
|
||||
/**
|
||||
* It takes a URL, fetches the resource, and returns a URL to the resource.
|
||||
* @param {string} url The URL to fetch.
|
||||
* @returns A promise that resolves to a blob URL.
|
||||
*/
|
||||
const toDataURL = async (url) => {
|
||||
const res = await fetch(url);
|
||||
return URL.createObjectURL(await res.blob());
|
||||
};
|
||||
|
||||
/**
|
||||
* It takes a string, makes it lowercase, removes commas, and replaces spaces with dashes.
|
||||
* @param {string} text The string to format.
|
||||
* @returns A function that takes a string and returns a string.
|
||||
*/
|
||||
const formatText = (text) => {
|
||||
return text.toLowerCase().replaceAll(',', '').replaceAll(' ', '-');
|
||||
};
|
||||
|
||||
/**
|
||||
* It downloads an image from a URL and saves it to the user's computer.
|
||||
* @param {object} info The photo information.
|
||||
*/
|
||||
const downloadImage = async (info) => {
|
||||
const link = document.createElement('a');
|
||||
link.href = await toDataURL(info.url);
|
||||
|
@ -383,4 +398,10 @@ function PhotoInformation({ info, url, api }) {
|
|||
);
|
||||
}
|
||||
|
||||
PhotoInformation.propTypes = {
|
||||
info: PropTypes.object.isRequired,
|
||||
url: PropTypes.string.isRequired,
|
||||
api: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(PhotoInformation);
|
||||
|
|
|
@ -16,6 +16,13 @@ export default class Greeting extends PureComponent {
|
|||
this.greeting = createRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the greeting message for the events of Christmas, New Year and Halloween.
|
||||
* If the events setting is disabled, then the greeting message will not be changed.
|
||||
* @param {Date} time The current time.
|
||||
* @param {String} message The current greeting message.
|
||||
* @returns The message variable is being returned.
|
||||
*/
|
||||
doEvents(time, message) {
|
||||
if (localStorage.getItem('events') === 'false') {
|
||||
return message;
|
||||
|
@ -39,6 +46,11 @@ export default class Greeting extends PureComponent {
|
|||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes a date object and returns the age of the person in years.
|
||||
* @param {Date} date The date of birth.
|
||||
* @returns The age of the person.
|
||||
*/
|
||||
calculateAge(date) {
|
||||
const diff = Date.now() - date.getTime();
|
||||
const birthday = new Date(diff);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent, createRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { MdRefresh, MdSettings } from 'react-icons/md';
|
||||
|
||||
import Notes from './Notes';
|
||||
|
@ -11,7 +13,7 @@ import EventBus from 'modules/helpers/eventbus';
|
|||
|
||||
import './scss/index.scss';
|
||||
|
||||
export default class Navbar extends PureComponent {
|
||||
class Navbar extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.navbarContainer = createRef();
|
||||
|
@ -81,12 +83,12 @@ export default class Navbar extends PureComponent {
|
|||
refresh() {
|
||||
switch (this.state.refreshOption) {
|
||||
case 'background':
|
||||
return EventBus.dispatch('refresh', 'backgroundrefresh');
|
||||
return EventBus.emit('refresh', 'backgroundrefresh');
|
||||
case 'quote':
|
||||
return EventBus.dispatch('refresh', 'quoterefresh');
|
||||
return EventBus.emit('refresh', 'quoterefresh');
|
||||
case 'quotebackground':
|
||||
EventBus.dispatch('refresh', 'quoterefresh');
|
||||
return EventBus.dispatch('refresh', 'backgroundrefresh');
|
||||
EventBus.emit('refresh', 'quoterefresh');
|
||||
return EventBus.emit('refresh', 'backgroundrefresh');
|
||||
default:
|
||||
window.location.reload();
|
||||
}
|
||||
|
@ -143,3 +145,9 @@ export default class Navbar extends PureComponent {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
Navbar.propTypes = {
|
||||
openModal: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Navbar;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { MdContentCopy, MdAssignment, MdPushPin, MdDownload } from 'react-icons/md';
|
||||
import { useFloating, shift } from '@floating-ui/react-dom';
|
||||
import TextareaAutosize from '@mui/material/TextareaAutosize';
|
||||
|
@ -120,12 +122,12 @@ class Notes extends PureComponent {
|
|||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip title={variables.getMessage('widgets.quote.copy')}>
|
||||
<button onClick={() => this.copy()} disabled={this.state.notes === ""}>
|
||||
<button onClick={() => this.copy()} disabled={this.state.notes === ''}>
|
||||
<MdContentCopy />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip title={variables.getMessage('widgets.background.download')}>
|
||||
<button onClick={() => this.download()} disabled={this.state.notes === ""}>
|
||||
<button onClick={() => this.download()} disabled={this.state.notes === ''}>
|
||||
<MdDownload />
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
@ -162,4 +164,12 @@ function NotesWrapper() {
|
|||
);
|
||||
}
|
||||
|
||||
Notes.propTypes = {
|
||||
notesRef: PropTypes.object,
|
||||
floatRef: PropTypes.object,
|
||||
position: PropTypes.string,
|
||||
xPosition: PropTypes.number,
|
||||
yPosition: PropTypes.number,
|
||||
};
|
||||
|
||||
export default memo(NotesWrapper);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
import { PureComponent, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
MdChecklist,
|
||||
MdPushPin,
|
||||
|
@ -53,6 +55,13 @@ class Todo extends PureComponent {
|
|||
EventBus.off('refresh');
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes an array, removes an item from it, and then inserts it at a new index.
|
||||
* @param {Array} array The array to move the item in.
|
||||
* @param {Number} oldIndex The index of the item to move.
|
||||
* @param {Number} newIndex The index to move the item to.
|
||||
* @returns The result of the splice method.
|
||||
*/
|
||||
arrayMove(array, oldIndex, newIndex) {
|
||||
const result = Array.from(array);
|
||||
const [removed] = result.splice(oldIndex, 1);
|
||||
|
@ -79,6 +88,12 @@ class Todo extends PureComponent {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This function takes in an action, an index, and data, and then updates the todo list accordingly.
|
||||
* @param {String} action The action to perform. Can be 'add', 'remove', 'set', or 'done'.
|
||||
* @param {Number} index The index of the item to perform the action on.
|
||||
* @param {Object} data The data to use for the action.
|
||||
*/
|
||||
updateTodo(action, index, data) {
|
||||
let todo = this.state.todo;
|
||||
switch (action) {
|
||||
|
@ -228,4 +243,12 @@ function TodoWrapper() {
|
|||
);
|
||||
}
|
||||
|
||||
Todo.propTypes = {
|
||||
todoRef: PropTypes.object,
|
||||
floatRef: PropTypes.object,
|
||||
position: PropTypes.string,
|
||||
xPosition: PropTypes.string,
|
||||
yPosition: PropTypes.string,
|
||||
};
|
||||
|
||||
export default memo(TodoWrapper);
|
||||
|
|
|
@ -109,13 +109,13 @@ textarea {
|
|||
display: flex !important;
|
||||
gap: 10px;
|
||||
button {
|
||||
&:disabled {
|
||||
@include themed() {
|
||||
background: t($modal-sidebar) !important;
|
||||
&:disabled {
|
||||
@include themed() {
|
||||
background: t($modal-sidebar) !important;
|
||||
}
|
||||
cursor: not-allowed;
|
||||
}
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
flex: 1 !important;
|
||||
|
|
|
@ -114,6 +114,12 @@ export default class Search extends PureComponent {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user selects a search engine from the dropdown menu, the function will set the state of the
|
||||
* search engine to the selected search engine.
|
||||
* @param {string} name - The name of the search engine
|
||||
* @param {boolean} custom - If the search engine is custom
|
||||
*/
|
||||
setSearch(name, custom) {
|
||||
let url;
|
||||
let query = 'q';
|
||||
|
@ -166,6 +172,11 @@ export default class Search extends PureComponent {
|
|||
EventBus.off('refresh');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the icon for the search engine dropdown.
|
||||
* @param {string} name - The name of the search engine.
|
||||
* @returns A React component.
|
||||
*/
|
||||
getSearchDropdownicon(name) {
|
||||
switch (name) {
|
||||
case 'Google':
|
||||
|
@ -196,7 +207,9 @@ export default class Search extends PureComponent {
|
|||
<div className="searchMain">
|
||||
<div className={this.state.classList}>
|
||||
{localStorage.getItem('searchDropdown') === 'true' ? (
|
||||
<Tooltip title={variables.getMessage('modals.main.settings.sections.search.search_engine')}>
|
||||
<Tooltip
|
||||
title={variables.getMessage('modals.main.settings.sections.search.search_engine')}
|
||||
>
|
||||
<button
|
||||
onClick={() => this.setState({ searchDropdown: !this.state.searchDropdown })}
|
||||
>
|
||||
|
@ -206,7 +219,9 @@ export default class Search extends PureComponent {
|
|||
) : (
|
||||
''
|
||||
)}
|
||||
<Tooltip title={variables.getMessage('modals.main.settings.sections.search.voice_search')}>
|
||||
<Tooltip
|
||||
title={variables.getMessage('modals.main.settings.sections.search.voice_search')}
|
||||
>
|
||||
{this.state.microphone}
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import variables from 'modules/variables';
|
||||
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 './date.scss';
|
||||
|
@ -16,6 +16,10 @@ export default class DateWidget extends PureComponent {
|
|||
this.date = createRef();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the week number of the year for the given date.
|
||||
* @param {Date} date
|
||||
*/
|
||||
getWeekNumber(date) {
|
||||
const dateToday = new Date(date.valueOf());
|
||||
const dayNumber = (dateToday.getDay() + 6) % 7;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { WiHumidity, WiWindy, WiBarometer, WiCloud } from 'react-icons/wi';
|
||||
import { MdDisabledVisible } from 'react-icons/md';
|
||||
|
@ -9,6 +10,12 @@ import WindDirectionIcon from './WindDirectionIcon';
|
|||
import Tooltip from 'components/helpers/tooltip/Tooltip';
|
||||
|
||||
function Expanded({ state, weatherType, variables }) {
|
||||
/**
|
||||
* If the localStorage item is true and the weatherType is greater than or equal to 3, or if the
|
||||
* weatherType is equal to 3, then return true.
|
||||
* @param {string} setting - The localStorage item to check.
|
||||
* @returns a boolean value.
|
||||
*/
|
||||
const enabled = (setting) => {
|
||||
return (localStorage.getItem(setting) === 'true' && weatherType >= 3) || weatherType === '3';
|
||||
};
|
||||
|
@ -107,4 +114,10 @@ function Expanded({ state, weatherType, variables }) {
|
|||
);
|
||||
}
|
||||
|
||||
Expanded.propTypes = {
|
||||
state: PropTypes.object.isRequired,
|
||||
weatherType: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
variables: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default memo(Expanded);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
WiDaySunny,
|
||||
|
@ -53,4 +54,8 @@ function WeatherIcon({ name }) {
|
|||
}
|
||||
}
|
||||
|
||||
WeatherIcon.propTypes = {
|
||||
name: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default memo(WeatherIcon);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
WiDirectionDownLeft,
|
||||
|
@ -54,4 +55,8 @@ function WindDirectionIcon({ degrees }) {
|
|||
return direction ? direction.icon : null;
|
||||
}
|
||||
|
||||
WindDirectionIcon.propTypes = {
|
||||
degrees: PropTypes.number.isRequired,
|
||||
};
|
||||
|
||||
export default memo(WindDirectionIcon);
|
||||
|
|
|
@ -2,15 +2,13 @@ import { render } from 'react-dom';
|
|||
import * as Sentry from '@sentry/react';
|
||||
|
||||
import App from './App';
|
||||
import variables from 'modules/variables';
|
||||
import variables from './modules/variables';
|
||||
|
||||
import './scss/index.scss';
|
||||
// the toast css is based on default so we need to import it
|
||||
import 'react-toastify/dist/ReactToastify.min.css';
|
||||
|
||||
import Stats from 'modules/helpers/stats';
|
||||
|
||||
import translations from 'modules/translations';
|
||||
import translations from './modules/translations';
|
||||
|
||||
const languagecode = localStorage.getItem('language') || 'en_GB';
|
||||
variables.language = translations(languagecode);
|
||||
|
@ -20,8 +18,6 @@ document.documentElement.lang = languagecode.replace('_', '-');
|
|||
variables.getMessage = (text, optional) =>
|
||||
variables.language.getMessage(variables.languagecode, text, optional || {});
|
||||
|
||||
variables.stats = Stats;
|
||||
|
||||
Sentry.init({
|
||||
dsn: variables.constants.SENTRY_DSN,
|
||||
defaultIntegrations: false,
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
const testImage =
|
||||
'AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAAFCbWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAFBETmF2aWYAAAAADnBpdG0AAAAAAAEAAAAsaWxvYwAAAABEAAACAAEAAAABAAACRgAAABgAAgAAAAEAAAFqAAAA3AAAAEFpaW5mAAAAAAACAAAAGmluZmUCAAAAAAEAAGF2MDFDb2xvcgAAAAAZaW5mZQIAAAEAAgAARXhpZkV4aWYAAAAAGmlyZWYAAAAAAAAADmNkc2MAAgABAAEAAAB5aXBycAAAAFlpcGNvAAAAFGlzcGUAAAAAAAAAAQAAAAEAAAAQcGFzcAAAAAEAAAABAAAADGF2MUOBABwAAAAADnBpeGkAAAAAAQgAAAATY29scm5jbHgAAQANAAGAAAAAGGlwbWEAAAAAAAAAAQABBQECg4SFAAAA/G1kYXQAAAAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwABAAAAAgAAADEBAgARAAAAZgAAAGmHBAABAAAAeAAAAAAAAAABAAAAAQAAAAEAAAABAAAAcGFpbnQubmV0IDQuMy4xMgAABQAAkAcABAAAADAyMzABoAMAAQAAAAEAAAACoAQAAQAAAAEAAAADoAQAAQAAAAEAAAAFoAQAAQAAALoAAAAAAAAAAgABAAIABAAAAFI5OAACAAcABAAAADAxMDAAAAAAEgAKBxgABpgIaA0yCxJABBEAEADG1FkX';
|
||||
|
||||
/**
|
||||
* It creates a new image element, sets the source to a base64 encoded AVIF image, and then resolves
|
||||
* true if the image loads successfully, or false if it doesn't
|
||||
*/
|
||||
export const supportsAVIF = () => {
|
||||
new Promise((resolve) => {
|
||||
const image = new Image();
|
||||
|
|
|
@ -4,6 +4,11 @@ import setRgba from './setRgba';
|
|||
const hexRegexp = /(^#{0,1}[0-9A-F]{6}$)|(^#{0,1}[0-9A-F]{3}$)|(^#{0,1}[0-9A-F]{8}$)/i;
|
||||
const regexp = /([0-9A-F])([0-9A-F])([0-9A-F])/i;
|
||||
|
||||
/**
|
||||
* It takes a hex color code and returns an object with the color's RGB and HSV values
|
||||
* @param value - The hex value to convert to RGB.
|
||||
* @returns An object with the properties red, green, blue, alpha, hue, saturation, and value.
|
||||
*/
|
||||
export default function hexToRgb(value) {
|
||||
const valid = hexRegexp.test(value);
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
/**
|
||||
* It takes three numbers, converts them to hexadecimal, and returns a string of the three hexadecimal
|
||||
* numbers concatenated together
|
||||
* @param red - The red value of the color (0-255)
|
||||
* @param green - 0
|
||||
* @param blue - 0
|
||||
* @returns a string of the hexadecimal value of the rgb values passed in.
|
||||
*/
|
||||
export default function rgbToHex(red, green, blue) {
|
||||
let r16 = red.toString(16);
|
||||
let g16 = green.toString(16);
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
/**
|
||||
* It converts RGB values to HSV values
|
||||
* @returns An object with the hue, saturation, and value of the color.
|
||||
* @param red - The red value of the color.
|
||||
* @param green - 0-255
|
||||
* @param blue - The blue value of the color.
|
||||
*/
|
||||
export default function rgbToHSv({ red, green, blue }) {
|
||||
let rr, gg, bb, h, s;
|
||||
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
/**
|
||||
* It returns true if the value is a number, not NaN, and between 0 and 255.
|
||||
* @param value - The value to check.
|
||||
* @returns A function that takes a value and returns a boolean.
|
||||
*/
|
||||
const isValidRGBValue = (value) => {
|
||||
return typeof value === 'number' && Number.isNaN(value) === false && value >= 0 && value <= 255;
|
||||
};
|
||||
|
||||
/**
|
||||
* "If the red, green, and blue values are valid, return an object with the red, green, and blue
|
||||
* values, and if the alpha value is valid, add it to the object."
|
||||
*
|
||||
* The function is a bit more complicated than that, but that's the gist of it
|
||||
* @param red - The red value of the color.
|
||||
* @param green - 0-255
|
||||
* @param blue - The blue value of the color.
|
||||
* @param alpha - The alpha value of the color.
|
||||
* @returns An object with the properties red, green, blue, and alpha.
|
||||
*/
|
||||
export default function setRGBA(red, green, blue, alpha) {
|
||||
if (isValidRGBValue(red) && isValidRGBValue(green) && isValidRGBValue(blue)) {
|
||||
const color = {
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
// since there is so much code in the component, we have moved it to a separate file
|
||||
import offlineImages from './offlineImages.json';
|
||||
|
||||
/**
|
||||
* If the URL starts with `data:video/` or ends with `.mp4`, `.webm`, or `.ogg`, then it's a video.
|
||||
* @param url - The URL of the file to be checked.
|
||||
* @returns A function that takes a url and returns a boolean.
|
||||
*/
|
||||
export function videoCheck(url) {
|
||||
return (
|
||||
url.startsWith('data:video/') ||
|
||||
|
@ -10,8 +15,19 @@ export function videoCheck(url) {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* It gets a random photographer from the offlineImages.json file, then gets a random image from that
|
||||
* photographer, and returns an object with the image's URL, type, and photoInfo.
|
||||
* </code>
|
||||
* @param type - 'background' or 'thumbnail'
|
||||
* @returns An object with the following properties:
|
||||
* url: A string that is the path to the image.
|
||||
* type: A string that is the type of image.
|
||||
* photoInfo: An object with the following properties:
|
||||
* offline: A boolean that is true.
|
||||
* credit: A string that is the name of the photographer.
|
||||
*/
|
||||
export function offlineBackground(type) {
|
||||
// Get all photographers from the keys in offlineImages.json
|
||||
const photographers = Object.keys(offlineImages);
|
||||
const photographer = photographers[Math.floor(Math.random() * photographers.length)];
|
||||
|
||||
|
@ -33,6 +49,10 @@ export function offlineBackground(type) {
|
|||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes a gradient object and returns a style object
|
||||
* @returns An object with two properties: type and style.
|
||||
*/
|
||||
function gradientStyleBuilder({ type, angle, gradient }) {
|
||||
// Note: Append the gradient for additional browser support.
|
||||
const steps = gradient?.map((v) => `${v.colour} ${v.stop}%`);
|
||||
|
@ -44,6 +64,10 @@ function gradientStyleBuilder({ type, angle, gradient }) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* It gets the gradient settings from localStorage, parses it, and returns the gradient style.
|
||||
* @returns A string.
|
||||
*/
|
||||
export function getGradient() {
|
||||
const customBackgroundColour = localStorage.getItem('customBackgroundColour') || {
|
||||
angle: '180',
|
||||
|
@ -72,6 +96,11 @@ export function getGradient() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns a random colour or random gradient as a style object
|
||||
* @param type - The type of the style. This is used to determine which style builder to use.
|
||||
* @returns An object with two properties: type and style.
|
||||
*/
|
||||
export function randomColourStyleBuilder(type) {
|
||||
// randomColour based on https://stackoverflow.com/a/5092872
|
||||
const randomColour = () =>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/**
|
||||
* If the number is between 3 and 20, return the number with the suffix "th". Otherwise, return the
|
||||
* number with the suffix "st", "nd", "rd", or "th" depending on the last digit of the number
|
||||
* @param d - The day of the month.
|
||||
* @returns the day of the month with the appropriate suffix.
|
||||
*/
|
||||
export function nth(d) {
|
||||
if (d > 3 && d < 21) {
|
||||
return d + 'th';
|
||||
|
@ -15,6 +21,12 @@ export function nth(d) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes a date and a timezone and returns a new date object with the timezone applied.
|
||||
* @param date - The date you want to convert.
|
||||
* @param tz - The timezone you want to convert to.
|
||||
* @returns A new Date object with the timezone set to the timezone passed in.
|
||||
*/
|
||||
export function convertTimezone(date, tz) {
|
||||
return new Date(
|
||||
(typeof date === 'string' ? new Date(date) : date).toLocaleString('en-US', {
|
||||
|
|
|
@ -1,13 +1,28 @@
|
|||
// one day it might be a good idea to replace all this with redux, but it'd take
|
||||
// a lot of rewriting
|
||||
export default class EventBus {
|
||||
static listeners = {};
|
||||
|
||||
/**
|
||||
* The on function adds an event listener to the document, and then pushes the callback function into
|
||||
* the listeners array.
|
||||
* @param event - The event name
|
||||
* @param callback - The function to be called when the event is triggered.
|
||||
*/
|
||||
static on(event, callback) {
|
||||
document.addEventListener(event, (e) => {
|
||||
callback(e.detail);
|
||||
});
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push(callback);
|
||||
}
|
||||
|
||||
static dispatch(event, data) {
|
||||
/**
|
||||
* It creates a new custom event, and dispatches it
|
||||
* @param event - The name of the event you want to emit.
|
||||
* @param data - The data you want to pass to the event.
|
||||
*/
|
||||
static emit(event, data) {
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(event, {
|
||||
detail: data,
|
||||
|
@ -15,7 +30,107 @@ export default class EventBus {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* It removes an event listener from the document and removes the callback from the listeners array
|
||||
* @param event - The event to listen for.
|
||||
* @param callback - The function to be called when the event is triggered.
|
||||
*/
|
||||
static off(event, callback) {
|
||||
document.removeEventListener(event, callback);
|
||||
if (this.listeners[event]) {
|
||||
this.listeners[event] = this.listeners[event].filter((listener) => listener !== callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The once function takes an event and a callback, and then adds a listener to the event that calls
|
||||
* the callback with the event's detail, and then removes the listener.
|
||||
* @param event - The event name
|
||||
* @param callback - The function to be called when the event is triggered.
|
||||
*/
|
||||
static once(event, callback) {
|
||||
const listener = (e) => {
|
||||
callback(e.detail);
|
||||
this.off(event, listener);
|
||||
};
|
||||
document.addEventListener(event, listener);
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].push({ callback, listener });
|
||||
}
|
||||
|
||||
/**
|
||||
* It adds a listener to the beginning of the event listener queue.
|
||||
* @param event - The name of the event to listen for.
|
||||
* @param callback - The function to be called when the event is triggered.
|
||||
*/
|
||||
static prepend(event, callback) {
|
||||
const listener = (e) => {
|
||||
callback(e.detail);
|
||||
};
|
||||
document.addEventListener(
|
||||
event,
|
||||
listener,
|
||||
true, // set `useCapture` to `true` to insert the listener at the beginning
|
||||
);
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].unshift({ callback, listener });
|
||||
}
|
||||
|
||||
/**
|
||||
* It adds an event listener to the document that will be called before any other event listeners for
|
||||
* the same event
|
||||
* @param event - The name of the event to listen for.
|
||||
* @param callback - The function to be called when the event is triggered.
|
||||
*/
|
||||
static prependOnce(event, callback) {
|
||||
const listener = (e) => {
|
||||
callback(e.detail);
|
||||
this.off(event, listener);
|
||||
};
|
||||
document.addEventListener(
|
||||
event,
|
||||
listener,
|
||||
true, // set `useCapture` to `true` to insert the listener at the beginning
|
||||
);
|
||||
if (!this.listeners[event]) {
|
||||
this.listeners[event] = [];
|
||||
}
|
||||
this.listeners[event].unshift({ callback, listener });
|
||||
}
|
||||
|
||||
/**
|
||||
* If the event exists, return the listeners for that event, otherwise return an empty array.
|
||||
* @param event - The event name.
|
||||
* @returns An array of listeners for the event.
|
||||
*/
|
||||
static getListeners(event) {
|
||||
if (this.listeners[event]) {
|
||||
return this.listeners[event];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns an array of all the event names that have listeners attached to them.
|
||||
* @returns An array of the keys of the listeners object.
|
||||
*/
|
||||
static eventNames() {
|
||||
return Object.keys(this.listeners);
|
||||
}
|
||||
|
||||
/**
|
||||
* It removes all event listeners from the document.
|
||||
*/
|
||||
static removeAllListeners() {
|
||||
Object.keys(this.listeners).forEach((event) => {
|
||||
this.listeners[event].forEach(({ listener }) => {
|
||||
document.removeEventListener(event, listener);
|
||||
});
|
||||
});
|
||||
this.listeners = {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ export function install(type, input, sideload) {
|
|||
}
|
||||
localStorage.setItem('backgroundType', 'photo_pack');
|
||||
localStorage.removeItem('backgroundchange');
|
||||
EventBus.dispatch('refresh', 'background');
|
||||
EventBus.emit('refresh', 'background');
|
||||
// TODO: make this legitimately good and work without a reload - currently we just refresh
|
||||
sleep(4000);
|
||||
window.location.reload();
|
||||
|
@ -66,7 +66,7 @@ export function install(type, input, sideload) {
|
|||
}
|
||||
localStorage.setItem('quoteType', 'quote_pack');
|
||||
localStorage.removeItem('quotechange');
|
||||
EventBus.dispatch('refresh', 'quote');
|
||||
EventBus.emit('refresh', 'quote');
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -121,7 +121,7 @@ export function uninstall(type, name) {
|
|||
localStorage.removeItem('quote_packs');
|
||||
}
|
||||
localStorage.removeItem('quotechange');
|
||||
EventBus.dispatch('refresh', 'marketplacequoteuninstall');
|
||||
EventBus.emit('refresh', 'marketplacequoteuninstall');
|
||||
break;
|
||||
|
||||
case 'photos':
|
||||
|
@ -142,7 +142,7 @@ export function uninstall(type, name) {
|
|||
localStorage.removeItem('photo_packs');
|
||||
}
|
||||
localStorage.removeItem('backgroundchange');
|
||||
EventBus.dispatch('refresh', 'marketplacebackgrounduninstall');
|
||||
EventBus.emit('refresh', 'marketplacebackgrounduninstall');
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -4,6 +4,10 @@ import experimentalInit from '../experimental';
|
|||
import defaultSettings from 'modules/default_settings.json';
|
||||
import languages from 'modules/languages.json';
|
||||
|
||||
/**
|
||||
* It sets the default settings for the extension
|
||||
* @param reset - boolean
|
||||
*/
|
||||
export function setDefaultSettings(reset) {
|
||||
localStorage.clear();
|
||||
defaultSettings.forEach((element) => localStorage.setItem(element.name, element.value));
|
||||
|
@ -31,6 +35,10 @@ export function setDefaultSettings(reset) {
|
|||
localStorage.setItem('firstRun', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* It loads the settings from localStorage and applies them to the page.
|
||||
* @param hotreload - boolean
|
||||
*/
|
||||
export function loadSettings(hotreload) {
|
||||
switch (localStorage.getItem('theme')) {
|
||||
case 'dark':
|
||||
|
@ -157,8 +165,11 @@ export function loadSettings(hotreload) {
|
|||
`);
|
||||
}
|
||||
|
||||
// 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
|
||||
/**
|
||||
* 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.
|
||||
* @returns the result of the setDefaultSettings() function.
|
||||
*/
|
||||
export function moveSettings() {
|
||||
const currentSettings = Object.keys(localStorage);
|
||||
if (currentSettings.length === 0) {
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import variables from 'modules/variables';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
/**
|
||||
* It creates a link to a file, and then clicks it
|
||||
* @param data - the data you want to save
|
||||
* @param [filename=file] - the name of the file to be saved
|
||||
* @param [type=text/json] - the type of file you want to save.
|
||||
*/
|
||||
export function saveFile(data, filename = 'file', type = 'text/json') {
|
||||
if (typeof data === 'object') {
|
||||
data = JSON.stringify(data, undefined, 4);
|
||||
|
@ -36,6 +42,9 @@ export function saveFile(data, filename = 'file', type = 'text/json') {
|
|||
a.dispatchEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes all the settings from localStorage and saves them to a file
|
||||
*/
|
||||
export function exportSettings() {
|
||||
const settings = {};
|
||||
|
||||
|
@ -49,6 +58,11 @@ export function exportSettings() {
|
|||
variables.stats.postEvent('tab', 'Settings exported');
|
||||
}
|
||||
|
||||
/**
|
||||
* It takes a JSON file of Mue settings, parses it, and then sets the localStorage values to the values in the
|
||||
* file.
|
||||
* @param e - The JSON settings string to import
|
||||
*/
|
||||
export function importSettings(e) {
|
||||
const content = JSON.parse(e);
|
||||
|
||||
|
@ -60,6 +74,11 @@ export function importSettings(e) {
|
|||
variables.stats.postEvent('tab', 'Settings imported');
|
||||
}
|
||||
|
||||
/**
|
||||
* It returns an array of objects with a value and label property for the Mue sliders.
|
||||
* @param type - The type of slider you want to use.
|
||||
* @returns An object with keys of either zoom, toast, background or experimental.
|
||||
*/
|
||||
export function values(type) {
|
||||
const marks = {
|
||||
zoom: [
|
||||
|
@ -98,5 +117,5 @@ export function values(type) {
|
|||
],
|
||||
};
|
||||
|
||||
return marks[type];
|
||||
return marks[type] || [];
|
||||
}
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
export default class Stats {
|
||||
/**
|
||||
* It takes two arguments, a type and a name, and then it increments the value of the name in the type
|
||||
* object in localStorage
|
||||
* @param type - The type of event you want to track. This can be anything you want, but I recommend
|
||||
* using something like "click" or "hover"
|
||||
* @param name - The name of the event.
|
||||
*/
|
||||
static async postEvent(type, name) {
|
||||
const value = name.toLowerCase().replaceAll(' ', '-');
|
||||
|
||||
|
@ -19,6 +26,9 @@ export default class Stats {
|
|||
localStorage.setItem('statsData', JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* It increments the value of the key 'tabs-opened' in the object stored in localStorage by 1.
|
||||
*/
|
||||
static async tabLoad() {
|
||||
const data = JSON.parse(localStorage.getItem('statsData'));
|
||||
data['tabs-opened'] = data['tabs-opened'] + 1 || 1;
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
import I18n from '@eartharoid/i18n';
|
||||
|
||||
import * as de_DE from '../translations/de_DE.json';
|
||||
import * as en_GB from '../translations/en_GB.json';
|
||||
import * as en_US from '../translations/en_US.json';
|
||||
import * as es from '../translations/es.json';
|
||||
import * as es_419 from '../translations/es_419.json';
|
||||
import * as fr from '../translations/fr.json';
|
||||
import * as nl from '../translations/nl.json';
|
||||
import * as no from '../translations/no.json';
|
||||
import * as ru from '../translations/ru.json';
|
||||
import * as zh_CN from '../translations/zh_CN.json';
|
||||
import * as id_ID from '../translations/id_ID.json';
|
||||
import * as tr_TR from '../translations/tr_TR.json';
|
||||
import * as pt_BR from '../translations/pt_BR.json';
|
||||
|
||||
/**
|
||||
* Initialise the i18n object.
|
||||
* The i18n object is then returned.
|
||||
* @param locale - The locale to use.
|
||||
* @returns The i18n object.
|
||||
*/
|
||||
export default function initTranslations(locale) {
|
||||
const i18n = new I18n(locale, {
|
||||
de_DE,
|
||||
en_GB,
|
||||
en_US,
|
||||
es,
|
||||
es_419,
|
||||
fr,
|
||||
nl,
|
||||
no,
|
||||
ru,
|
||||
zh_CN,
|
||||
id_ID,
|
||||
tr_TR,
|
||||
pt_BR,
|
||||
de_DE: import('../translations/de_DE.json'),
|
||||
en_GB: import('../translations/en_GB.json'),
|
||||
en_US: import('../translations/en_US.json'),
|
||||
es: import('../translations/es.json'),
|
||||
es_419: import('../translations/es_419.json'),
|
||||
fr: import('../translations/fr.json'),
|
||||
nl: import('../translations/nl.json'),
|
||||
no: import('../translations/no.json'),
|
||||
ru: import('../translations/ru.json'),
|
||||
zh_CN: import('../translations/zh_CN.json'),
|
||||
id_ID: import('../translations/id_ID.json'),
|
||||
tr_TR: import('../translations/tr_TR.json'),
|
||||
pt_BR: import('../translations/pt_BR.json'),
|
||||
});
|
||||
|
||||
return i18n;
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import * as constants from 'modules/constants';
|
||||
import Stats from 'modules/helpers/stats';
|
||||
|
||||
const variables = {
|
||||
language: {},
|
||||
languagecode: '',
|
||||
stats: {
|
||||
tabLoad: () => '',
|
||||
postEvent: () => '',
|
||||
},
|
||||
stats: Stats,
|
||||
constants,
|
||||
};
|
||||
|
||||
|
|
|
@ -61,11 +61,7 @@ const prepareBuilds = () => ({
|
|||
});
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
prepareBuilds(),
|
||||
progress(),
|
||||
],
|
||||
plugins: [react(), prepareBuilds(), progress()],
|
||||
server: {
|
||||
open: true,
|
||||
hmr: {
|
||||
|
|
Loading…
Reference in New Issue