mirror of
https://github.com/mue/mue.git
synced 2026-07-18 14:34:12 +02:00
7.x Structural Changes (#637)
* refactor(files): Initial commit on experimental file structure * refactor(structure): New components system * refactor(structure): Tidy settings' components * Refactor(structure): Component exports and imports * refactor(settings): Use new component imports * feat: unified background.js script * fix(build): Partially, distributions still not ready * feat: critical error on noscript, light theme support for it * fix(background): Critical issue of code making every background #000 * refactor(welcome): Partition into different files + shared components - This took too long and destroyed my sanity --------- Co-authored-by: alexsparkes <turbomarshmello@gmail.com> Co-authored-by: alexsparkes <alexsparkes@gmail.com>
This commit is contained in:
61
src/components/Form/Settings/Checkbox/Checkbox.jsx
Normal file
61
src/components/Form/Settings/Checkbox/Checkbox.jsx
Normal file
@@ -0,0 +1,61 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import { Checkbox as CheckboxUI, FormControlLabel } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
class Checkbox extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
checked: localStorage.getItem(this.props.name) === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = () => {
|
||||
const value = this.state.checked !== true;
|
||||
localStorage.setItem(this.props.name, value);
|
||||
|
||||
this.setState({
|
||||
checked: value,
|
||||
});
|
||||
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
|
||||
variables.stats.postEvent(
|
||||
'setting',
|
||||
`${this.props.name} ${this.state.checked === true ? 'enabled' : 'disabled'}`,
|
||||
);
|
||||
|
||||
if (this.props.element) {
|
||||
if (!document.querySelector(this.props.element)) {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
return localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<FormControlLabel
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Checkbox as default, Checkbox };
|
||||
1
src/components/Form/Settings/Checkbox/index.jsx
Normal file
1
src/components/Form/Settings/Checkbox/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Checkbox';
|
||||
58
src/components/Form/Settings/ChipSelect/ChipSelect.jsx
Normal file
58
src/components/Form/Settings/ChipSelect/ChipSelect.jsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { useState, memo } from 'react';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import OutlinedInput from '@mui/material/OutlinedInput';
|
||||
import InputLabel from '@mui/material/InputLabel';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import FormControl from '@mui/material/FormControl';
|
||||
import Select from '@mui/material/Select';
|
||||
import Chip from '@mui/material/Chip';
|
||||
|
||||
function ChipSelect({ label, options }) {
|
||||
let start = (localStorage.getItem('apiCategories') || '').split(',');
|
||||
if (start[0] === '') {
|
||||
start = [];
|
||||
}
|
||||
|
||||
const [optionsSelected, setoptionsSelected] = useState(start);
|
||||
|
||||
const handleChange = (event) => {
|
||||
const {
|
||||
target: { value },
|
||||
} = event;
|
||||
setoptionsSelected(typeof value === 'string' ? value.split(',') : value);
|
||||
localStorage.setItem('apiCategories', value);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FormControl>
|
||||
<InputLabel id="chipSelect-label">{label}</InputLabel>
|
||||
<Select
|
||||
labelId="chipSelect-label"
|
||||
id="chipSelect"
|
||||
multiple
|
||||
value={optionsSelected}
|
||||
onChange={handleChange}
|
||||
input={<OutlinedInput id="select-multiple-chip" label={label} />}
|
||||
renderValue={(optionsSelected) => (
|
||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
||||
{optionsSelected.map((value) => (
|
||||
<Chip key={value} label={value} />
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<MenuItem key={option.name} value={option.name}>
|
||||
{option.name.charAt(0).toUpperCase() + option.name.slice(1)}{' '}
|
||||
{option.count && `(${option.count})`}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default memo(ChipSelect);
|
||||
1
src/components/Form/Settings/ChipSelect/index.jsx
Normal file
1
src/components/Form/Settings/ChipSelect/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './ChipSelect';
|
||||
76
src/components/Form/Settings/Dropdown/Dropdown.jsx
Normal file
76
src/components/Form/Settings/Dropdown/Dropdown.jsx
Normal file
@@ -0,0 +1,76 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent, createRef } from 'react';
|
||||
import { InputLabel, MenuItem, FormControl, Select } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
class Dropdown extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: localStorage.getItem(this.props.name) || this.props.items[0].value,
|
||||
title: '',
|
||||
};
|
||||
this.dropdown = createRef();
|
||||
}
|
||||
|
||||
onChange = (e) => {
|
||||
const { value } = e.target;
|
||||
|
||||
if (value === variables.getMessage('modals.main.loading')) {
|
||||
return;
|
||||
}
|
||||
|
||||
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
|
||||
|
||||
this.setState({
|
||||
value,
|
||||
});
|
||||
|
||||
if (!this.props.noSetting) {
|
||||
localStorage.setItem(this.props.name, value);
|
||||
localStorage.setItem(this.props.name2, this.props.value2);
|
||||
}
|
||||
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
|
||||
if (this.props.element) {
|
||||
if (!document.querySelector(this.props.element)) {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
return localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
const id = 'dropdown' + this.props.name;
|
||||
const label = this.props.label || '';
|
||||
|
||||
return (
|
||||
<FormControl fullWidth className={id}>
|
||||
<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}
|
||||
>
|
||||
{this.props.items.map(({ value, text }) => (
|
||||
<MenuItem key={id + value} value={value}>
|
||||
{text}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Dropdown as default, Dropdown };
|
||||
1
src/components/Form/Settings/Dropdown/index.jsx
Normal file
1
src/components/Form/Settings/Dropdown/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Dropdown';
|
||||
65
src/components/Form/Settings/FileUpload/FileUpload.jsx
Normal file
65
src/components/Form/Settings/FileUpload/FileUpload.jsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { compressAccurately, filetoDataURL } from 'image-conversion';
|
||||
import { videoCheck } from 'modules/helpers/background/widget';
|
||||
|
||||
class FileUpload extends PureComponent {
|
||||
componentDidMount() {
|
||||
document.getElementById(this.props.id).onchange = (e) => {
|
||||
const reader = new FileReader();
|
||||
const file = e.target.files[0];
|
||||
|
||||
if (this.props.type === 'settings') {
|
||||
reader.readAsText(file, 'UTF-8');
|
||||
reader.onload = (e) => {
|
||||
return this.props.loadFunction(e.target.result);
|
||||
};
|
||||
} else {
|
||||
// background upload
|
||||
const settings = {};
|
||||
|
||||
Object.keys(localStorage).forEach((key) => {
|
||||
settings[key] = localStorage.getItem(key);
|
||||
});
|
||||
|
||||
const settingsSize = new TextEncoder().encode(JSON.stringify(settings)).length;
|
||||
if (videoCheck(file.type) === true) {
|
||||
if (settingsSize + file.size > 4850000) {
|
||||
return toast(variables.getMessage('toasts.no_storage'));
|
||||
}
|
||||
|
||||
return this.props.loadFunction(file);
|
||||
}
|
||||
|
||||
compressAccurately(file, {
|
||||
size: 450,
|
||||
accuracy: 0.9,
|
||||
}).then(async (res) => {
|
||||
if (settingsSize + res.size > 4850000) {
|
||||
return toast(variables.getMessage('toasts.no_storage'));
|
||||
}
|
||||
|
||||
this.props.loadFunction({
|
||||
target: {
|
||||
result: await filetoDataURL(res),
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<input
|
||||
id={this.props.id}
|
||||
type="file"
|
||||
style={{ display: 'none' }}
|
||||
accept={this.props.accept}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { FileUpload as default, FileUpload };
|
||||
1
src/components/Form/Settings/FileUpload/index.jsx
Normal file
1
src/components/Form/Settings/FileUpload/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './FileUpload';
|
||||
87
src/components/Form/Settings/Radio/Radio.jsx
Normal file
87
src/components/Form/Settings/Radio/Radio.jsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import {
|
||||
Radio as RadioUI,
|
||||
RadioGroup,
|
||||
FormControlLabel,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
} from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
import { translations } from 'modules/translations';
|
||||
|
||||
class Radio extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: localStorage.getItem(this.props.name),
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = async (e) => {
|
||||
const { value } = e.target;
|
||||
|
||||
if (value === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.name === 'language') {
|
||||
// old tab name
|
||||
if (localStorage.getItem('tabName') === variables.getMessage('tabname')) {
|
||||
localStorage.setItem('tabName', translations[value.replace('-', '_')].tabname);
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem(this.props.name, value);
|
||||
|
||||
this.setState({
|
||||
value,
|
||||
});
|
||||
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(value);
|
||||
}
|
||||
|
||||
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
|
||||
|
||||
if (this.props.element) {
|
||||
if (!document.querySelector(this.props.element)) {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
return localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<FormControl component="fieldset">
|
||||
<FormLabel
|
||||
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) => (
|
||||
<FormControlLabel
|
||||
value={option.value}
|
||||
control={<RadioUI />}
|
||||
label={option.name}
|
||||
key={option.name}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Radio as default, Radio };
|
||||
1
src/components/Form/Settings/Radio/index.jsx
Normal file
1
src/components/Form/Settings/Radio/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Radio';
|
||||
88
src/components/Form/Settings/Slider/Slider.jsx
Normal file
88
src/components/Form/Settings/Slider/Slider.jsx
Normal file
@@ -0,0 +1,88 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { Slider } from '@mui/material';
|
||||
import { MdRefresh } from 'react-icons/md';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
class SliderComponent extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: localStorage.getItem(this.props.name) || this.props.default,
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = (e, text) => {
|
||||
let { value } = e.target;
|
||||
value = Number(value);
|
||||
|
||||
if (text) {
|
||||
if (value === '') {
|
||||
return this.setState({
|
||||
value: 0,
|
||||
});
|
||||
}
|
||||
|
||||
if (value > this.props.max) {
|
||||
value = this.props.max;
|
||||
}
|
||||
|
||||
if (value < this.props.min) {
|
||||
value = this.props.min;
|
||||
}
|
||||
}
|
||||
|
||||
localStorage.setItem(this.props.name, value);
|
||||
this.setState({
|
||||
value,
|
||||
});
|
||||
|
||||
if (this.props.element) {
|
||||
if (!document.querySelector(this.props.element)) {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
return localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
resetItem = () => {
|
||||
this.handleChange({
|
||||
target: {
|
||||
value: this.props.default || '',
|
||||
},
|
||||
});
|
||||
toast(variables.getMessage('toasts.reset'));
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<span className={'sliderTitle'}>
|
||||
{this.props.title}
|
||||
<span>{Number(this.state.value)}</span>
|
||||
<span className="link" onClick={this.resetItem}>
|
||||
<MdRefresh />
|
||||
{variables.getMessage('modals.main.settings.buttons.reset')}
|
||||
</span>
|
||||
</span>
|
||||
<Slider
|
||||
value={Number(this.state.value)}
|
||||
onChange={this.handleChange}
|
||||
valueLabelDisplay="auto"
|
||||
default={Number(this.props.default)}
|
||||
min={Number(this.props.min)}
|
||||
max={Number(this.props.max)}
|
||||
step={Number(this.props.step) || 1}
|
||||
getAriaValueText={(value) => `${value}`}
|
||||
marks={this.props.marks || []}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { SliderComponent as default, SliderComponent as Slider };
|
||||
1
src/components/Form/Settings/Slider/index.jsx
Normal file
1
src/components/Form/Settings/Slider/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Slider';
|
||||
56
src/components/Form/Settings/Switch/Switch.jsx
Normal file
56
src/components/Form/Settings/Switch/Switch.jsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import { Switch as SwitchUI, FormControlLabel } from '@mui/material';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
class Switch extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
checked: localStorage.getItem(this.props.name) === 'true',
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = () => {
|
||||
const value = this.state.checked !== true;
|
||||
localStorage.setItem(this.props.name, value);
|
||||
|
||||
this.setState({
|
||||
checked: value,
|
||||
});
|
||||
|
||||
variables.stats.postEvent(
|
||||
'setting',
|
||||
`${this.props.name} ${this.state.checked === true ? 'enabled' : 'disabled'}`,
|
||||
);
|
||||
|
||||
if (this.props.element) {
|
||||
if (!document.querySelector(this.props.element)) {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
return localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<SwitchUI
|
||||
name={this.props.name}
|
||||
color="primary"
|
||||
checked={this.state.checked}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
}
|
||||
label={this.props.header ? '' : this.props.text}
|
||||
labelPlacement="start"
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Switch as default, Switch };
|
||||
1
src/components/Form/Settings/Switch/index.jsx
Normal file
1
src/components/Form/Settings/Switch/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Switch';
|
||||
84
src/components/Form/Settings/Text/Text.jsx
Normal file
84
src/components/Form/Settings/Text/Text.jsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { TextField } from '@mui/material';
|
||||
import { MdRefresh } from 'react-icons/md';
|
||||
|
||||
import EventBus from 'modules/helpers/eventbus';
|
||||
|
||||
class Text extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
value: localStorage.getItem(this.props.name) || '',
|
||||
};
|
||||
}
|
||||
|
||||
handleChange = (e) => {
|
||||
let { value } = e.target;
|
||||
|
||||
// Alex wanted font to work with montserrat and Montserrat, so I made it work
|
||||
if (this.props.upperCaseFirst === true) {
|
||||
value = value.charAt(0).toUpperCase() + value.slice(1);
|
||||
}
|
||||
|
||||
localStorage.setItem(this.props.name, value);
|
||||
this.setState({
|
||||
value,
|
||||
});
|
||||
|
||||
if (this.props.element) {
|
||||
if (!document.querySelector(this.props.element)) {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
return localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}
|
||||
|
||||
EventBus.emit('refresh', this.props.category);
|
||||
};
|
||||
|
||||
resetItem = () => {
|
||||
this.handleChange({
|
||||
target: {
|
||||
value: this.props.default || '',
|
||||
},
|
||||
});
|
||||
toast(variables.getMessage('toasts.reset'));
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
{this.props.textarea === true ? (
|
||||
<TextField
|
||||
label={this.props.title}
|
||||
value={this.state.value}
|
||||
onChange={this.handleChange}
|
||||
varient="outlined"
|
||||
className={this.props.customcss ? 'customcss' : ''}
|
||||
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 }}
|
||||
placeholder={this.props.placeholder || ''}
|
||||
/>
|
||||
)}
|
||||
<span className="link" onClick={this.resetItem}>
|
||||
<MdRefresh />
|
||||
{variables.getMessage('modals.main.settings.buttons.reset')}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { Text as default, Text };
|
||||
1
src/components/Form/Settings/Text/index.jsx
Normal file
1
src/components/Form/Settings/Text/index.jsx
Normal file
@@ -0,0 +1 @@
|
||||
export * from './Text';
|
||||
8
src/components/Form/Settings/index.jsx
Normal file
8
src/components/Form/Settings/index.jsx
Normal file
@@ -0,0 +1,8 @@
|
||||
export * from './Checkbox';
|
||||
export * from './ChipSelect';
|
||||
export * from './Dropdown';
|
||||
export * from './FileUpload';
|
||||
export * from './Radio';
|
||||
export * from './Slider';
|
||||
export * from './Switch';
|
||||
export * from './Text';
|
||||
Reference in New Issue
Block a user