feat: new sliders, dropdowns, text inputs, update settings ui, fix language bug

Co-authored-by: Alex Sparkes <turbomarshmello@gmail.com>
This commit is contained in:
David Ralph
2021-10-12 22:18:47 +01:00
parent 14121fb975
commit bc8ef0d9f2
43 changed files with 213 additions and 535 deletions

View File

@@ -4,7 +4,6 @@ import Modal from 'react-modal';
import Hotkeys from 'react-hot-keys';
import Main from './main/Main';
import Feedback from './feedback/Feedback';
import Navbar from '../widgets/navbar/Navbar';
import EventBus from 'modules/helpers/eventbus';
@@ -75,9 +74,6 @@ export default class Modals extends PureComponent {
<Modal closeTimeoutMS={300} onRequestClose={() => this.closeWelcome()} isOpen={this.state.welcomeModal} className='Modal welcomemodal mainModal' overlayClassName='Overlay welcomeoverlay' shouldCloseOnOverlayClick={false} ariaHideApp={false}>
<Welcome modalClose={() => this.closeWelcome()}/>
</Modal>
<Modal closeTimeoutMS={300} onRequestClose={() => this.toggleModal('feedbackModal', false)} isOpen={this.state.feedbackModal} className='Modal mainModal' overlayClassName='Overlay' ariaHideApp={false}>
<Feedback modalClose={() => this.toggleModal('feedbackModal', false)}/>
</Modal>
</Suspense>
{variables.keybinds.toggleModal && variables.keybinds.toggleModal !== '' ? <Hotkeys keyName={variables.keybinds.toggleModal} onKeyDown={() => this.toggleModal('mainModal', (this.state.mainModal === true ? false : true))}/> : null}
</>

View File

@@ -1,109 +0,0 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import './feedback.scss';
export default class FeedbackModal extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
constructor() {
super();
this.state = {
question_one: 5,
question_two: {
value: '',
error: ''
},
question_three: 5,
question_four: {
value: '',
error: ''
},
formsubmit: ''
};
}
async submitForm(e) {
e.preventDefault();
let question_two_error, question_four_error;
if (this.state.question_two.value.length <= 0) {
question_two_error = this.getMessage('modals.feedback.not_filled');
}
if (this.state.question_four.value.length <= 0) {
question_four_error = this.getMessage('modals.feedback.not_filled');
}
if (question_two_error || question_four_error) {
this.setState({
question_two: {
error: question_two_error
},
question_four: {
error: question_four_error
}
});
} else {
this.setState({
question_two: {
error: ''
},
question_four: {
error: ''
}
});
await fetch(variables.constants.FEEDBACK_FORM, {
method: 'POST'
});
this.setState({
formsubmit: this.getMessage('modals.feedback.success')
});
setTimeout(() => {
this.props.modalClose();
}, 5000);
}
}
render() {
return (
<div className='feedback'>
<h1>{this.getMessage('modals.feedback.title')}</h1>
<span className='closeModal' onClick={this.props.modalClose}>&times;</span>
<form>
<input type='hidden' name='version' value={variables.constants.VERSION} />
<div className='question'>
<label>{this.getMessage('modals.feedback.question_one')}</label>
<br/><br/>
<label className='values'>0</label>
<input className='range' type='range' min='0' max='10' name='questionone' value={this.state.question_one} onChange={(e) => this.setState({ question_one: e.target.value })}/>
<label className='values'>10 ({this.state.question_one})</label>
</div>
<div className='question'>
<label>{this.getMessage('modals.feedback.question_two')}</label>
<textarea name='questiontwo' onChange={(e) => this.setState({ question_two: { value: e.target.value }})}/>
<p className='feedbackerror'>{this.state.question_two.error}</p>
</div>
<div className='question'>
<label>{this.getMessage('modals.feedback.question_three')}</label>
<br/><br/>
<label className='values'>0</label>
<input className='range' type='range' min='0' max='10' name='questionthree' value={this.state.question_three} onChange={(e) => this.setState({ question_three: e.target.value })}/>
<label className='values'>10 ({this.state.question_three})</label>
</div>
<div className='question'>
<label>{this.getMessage('modals.feedback.question_four')}</label>
<textarea name='questionfour' value={this.state.question_four.value} onChange={(e) => this.setState({ question_four: { value: e.target.value }})}/>
<p className='feedbackerror'>{this.state.question_four.error}</p>
</div>
<p>{this.state.formsubmit}</p>
<button onClick={(e) => this.submitForm(e)}>{this.getMessage('modals.feedback.submit')}</button>
</form>
</div>
);
}
}

View File

