mirror of
https://github.com/mue/mue.git
synced 2026-06-05 23:45:53 +02:00
refactor: weather and app to functional components
This commit is contained in:
91
src/App.jsx
91
src/App.jsx
@@ -1,56 +1,75 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ToastContainer } from 'react-toastify';
|
||||
|
||||
import Background from 'features/background/Background';
|
||||
import Widgets from 'features/misc/views/Widgets';
|
||||
import Modals from 'features/misc/modals/Modals';
|
||||
|
||||
import { loadSettings, moveSettings } from 'utils/settings';
|
||||
|
||||
import EventBus from 'utils/eventbus';
|
||||
import variables from 'config/variables';
|
||||
|
||||
export default class App extends PureComponent {
|
||||
componentDidMount() {
|
||||
// 4.0 -> 5.0 (the key below is only on 5.0)
|
||||
// now featuring 5.0 -> 5.1
|
||||
// the firstRun check was moved here because the old function was useless
|
||||
if (!localStorage.getItem('firstRun') || !localStorage.getItem('stats')) {
|
||||
const useAppSetup = () => {
|
||||
useEffect(() => {
|
||||
const firstRun = localStorage.getItem('firstRun');
|
||||
const stats = localStorage.getItem('stats');
|
||||
|
||||
if (!firstRun || !stats) {
|
||||
moveSettings();
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
|
||||
EventBus.on('refresh', (data) => {
|
||||
const refreshHandler = (data) => {
|
||||
if (data === 'other') {
|
||||
loadSettings(true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
EventBus.on('refresh', refreshHandler);
|
||||
|
||||
variables.stats.tabLoad();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
EventBus.off('refresh');
|
||||
}
|
||||
return () => {
|
||||
EventBus.off('refresh', refreshHandler);
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
{localStorage.getItem('background') === 'true' && <Background />}
|
||||
<ToastContainer
|
||||
position="top-center"
|
||||
autoClose={localStorage.getItem('toastDisplayTime') || 2500}
|
||||
newestOnTop={true}
|
||||
closeOnClick
|
||||
pauseOnFocusLoss
|
||||
/>
|
||||
<div id="center">
|
||||
<Widgets />
|
||||
<Modals />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
const App = () => {
|
||||
const [toastDisplayTime, setToastDisplayTime] = useState(2500);
|
||||
const [showBackground, setShowBackground] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const storedToastDisplayTime = localStorage.getItem('toastDisplayTime');
|
||||
const storedBackground = localStorage.getItem('background');
|
||||
|
||||
if (storedToastDisplayTime) {
|
||||
setToastDisplayTime(parseInt(storedToastDisplayTime, 10));
|
||||
}
|
||||
|
||||
if (storedBackground === 'true') {
|
||||
setShowBackground(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useAppSetup();
|
||||
|
||||
return (
|
||||
<>
|
||||
{showBackground && <Background />}
|
||||
<ToastContainer
|
||||
position="top-center"
|
||||
autoClose={toastDisplayTime}
|
||||
newestOnTop={true}
|
||||
closeOnClick
|
||||
pauseOnFocusLoss
|
||||
/>
|
||||
<div id="center">
|
||||
<Widgets />
|
||||
<Modals />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -1,224 +1,211 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { MdAutoAwesome } from 'react-icons/md';
|
||||
|
||||
import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Layout/Settings';
|
||||
import { Radio, Dropdown, Checkbox } from 'components/Form/Settings';
|
||||
import { TextField } from '@mui/material';
|
||||
import variables from 'config/variables';
|
||||
|
||||
class WeatherOptions extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
location: localStorage.getItem('location') || '',
|
||||
windSpeed: localStorage.getItem('windspeed') !== 'true',
|
||||
};
|
||||
}
|
||||
const useLocalStorageState = (key, initialValue) => {
|
||||
const [state, setState] = useState(() => localStorage.getItem(key) || initialValue);
|
||||
|
||||
componentDidUpdate() {
|
||||
localStorage.setItem('location', this.state.location);
|
||||
}
|
||||
useEffect(() => {
|
||||
localStorage.setItem(key, state);
|
||||
}, [key, state]);
|
||||
|
||||
showReminder() {
|
||||
return [state, setState];
|
||||
};
|
||||
|
||||
const useWeatherSettings = () => {
|
||||
const [location, setLocation] = useLocalStorageState('location', '');
|
||||
const [windSpeed, setWindSpeed] = useLocalStorageState('windspeed', 'true');
|
||||
|
||||
const showReminder = useCallback(() => {
|
||||
document.querySelector('.reminder-info').style.display = 'flex';
|
||||
localStorage.setItem('showReminder', true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
changeLocation(e) {
|
||||
const changeLocation = (e) => {
|
||||
localStorage.removeItem('currentWeather');
|
||||
this.setState({
|
||||
location: e.target.value,
|
||||
});
|
||||
setLocation(e.target.value);
|
||||
showReminder();
|
||||
};
|
||||
|
||||
this.showReminder();
|
||||
}
|
||||
const getAutoLocation = useCallback(() => {
|
||||
setLocation(variables.getMessage('modals.main.loading'));
|
||||
|
||||
render() {
|
||||
const weatherType = localStorage.getItem('weatherType');
|
||||
const WEATHER_SECTION = 'modals.main.settings.sections.weather';
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
async (position) => {
|
||||
const data = await (
|
||||
await fetch(
|
||||
`${variables.constants.API_URL}/gps?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}`
|
||||
)
|
||||
).json();
|
||||
setLocation(data[0].name);
|
||||
showReminder();
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
}
|
||||
);
|
||||
}, [setLocation, showReminder]);
|
||||
|
||||
const WidgetType = () => {
|
||||
return (
|
||||
<Row>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.widget_type`)} />
|
||||
<Action>
|
||||
<Dropdown
|
||||
label={variables.getMessage('modals.main.settings.sections.time.type')}
|
||||
name="weatherType"
|
||||
category="weather"
|
||||
onChange={() => this.forceUpdate()}
|
||||
items={[
|
||||
{ value: '1', text: variables.getMessage(`${WEATHER_SECTION}.options.basic`) },
|
||||
{
|
||||
value: '2',
|
||||
text: variables.getMessage(`${WEATHER_SECTION}.options.standard`),
|
||||
},
|
||||
{
|
||||
value: '3',
|
||||
text: variables.getMessage(`${WEATHER_SECTION}.options.expanded`),
|
||||
},
|
||||
{ value: '4', text: variables.getMessage(`${WEATHER_SECTION}.options.custom`) },
|
||||
]}
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
return {
|
||||
location,
|
||||
windSpeed: windSpeed !== 'true',
|
||||
setWindSpeed,
|
||||
changeLocation,
|
||||
getAutoLocation,
|
||||
};
|
||||
};
|
||||
|
||||
const LocationSetting = () => {
|
||||
const getAuto = () => {
|
||||
this.setState({
|
||||
location: variables.getMessage('modals.main.loading'),
|
||||
});
|
||||
const WeatherOptions = () => {
|
||||
const { location, windSpeed, setWindSpeed, changeLocation, getAutoLocation } = useWeatherSettings();
|
||||
const weatherType = localStorage.getItem('weatherType');
|
||||
const WEATHER_SECTION = 'modals.main.settings.sections.weather';
|
||||
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
async (position) => {
|
||||
const data = await (
|
||||
await fetch(
|
||||
`${variables.constants.API_URL}/gps?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}`,
|
||||
)
|
||||
).json();
|
||||
this.setState({
|
||||
location: data[0].name,
|
||||
});
|
||||
const WidgetType = () => (
|
||||
<Row>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.widget_type`)} />
|
||||
<Action>
|
||||
<Dropdown
|
||||
label={variables.getMessage('modals.main.settings.sections.time.type')}
|
||||
name="weatherType"
|
||||
category="weather"
|
||||
onChange={() => this.forceUpdate()}
|
||||
items={[
|
||||
{ value: '1', text: variables.getMessage(`${WEATHER_SECTION}.options.basic`) },
|
||||
{ value: '2', text: variables.getMessage(`${WEATHER_SECTION}.options.standard`) },
|
||||
{ value: '3', text: variables.getMessage(`${WEATHER_SECTION}.options.expanded`) },
|
||||
{ value: '4', text: variables.getMessage(`${WEATHER_SECTION}.options.custom`) },
|
||||
]}
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
|
||||
this.showReminder();
|
||||
},
|
||||
(error) => {
|
||||
// firefox requires this 2nd function
|
||||
console.error(error);
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
},
|
||||
);
|
||||
};
|
||||
return (
|
||||
<Row>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.location`)} />
|
||||
<Action>
|
||||
<TextField
|
||||
label={variables.getMessage(`${WEATHER_SECTION}.location`)}
|
||||
value={this.state.location}
|
||||
onChange={(e) => this.changeLocation(e)}
|
||||
placeholder="London"
|
||||
varient="outlined"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
<span className="link" onClick={getAuto}>
|
||||
<MdAutoAwesome />
|
||||
{variables.getMessage(`${WEATHER_SECTION}.auto`)}
|
||||
</span>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
const LocationSetting = () => (
|
||||
<Row>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.location`)} />
|
||||
<Action>
|
||||
<TextField
|
||||
label={variables.getMessage(`${WEATHER_SECTION}.location`)}
|
||||
value={location}
|
||||
onChange={changeLocation}
|
||||
placeholder="London"
|
||||
variant="outlined"
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
<span className="link" onClick={getAutoLocation}>
|
||||
<MdAutoAwesome />
|
||||
{variables.getMessage(`${WEATHER_SECTION}.auto`)}
|
||||
</span>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
|
||||
const TemperatureFormat = () => {
|
||||
return (
|
||||
<Row final={weatherType !== '4'}>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.temp_format.title`)} />
|
||||
<Action>
|
||||
<Radio
|
||||
name="tempformat"
|
||||
options={[
|
||||
{
|
||||
name: variables.getMessage(`${WEATHER_SECTION}.temp_format.celsius`) + ' (°C)',
|
||||
value: 'celsius',
|
||||
},
|
||||
{
|
||||
name: variables.getMessage(`${WEATHER_SECTION}.temp_format.fahrenheit`) + ' (°F)',
|
||||
value: 'fahrenheit',
|
||||
},
|
||||
{
|
||||
name: variables.getMessage(`${WEATHER_SECTION}.temp_format.kelvin`) + ' (K)',
|
||||
value: 'kelvin',
|
||||
},
|
||||
]}
|
||||
category="weather"
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
const TemperatureFormat = () => (
|
||||
<Row final={weatherType !== '4'}>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.temp_format.title`)} />
|
||||
<Action>
|
||||
<Radio
|
||||
name="tempformat"
|
||||
options={[
|
||||
{
|
||||
name: `${variables.getMessage(`${WEATHER_SECTION}.temp_format.celsius`)} (°C)`,
|
||||
value: 'celsius',
|
||||
},
|
||||
{
|
||||
name: `${variables.getMessage(`${WEATHER_SECTION}.temp_format.fahrenheit`)} (°F)`,
|
||||
value: 'fahrenheit',
|
||||
},
|
||||
{
|
||||
name: `${variables.getMessage(`${WEATHER_SECTION}.temp_format.kelvin`)} (K)`,
|
||||
value: 'kelvin',
|
||||
},
|
||||
]}
|
||||
category="weather"
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
|
||||
const CustomOptions = () => {
|
||||
const weatherOptions = [
|
||||
{
|
||||
name: 'weatherdescription',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.show_description`,
|
||||
},
|
||||
{
|
||||
name: 'cloudiness',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.cloudiness`,
|
||||
},
|
||||
{ name: 'humidity', textKey: `${WEATHER_SECTION}.extra_info.humidity` },
|
||||
{
|
||||
name: 'visibility',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.visibility`,
|
||||
},
|
||||
{
|
||||
name: 'windspeed',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.wind_speed`,
|
||||
onChange: () =>
|
||||
this.setState({ windSpeed: localStorage.getItem('windspeed') !== 'true' }),
|
||||
},
|
||||
{
|
||||
name: 'windDirection',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.wind_direction`,
|
||||
disabled: this.state.windSpeed,
|
||||
},
|
||||
{
|
||||
name: 'atmosphericpressure',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.atmospheric_pressure`,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Row final={true}>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.custom_settings`)} />
|
||||
<Action>
|
||||
{weatherOptions.map((item) => (
|
||||
<Checkbox
|
||||
key={item.name}
|
||||
name={item.name}
|
||||
text={variables.getMessage(item.textKey)}
|
||||
category="weather"
|
||||
onChange={item.onChange}
|
||||
disabled={item.disabled}
|
||||
/>
|
||||
))}
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
const CustomOptions = () => {
|
||||
const weatherOptions = [
|
||||
{
|
||||
name: 'weatherdescription',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.show_description`,
|
||||
},
|
||||
{
|
||||
name: 'cloudiness',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.cloudiness`,
|
||||
},
|
||||
{ name: 'humidity', textKey: `${WEATHER_SECTION}.extra_info.humidity` },
|
||||
{
|
||||
name: 'visibility',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.visibility`,
|
||||
},
|
||||
{
|
||||
name: 'windspeed',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.wind_speed`,
|
||||
onChange: () => setWindSpeed(localStorage.getItem('windspeed') !== 'true'),
|
||||
},
|
||||
{
|
||||
name: 'windDirection',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.wind_direction`,
|
||||
disabled: windSpeed,
|
||||
},
|
||||
{
|
||||
name: 'atmosphericpressure',
|
||||
textKey: `${WEATHER_SECTION}.extra_info.atmospheric_pressure`,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header
|
||||
title={variables.getMessage(`${WEATHER_SECTION}.title`)}
|
||||
setting="weatherEnabled"
|
||||
category="widgets"
|
||||
zoomSetting="zoomWeather"
|
||||
zoomCategory="weather"
|
||||
visibilityToggle={true}
|
||||
/>
|
||||
<PreferencesWrapper
|
||||
setting="weatherEnabled"
|
||||
zoomSetting="zoomWeather"
|
||||
zoomCategory="weather"
|
||||
visibilityToggle={true}
|
||||
>
|
||||
<WidgetType />
|
||||
{/* https://stackoverflow.com/a/65328486 when using inputs it may defocus so we do the {} instead of <> */}
|
||||
{LocationSetting()}
|
||||
<TemperatureFormat />
|
||||
{weatherType === '4' && <CustomOptions />}
|
||||
</PreferencesWrapper>
|
||||
</>
|
||||
<Row final={true}>
|
||||
<Content title={variables.getMessage(`${WEATHER_SECTION}.custom_settings`)} />
|
||||
<Action>
|
||||
{weatherOptions.map((item) => (
|
||||
<Checkbox
|
||||
key={item.name}
|
||||
name={item.name}
|
||||
text={variables.getMessage(item.textKey)}
|
||||
category="weather"
|
||||
onChange={item.onChange}
|
||||
disabled={item.disabled}
|
||||
/>
|
||||
))}
|
||||
</Action>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header
|
||||
title={variables.getMessage(`${WEATHER_SECTION}.title`)}
|
||||
setting="weatherEnabled"
|
||||
category="widgets"
|
||||
zoomSetting="zoomWeather"
|
||||
zoomCategory="weather"
|
||||
visibilityToggle={true}
|
||||
/>
|
||||
<PreferencesWrapper
|
||||
setting="weatherEnabled"
|
||||
zoomSetting="zoomWeather"
|
||||
zoomCategory="weather"
|
||||
visibilityToggle={true}
|
||||
>
|
||||
<WidgetType />
|
||||
{/* https://stackoverflow.com/a/65328486 when using inputs it may defocus so we do the {} instead of <> */}
|
||||
{LocationSetting()}
|
||||
<TemperatureFormat />
|
||||
{weatherType === '4' && <CustomOptions />}
|
||||
</PreferencesWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { WeatherOptions as default, WeatherOptions };
|
||||
|
||||
Reference in New Issue
Block a user