@@ -1,72 +0,0 @@
@import '../main/scss/index.scss';
#feedbackmodal {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 400px;
height: 100px;
}
.feedback {
width: 400px;
padding: 5px;
h1,
.closeModal {
font-size: 2.5em;
}
span {
font-size: 6em;
}
button {
width: 50%;
border-radius: 48px;
outline: none;
border: none;
padding: 15px 20px;
font-size: 1.5em;
background: #5352ed;
color: #fff;
text-transform: uppercase;
cursor: pointer;
&:hover {
background: rgba(83, 82, 237, 0.8);
}
}
input[type=text] {
width: 100%;
font-size: 1em;
}
input[type=range] {
margin-left: 20px;
margin-right: 20px;
vertical-align: middle;
}
label.values {
font-weight: 700;
}
textarea {
width: 80%;
padding: 10px;
background-color: var(--sidebar) !important;
}
.question {
margin-bottom: 20px;
}
.feedbackerror {
color: red;
}
}

View File

@@ -1,3 +1,5 @@
import variables from 'modules/variables';
export default function Items({ items, toggleFunction }) {
return (
<div className='items'>

View File

@@ -224,7 +224,6 @@ export default class Marketplace extends PureComponent {
<option value='a-z'>{this.getMessage('modals.main.addons.sort.a_z')}</option>
<option value='z-a'>{this.getMessage('modals.main.addons.sort.z_a')}</option>
</Dropdown>
<br/>
<Items items={this.state.items} toggleFunction={(input) => this.toggle('item', input)} />
</>
);

View File

@@ -129,3 +129,13 @@ h3 {
h5 {
font-size: 0.8rem;
}
.tab-content {
hr {
height: 5px;
background: rgba(196, 196, 196, 0.74);
outline: none;
border: none;
margin: 50px 0 30px 0;
}
}

View File

@@ -1,25 +1,12 @@
@import 'modules/dropdown';
@import 'modules/resetmodal';
@import 'modules/material-ui';
@import 'modules/slider';
@import 'modules/reminder';
@import 'modules/textarea';
@import 'modules/tabs/about';
@import 'modules/tabs/changelog';
@import 'modules/tabs/order';
input {
/* text input */
&[type=text] {
width: 200px;
color: var(--modal-text);
background: var(--sidebar);
border: none;
padding: 10px 10px;
border-radius: 5px;
}
/* colour picker */
&[type=color] {
border-radius: 100%;
@@ -64,12 +51,13 @@ input {
/* date picker */
&[type=date] {
width: 200px;
width: 280px;
color: var(--modal-text);
background: var(--sidebar);
border: none;
padding: 10px 10px;
border-radius: 5px;
background: var(--background);
border: solid white 1px;
padding: 15px 20px;
border-radius: 4px;
display: flex !important;
}
}

View File

@@ -1,37 +0,0 @@
select {
margin-left: 10px;
width: 120px;
color: var(--modal-text);
background: var(--sidebar);
border: none;
padding: 10px 10px;
border-radius: 5px;
}
// firefox dropdown
@supports (-moz-appearance: none) {
select {
-moz-appearance: none !important;
background: url("data:image/svg+xml;utf8,<svg fill='black' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>") right center no-repeat, var(--sidebar) !important;
}
.dark select {
background: url("data:image/svg+xml;utf8,<svg fill='white' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>") right center no-repeat, var(--sidebar) !important;
}
option {
font: -moz-pull-down-menu !important;
}
}
// safari dropdown
@supports (-webkit-hyphens: none) {
select {
-webkit-appearance: none !important;
background: url("data:image/svg+xml;utf8,<svg fill='black' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>") right center no-repeat, var(--sidebar) !important;
}
.dark select {
background: url("data:image/svg+xml;utf8,<svg fill='white' height='24' viewBox='0 0 24 24' width='24' xmlns='http://www.w3.org/2000/svg'><path d='M7 10l5 5 5-5z'/><path d='M0 0h24v24H0z' fill='none'/></svg>") right center no-repeat, var(--sidebar) !important;
}
}

View File

@@ -7,6 +7,7 @@
.PrivateSwitchBase-input-4,
.MuiRadio-root,
.aboutLink,
.MuiSlider-colorPrimary,
legend {
color: var(--modal-text) !important;
}
@@ -46,3 +47,42 @@ legend {
font-weight: bold;
font-size: 1rem;
}
.MuiSlider-root {
margin-bottom: 30px !important;
}
.MuiOutlinedInput-notchedOutline {
border-color: var(--modal-text) !important;
}
.MuiFormLabel-root-MuiInputLabel-root {
color: var(--modal-text) !important;
}
.MuiInputLabel-root,
.MuiSlider-markLabel,
.MuiInputLabel-root,
.MuiSelect-icon,
.MuiSelect-select,
.Mui-focused,
legend,
.MuiOutlinedInput-input {
color: var(--modal-text) !important;
}
.MuiMenu-list {
background-color: var(--background) !important;
color: var(--modal-text) !important;
}
.Mui-selected {
background-color: var(--tab-active) !important;
}
.MuiTextField-root,
.MuiFormControl-root,
.MuiSlider-root {
width: 300px !important;
display: flex !important;
}

View File

@@ -1,46 +0,0 @@
.range {
-webkit-appearance: none;
width: 200px;
height: 12px;
border-radius: 12px;
outline: none;
background: var(--sidebar);
box-shadow: 0 0 100px rgba(0, 0, 0, 0.3);
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 12px;
background: var(--modal-text);
cursor: pointer;
}
&::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 12px;
border: 0;
background: var(--modal-text);
cursor: pointer;
}
}
.sliderText {
color: var(--modal-text);
background: none;
border: none;
border-radius: 0;
font-size: 1rem;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type=number] {
-moz-appearance: textfield;
}

View File

@@ -1,11 +0,0 @@
.settingsTextarea {
font-family: Consolas !important;
padding: 15px;
border-radius: 15px;
background-color: var(--sidebar) !important;
border: none;
margin-left: 0;
width: 400px;
height: 200px;
max-width: 60%;
}

View File

@@ -1,5 +1,6 @@
import variables from 'modules/variables';
import { PureComponent, createRef } from 'react';
import { InputLabel, MenuItem, FormControl, Select } from '@mui/material';
import EventBus from 'modules/helpers/eventbus';
@@ -7,16 +8,12 @@ export default class Dropdown extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || '',
value: localStorage.getItem(this.props.name) || this.props.children[0].props.value,
title: ''
};
this.dropdown = createRef();
}
getLabel() {
return this.props.label ? <label>{this.props.label}</label> : null;
}
onChange = (e) => {
const { value } = e.target;
@@ -27,8 +24,7 @@ export default class Dropdown extends PureComponent {
variables.stats.postEvent('setting', `${this.props.name} from ${this.state.value} to ${value}`);
this.setState({
value,
title: e.target[e.target.selectedIndex].text
value
});
if (!this.props.noSetting) {
@@ -49,21 +45,19 @@ export default class Dropdown extends PureComponent {
EventBus.dispatch('refresh', this.props.category);
}
// todo: find a better way to do this
componentDidMount() {
this.setState({
title: this.dropdown.current[this.dropdown.current.selectedIndex].text
});
}
render() {
const id = 'dropdown' + this.props.name;
const label = this.props.label || '';
return (
<>
{this.getLabel()}
<select id={this.props.name} ref={this.dropdown} value={this.state.value} onChange={this.onChange} style={{ width: `${(8*this.state.title.length) + 50}px` }}>
{this.props.children}
</select>
</>
<FormControl fullWidth>
<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.manual ? this.props.children : this.props.children.map((e, index) => {
return e ? <MenuItem key={index} value={e.props ? e.props.value : ''}>{e.props ? e.props.children : ''}</MenuItem> : null
})}
</Select>
</FormControl>
);
}
}

View File

@@ -5,6 +5,8 @@ import { PureComponent } from 'react';
import Slider from './Slider';
import Switch from './Switch';
import { values } from 'modules/helpers/settings/modals';
export default class Header extends PureComponent {
render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
@@ -14,8 +16,8 @@ export default class Header extends PureComponent {
<h2>{this.props.title}</h2>
<Switch name={this.props.setting} text={getMessage('modals.main.settings.enabled')} category={this.props.category} element={this.props.element || null} />
{this.props.zoomSetting ?
<><Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.widget_zoom')} name={this.props.zoomSetting} min='10' max='400' default='100' display='%' category={this.props.zoomCategory || this.props.category} /><br/><br/></>
: null}
<><Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.widget_zoom')} name={this.props.zoomSetting} min='10' max='400' default='100' display='%' marks={values('zoom')} category={this.props.zoomCategory || this.props.category}/></>
: <br/>}
</>
);
}

View File

@@ -1,5 +1,6 @@
import variables from 'modules/variables';
import { Cancel } from '@mui/icons-material';
import { TextField } from '@mui/material';
export default function KeybindInput(props) {
const value = props.state[props.setting];
@@ -17,7 +18,7 @@ export default function KeybindInput(props) {
return (
<>
<p>{props.name}</p>
<input type='text' onClick={() => props.action('listen', props.setting)} value={value || variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.keybinds.click_to_record')} readOnly/>
<TextField onClick={() => props.action('listen', props.setting)} value={value || variables.language.getMessage(variables.languagecode, 'modals.main.settings.sections.keybinds.click_to_record')} readOnly spellCheck={false} varient='outlined' />
{getButton()}
</>
);

View File

@@ -1,22 +1,21 @@
// todo: find a better method to do width of number input
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { Slider } from '@mui/material';
import EventBus from 'modules/helpers/eventbus';
export default class Slider extends PureComponent {
export default class SliderComponent extends PureComponent {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem(this.props.name) || this.props.default,
numberWidth: localStorage.getItem(this.props.name) ? ((localStorage.getItem(this.props.name).length + 1) * ((this.props.toast === true) ? 7.75 : 7)) : 32
value: localStorage.getItem(this.props.name) || this.props.default
};
this.widthCalculation = (this.props.toast === true) ? 7.75 : 7;
}
handleChange = (e, text) => {
let { value } = e.target;
value = Number(value);
if (text) {
if (value === '') {
@@ -25,19 +24,18 @@ export default class Slider extends PureComponent {
});
}
if (Number(value) > this.props.max) {
if (value > this.props.max) {
value = this.props.max;
}
if (Number(value) < this.props.min) {
if (value < this.props.min) {
value = this.props.min;
}
}
localStorage.setItem(this.props.name, value);
this.setState({
value,
numberWidth: ((value.length + 1) * this.widthCalculation)
value
});
if (this.props.element) {
@@ -60,12 +58,20 @@ export default class Slider extends PureComponent {
}
render() {
const text = <input className='sliderText' type='number' min={this.props.min} max={this.props.max} onChange={(e) => this.handleChange(e, 'text')} value={this.state.value} style={{ width: this.state.numberWidth }}/>;
return (
<>
<p>{this.props.title} ({text}{this.props.display}) <span className='modalLink' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span></p>
<input className='range' type='range' min={this.props.min} max={this.props.max} step={this.props.step || 1} value={this.state.value} onChange={this.handleChange} />
<p>{this.props.title}<span className='modalLink' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span></p>
<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={this.props.step || 1}
getAriaValueText={(value) => `${value}`}
marks={this.props.marks || []}
/>
</>
);
}

View File

@@ -40,7 +40,6 @@ export default class Switch extends PureComponent {
label={this.props.text}
labelPlacement='start'
/>
<br/>
</>
);
}

View File

@@ -1,6 +1,7 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { TextField } from '@mui/material';
import EventBus from 'modules/helpers/eventbus';
@@ -47,11 +48,11 @@ export default class Text extends PureComponent {
render() {
return (
<>
<p>{this.props.title} <span className='modalLink' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span></p>
{(this.props.textarea === true) ?
<textarea className='settingsTextarea' spellCheck={false} value={this.state.value} onChange={this.handleChange}/>
: <input type='text' value={this.state.value} onChange={this.handleChange}/>
{(this.props.textarea === true) ?
<TextField label={this.props.title} value={this.state.value} onChange={this.handleChange} varient='outlined' multiline spellCheck={false} minRows={4} maxRows={10} />
: <TextField label={this.props.title} value={this.state.value} onChange={this.handleChange} varient='outlined' />
}
<span className='modalLink' onClick={this.resetItem}>{variables.language.getMessage(variables.languagecode, 'modals.main.settings.buttons.reset')}</span>
</>
);
}

View File

@@ -1,6 +1,7 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import Modal from 'react-modal';
import { MenuItem } from '@mui/material';
import { exportSettings, importSettings } from 'modules/helpers/settings/modals';
@@ -28,14 +29,15 @@ export default class AdvancedSettings extends PureComponent {
<>
<h2>{getMessage('modals.main.settings.sections.advanced.title')}</h2>
<Checkbox name='offlineMode' text={getMessage('modals.main.settings.sections.advanced.offline_mode')} element='.other' />
<Dropdown name='timezone' label={getMessage('modals.main.settings.sections.advanced.timezone.title')} category='timezone'>
<option value='auto'>{getMessage('modals.main.settings.sections.advanced.timezone.automatic')}</option>
<Dropdown name='timezone' label={getMessage('modals.main.settings.sections.advanced.timezone.title')} category='timezone' manual={true}>
<MenuItem value='auto'>{getMessage('modals.main.settings.sections.advanced.timezone.automatic')}</MenuItem>
{time_zones.map((timezone) => (
<option value={timezone} key={timezone}>{timezone}</option>
<MenuItem value={timezone} key={timezone}>{timezone}</MenuItem>
))}
</Dropdown>
<h3>{getMessage('modals.main.settings.sections.advanced.data')}</h3>
<br/>
<button className='reset' onClick={() => this.setState({ resetModal: true })}>{getMessage('modals.main.settings.buttons.reset')}</button>
<button className='export' onClick={() => exportSettings()}>{getMessage('modals.main.settings.buttons.export')}</button>
<button className='import' onClick={() => document.getElementById('file-input').click()}>{getMessage('modals.main.settings.buttons.import')}</button>

View File

@@ -6,6 +6,8 @@ import Radio from '../Radio';
import Slider from '../Slider';
import Text from '../Text';
import { values } from 'modules/helpers/settings/modals';
export default function AppearanceSettings() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
@@ -54,7 +56,7 @@ export default function AppearanceSettings() {
<h3>{getMessage('modals.main.settings.sections.appearance.accessibility.title')}</h3>
<Checkbox text={getMessage('modals.main.settings.sections.appearance.accessibility.text_shadow')} name='textBorder' category='other'/>
<Checkbox text={getMessage('modals.main.settings.sections.appearance.accessibility.animations')} name='animations' category='other'/>
<Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.toast_duration')} name='toastDisplayTime' default='2500' step='100' min='500' max='5000' toast={true}
<Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.toast_duration')} name='toastDisplayTime' default='2500' step='100' min='500' max='5000' marks={values('toast')} toast={true}
display={' ' + getMessage('modals.main.settings.sections.appearance.accessibility.milliseconds')} />
</>
);

View File

@@ -27,13 +27,13 @@ export default class DateSettings extends PureComponent {
const shortSettings = (
<>
<br/>
<Dropdown label={getMessage('modals.main.settings.sections.date.short_format')} name='dateFormat' category='date'>
<option value='DMY'>DMY</option>
<option value='MDY'>MDY</option>
<option value='YMD'>YMD</option>
</Dropdown>
<br/><br/>
<Dropdown label={getMessage('modals.main.settings.sections.date.short_separator.title')} name='shortFormat' category='date'>
<option value='dash'>{getMessage('modals.main.settings.sections.date.short_separator.dash')}</option>
<option value='dots'>{getMessage('modals.main.settings.sections.date.short_separator.dots')}</option>
@@ -56,7 +56,7 @@ export default class DateSettings extends PureComponent {
<option value='long'>{getMessage('modals.main.settings.sections.date.type.long')}</option>
<option value='short'>{getMessage('modals.main.settings.sections.date.type.short')}</option>
</Dropdown>
<br/>
<Checkbox name='datezero' text={getMessage('modals.main.settings.sections.time.digital.zero')} category='date'/>
<Checkbox name='weeknumber' text={getMessage('modals.main.settings.sections.date.week_number')} category='date'/>
{dateSettings}

View File

@@ -34,6 +34,7 @@ export default class GreetingSettings extends PureComponent {
<h3>{getMessage('modals.main.settings.sections.greeting.birthday')}</h3>
<Switch name='birthdayenabled' text={getMessage('modals.main.settings.enabled')} category='greeting'/>
<br/>
<Checkbox name='birthdayage' text={getMessage('modals.main.settings.sections.greeting.birthday_age')} category='greeting'/>
<p>{getMessage('modals.main.settings.sections.greeting.birthday_date')}</p>
<input type='date' onChange={this.changeDate} value={this.state.birthday.toISOString().substr(0, 10)}/>

View File

@@ -2,6 +2,7 @@ import variables from 'modules/variables';
import { PureComponent, Fragment } from 'react';
import { Cancel } from '@mui/icons-material';
import { toast } from 'react-toastify';
import { TextField } from '@mui/material';
import Header from '../Header';
@@ -64,13 +65,13 @@ export default class Message extends PureComponent {
<p>{this.getMessage('modals.main.settings.sections.message.text')}</p>
{this.state.messages.map((_url, index) => (
<Fragment key={index}>
<input type='text' value={this.state.messages[index]} onChange={(e) => this.message(e, true, index)}></input>
<TextField value={this.state.messages[index]} onChange={(e) => this.message(e, true, index)} varient='outlined' />
{this.state.messages.length > 1 ? <button className='cleanButton' onClick={() => this.modifyMessage('remove', index)}>
<Cancel/>
</button> : null}
<br/><br/>
</Fragment>
))}
<br/>
<button className='uploadbg' onClick={() => this.modifyMessage('add')}>{this.getMessage('modals.main.settings.sections.message.add')}</button>
</>
);

View File

@@ -6,6 +6,8 @@ import Checkbox from '../Checkbox';
import Dropdown from '../Dropdown';
import Slider from '../Slider';
import { values } from 'modules/helpers/settings/modals';
export default class Navbar extends PureComponent {
render() {
const getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
@@ -13,6 +15,7 @@ export default class Navbar extends PureComponent {
return (
<>
<h2>{getMessage('modals.main.settings.sections.appearance.navbar.title')}</h2>
<Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.widget_zoom')} name='zoomNavbar' min='10' max='400' default='100' display='%' marks={values('zoom')} category='navbar' />
<Checkbox name='navbarHover' text={'Only display on hover'} category='navbar'/>
<Checkbox name='notesEnabled' text={getMessage('modals.main.settings.sections.appearance.navbar.notes')} category='navbar' />
<Checkbox name='view' text={getMessage('modals.main.settings.sections.background.buttons.view')} category='navbar' />
@@ -25,8 +28,6 @@ export default class Navbar extends PureComponent {
{/* before it was just a checkbox */}
<option value='true'>{getMessage('modals.main.settings.sections.appearance.navbar.refresh_options.page')}</option>
</Dropdown>
<br/>
<Slider title={getMessage('modals.main.settings.sections.appearance.accessibility.widget_zoom')} name='zoomNavbar' min='10' max='400' default='100' display='%' category='navbar' />
</>
);
}

View File

@@ -1,6 +1,7 @@
import variables from 'modules/variables';
import { PureComponent, Fragment } from 'react';
import { Cancel } from '@mui/icons-material';
import { TextField } from '@mui/material';
import Header from '../Header';
import Checkbox from '../Checkbox';
@@ -88,12 +89,11 @@ export default class QuoteSettings extends PureComponent {
<p>{this.getMessage('modals.main.settings.sections.quote.custom')} <span className='modalLink' onClick={this.resetCustom}>{this.getMessage('modals.main.settings.buttons.reset')}</span></p>
{this.state.customQuote.map((_url, index) => (
<Fragment key={index}>
<input type='text' style={{ marginRight: '10px' }} value={this.state.customQuote[index].quote} placeholder='Quote' onChange={(e) => this.customQuote(e, true, index, 'quote')}></input>
<input type='text' value={this.state.customQuote[index].author} placeholder='Author' onChange={(e) => this.customQuote(e, true, index, 'author')}></input>
<TextField value={this.state.customQuote[index].quote} placeholder='Quote' onChange={(e) => this.customQuote(e, true, index, 'quote')} varient='outlined' />
<TextField value={this.state.customQuote[index].author} placeholder='Author' onChange={(e) => this.customQuote(e, true, index, 'author')} varient='outlined' />
{this.state.customQuote.length > 1 ? <button className='cleanButton' onClick={() => this.modifyCustomQuote('remove', index)}>
<Cancel/>
</button> : null}
<br/><br/>
</Fragment>
))}
<button className='uploadbg' onClick={() => this.modifyCustomQuote('add')}>{this.getMessage('modals.main.settings.sections.quote.add')}</button>
@@ -103,7 +103,6 @@ export default class QuoteSettings extends PureComponent {
// api
customSettings = (
<>
<br/><br/>
<Dropdown label={this.getMessage('modals.main.settings.sections.background.interval.title')} name='quotechange'>
<option value='refresh'>{this.getMessage('tabname')}</option>
<option value='60000'>{this.getMessage('modals.main.settings.sections.background.interval.minute')}</option>

View File

@@ -1,6 +1,7 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { toast } from 'react-toastify';
import { MenuItem, TextField } from '@mui/material';
import Header from '../Header';
import Dropdown from '../Dropdown';
@@ -78,18 +79,16 @@ export default class SearchSettings extends PureComponent {
<Checkbox name='voiceSearch' text={this.getMessage('modals.main.settings.sections.search.voice_search')} category='search'/>
: null}
<Checkbox name='searchDropdown' text={this.getMessage('modals.main.settings.sections.search.dropdown')} category='search' element='.other'/>
<Dropdown label={this.getMessage('modals.main.settings.sections.search.search_engine')} name='searchEngine' onChange={(value) => this.setSearchEngine(value)}>
<Dropdown label={this.getMessage('modals.main.settings.sections.search.search_engine')} name='searchEngine' onChange={(value) => this.setSearchEngine(value)} manual={true}>
{searchEngines.map((engine) => (
<option key={engine.name} value={engine.settingsName}>{engine.name}</option>
<MenuItem key={engine.name} value={engine.settingsName}>{engine.name}</MenuItem>
))}
<option value='custom'>{this.getMessage('modals.main.settings.sections.search.custom').split(' ')[0]}</option>
<MenuItem value='custom'>{this.getMessage('modals.main.settings.sections.search.custom').split(' ')[0]}</MenuItem>
</Dropdown>
<ul style={{ display: this.state.customDisplay }}>
<br/>
<p style={{ marginTop: '0px' }}>{this.getMessage('modals.main.settings.sections.search.custom')} <span className='modalLink' onClick={() => this.resetSearch()}>{this.getMessage('modals.main.settings.buttons.reset')}</span></p>
<input type='text' value={this.state.customValue} onInput={(e) => this.setState({ customValue: e.target.value })}></input>
<p style={{ marginTop: '0px' }}><span className='modalLink' onClick={() => this.resetSearch()}>{this.getMessage('modals.main.settings.buttons.reset')}</span></p>
<TextField label={this.getMessage('modals.main.settings.sections.search.custom')} value={this.state.customValue} onInput={(e) => this.setState({ customValue: e.target.value })} varient='outlined' />
</ul>
<br/>
<Checkbox name='autocomplete' text={this.getMessage('modals.main.settings.sections.search.autocomplete')} category='search' />
<Radio title={this.getMessage('modals.main.settings.sections.search.autocomplete_provider')} options={autocompleteProviders} name='autocompleteProvider' category='search'/>
</>

View File

@@ -34,7 +34,6 @@ export default class TimeSettings extends PureComponent {
<>
<h3>{getMessage('modals.main.settings.sections.time.digital.title')}</h3>
<Radio title={getMessage('modals.main.settings.sections.time.format')} name='timeformat' options={digitalOptions} smallTitle={true} category='clock' />
<br/>
<Checkbox name='seconds' text={getMessage('modals.main.settings.sections.time.digital.seconds')} category='clock' />
<Checkbox name='zero' text={getMessage('modals.main.settings.sections.time.digital.zero')} category='clock' />
</>

View File

@@ -4,12 +4,13 @@ import { PureComponent } from 'react';
import Header from '../Header';
import Radio from '../Radio';
import Checkbox from '../Checkbox';
import { TextField } from '@mui/material';
export default class TimeSettings extends PureComponent {
constructor() {
super();
this.state = {
location: localStorage.getItem('location') || 'London'
location: localStorage.getItem('location') || ''
};
}
@@ -67,11 +68,8 @@ export default class TimeSettings extends PureComponent {
return (
<>
<Header title={getMessage('modals.main.settings.sections.weather.title')} setting='weatherEnabled' category='widgets' zoomSetting='zoomWeather' zoomCategory='weather'/>
<ul>
<p>{getMessage('modals.main.settings.sections.weather.location')} <span className='modalLink' onClick={() => this.getAuto()}>{getMessage('modals.main.settings.sections.weather.auto')}</span></p>
<input type='text' value={this.state.location} onChange={(e) => this.changeLocation(e)}></input>
</ul>
<br/>
<TextField label={getMessage('modals.main.settings.sections.weather.location')} value={this.state.location} onChange={(e) => this.changeLocation(e)} placeholder='London' varient='outlined' />
<span className='modalLink' onClick={() => this.getAuto()}>{getMessage('modals.main.settings.sections.weather.auto')}</span>
<Radio name='tempformat' title={getMessage('modals.main.settings.sections.weather.temp_format.title')} options={tempFormat} category='weather'/>
<h3>{getMessage('modals.main.settings.sections.weather.extra_info.title')}</h3>

View File

@@ -1,5 +1,6 @@
import variables from 'modules/variables';
import { PureComponent } from 'react';
import { MenuItem } from '@mui/material';
import Header from '../../Header';
import Checkbox from '../../Checkbox';
@@ -10,6 +11,8 @@ import Radio from '../../Radio';
import ColourSettings from './Colour';
import CustomSettings from './Custom';
import { values } from 'modules/helpers/settings/modals';
export default class BackgroundSettings extends PureComponent {
getMessage = (text) => variables.language.getMessage(variables.languagecode, text);
@@ -17,6 +20,7 @@ export default class BackgroundSettings extends PureComponent {
super();
this.state = {
backgroundType: localStorage.getItem('backgroundType') || 'api',
backgroundFilter: localStorage.getItem('backgroundFilter') || 'none',
backgroundCategories: [this.getMessage('modals.main.loading')]
};
this.controller = new AbortController();
@@ -76,31 +80,25 @@ export default class BackgroundSettings extends PureComponent {
];
const interval = (
<>
<br/><br/>
<Dropdown label={getMessage('modals.main.settings.sections.background.interval.title')} name='backgroundchange'>
<Dropdown label={getMessage('modals.main.settings.sections.background.interval.title')} name='backgroundchange'>
<option value='refresh'>{getMessage('tabname')}</option>
<option value='60000'>{getMessage('modals.main.settings.sections.background.interval.minute')}</option>
<option value='1800000'>{getMessage('modals.main.settings.sections.background.interval.half_hour')}</option>
<option value='3600000'>{getMessage('modals.main.settings.sections.background.interval.hour')}</option>
<option value='86400000'>{getMessage('modals.main.settings.sections.background.interval.day')}</option>
<option value='604800000'>{getMessage('widgets.date.week')}</option>
<option value='2628000000'>{getMessage('modals.main.settings.sections.background.interval.month')}</option>
</Dropdown>
</>
<option value='60000'>{getMessage('modals.main.settings.sections.background.interval.minute')}</option>
<option value='1800000'>{getMessage('modals.main.settings.sections.background.interval.half_hour')}</option>
<option value='3600000'>{getMessage('modals.main.settings.sections.background.interval.hour')}</option>
<option value='86400000'>{getMessage('modals.main.settings.sections.background.interval.day')}</option>
<option value='604800000'>{getMessage('widgets.date.week')}</option>
<option value='2628000000'>{getMessage('modals.main.settings.sections.background.interval.month')}</option>
</Dropdown>
);
const APISettings = (
<>
<br/>
<Radio title={getMessage('modals.main.settings.sections.background.source.api')} options={apiOptions} name='backgroundAPI' category='background' element='#backgroundImage'/>
<br/>
<Dropdown label={getMessage('modals.main.settings.sections.background.category')} name='apiCategory'>
<Dropdown label={getMessage('modals.main.settings.sections.background.category')} name='apiCategory' manual={true}>
{this.state.backgroundCategories.map((category) => (
<option value={category} key={category}>{category.charAt(0).toUpperCase() + category.slice(1)}</option>
<MenuItem value={category} key={category}>{category.charAt(0).toUpperCase() + category.slice(1)}</MenuItem>
))}
</Dropdown>
<br/><br/>
<Dropdown label={getMessage('modals.main.settings.sections.background.source.quality.title')} name='apiQuality' element='.other'>
<option value='original'>{getMessage('modals.main.settings.sections.background.source.quality.original')}</option>
<option value='high'>{getMessage('modals.main.settings.sections.background.source.quality.high')}</option>
@@ -114,6 +112,8 @@ export default class BackgroundSettings extends PureComponent {
switch (this.state.backgroundType) {
case 'custom': backgroundSettings = <CustomSettings interval={interval}/>; break;
case 'colour': backgroundSettings = <ColourSettings/>; break;
case 'random_colour': backgroundSettings = <></>; break;
case 'random_gradient': backgroundSettings = <></>; break;
default: backgroundSettings = APISettings; break;
}
@@ -138,25 +138,27 @@ export default class BackgroundSettings extends PureComponent {
<option value='random_colour'>{getMessage('modals.main.settings.sections.background.type.random_colour')}</option>
<option value='random_gradient'>{getMessage('modals.main.settings.sections.background.type.random_gradient')}</option>
</Dropdown>
<br/>
{backgroundSettings}
<h3>{getMessage('modals.main.settings.sections.background.buttons.title')}</h3>
<Checkbox name='downloadbtn' text={getMessage('modals.main.settings.sections.background.buttons.download')} element='.other' />
<h3>{getMessage('modals.main.settings.sections.background.effects.title')}</h3>
<Slider title={getMessage('modals.main.settings.sections.background.effects.blur')} name='blur' min='0' max='100' default='0' display='%' category='background' element='#backgroundImage' />
<Slider title={getMessage('modals.main.settings.sections.background.effects.brightness')} name='brightness' min='0' max='100' default='90' display='%' category='background' element='#backgroundImage' />
<br/><br/>
<Dropdown label={getMessage('modals.main.settings.sections.background.effects.filters.title')} name='backgroundFilter' category='background' element='#backgroundImage'>
<Slider title={getMessage('modals.main.settings.sections.background.effects.blur')} name='blur' min='0' max='100' default='0' display='%' marks={values('background')} category='background' element='#backgroundImage' />
<Slider title={getMessage('modals.main.settings.sections.background.effects.brightness')} name='brightness' min='0' max='100' default='90' display='%' marks={values('background')} category='background' element='#backgroundImage' />
<br/>
<Dropdown label={getMessage('modals.main.settings.sections.background.effects.filters.title')} name='backgroundFilter' onChange={(value) => this.setState({ backgroundFilter: value })} category='background' element='#backgroundImage'>
<option value='none'>None</option>
<option value='grayscale'>{getMessage('modals.main.settings.sections.background.effects.filters.grayscale')}</option>
<option value='sepia'>{getMessage('modals.main.settings.sections.background.effects.filters.sepia')}</option>
<option value='invert'>{getMessage('modals.main.settings.sections.background.effects.filters.invert')}</option>
<option value='saturate'>{getMessage('modals.main.settings.sections.background.effects.filters.saturate')}</option>
<option value='contrast'>{getMessage('modals.main.settings.sections.background.effects.filters.contrast')}</option>
</Dropdown>
<Slider title={getMessage('modals.main.settings.sections.background.effects.filters.amount')} name='backgroundFilterAmount' min='0' max='100' default='0' display='%' category='background' element='#backgroundImage' />
{this.state.backgroundFilter !== 'none' ?
<Slider title={getMessage('modals.main.settings.sections.background.effects.filters.amount')} name='backgroundFilterAmount' min='0' max='100' default='0' display='%' marks={values('background')} category='background' element='#backgroundImage' />
: null}
</>
);
}

View File

@@ -2,6 +2,7 @@ import variables from 'modules/variables';
import { PureComponent, Fragment } from 'react';
import { toast } from 'react-toastify';
import { Cancel } from '@mui/icons-material';
import { TextField } from '@mui/material';
import Checkbox from '../../Checkbox';
import FileUpload from '../../FileUpload';
@@ -96,16 +97,17 @@ export default class CustomSettings extends PureComponent {
<p>{this.getMessage('modals.main.settings.sections.background.source.custom_background')} <span className='modalLink' onClick={this.resetCustom}>{this.getMessage('modals.main.settings.buttons.reset')}</span></p>
{this.state.customBackground.map((_url, index) => (
<Fragment key={index}>
<input type='text' value={this.state.customBackground[index]} onChange={(e) => this.customBackground(e, true, index)} autoComplete='off' autoCorrect='off' autoCapitalize='off' spellCheck={false}/>
<TextField value={this.state.customBackground[index]} onChange={(e) => this.customBackground(e, true, index)} autoComplete='off' autoCorrect='off' autoCapitalize='off' spellCheck={false} varient='outlined' />
{this.state.customBackground.length > 1 ? <button className='cleanButton' onClick={() => this.modifyCustomBackground('remove', index)}>
<Cancel/>
</button> : null}
<span className='modalLink' onClick={() => this.uploadCustombackground(index)}>{this.getMessage('modals.main.settings.sections.background.source.upload')}</span>
{this.videoCustomSettings(index)}
<br/><br/>
</Fragment>
))}
<br/><br/>
<button className='uploadbg' onClick={() => this.modifyCustomBackground('add')}>{this.getMessage('modals.main.settings.sections.background.source.add_background')}</button>
<br/><br/>
<FileUpload id='bg-input' accept='image/jpeg, image/png, image/webp, image/webm, image/gif, video/mp4, video/webm, video/ogg' loadFunction={(e) => this.customBackground(e, false, this.state.currentBackgroundIndex)} />
{this.props.interval}
</ul>