switch from connect to useSelector hook

This commit is contained in:
HF 2021-05-02 03:13:02 +02:00
parent c39bbbfa7b
commit 0ebc074086
11 changed files with 195 additions and 298 deletions

View File

@ -4,10 +4,10 @@
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux'; import { useSelector, shallowEqual } from 'react-redux';
import { t } from 'ttag'; import { t } from 'ttag';
import type { State } from '../reducers'; import { getToday } from '../core/utils';
const keptState = { const keptState = {
coords: null, coords: null,
@ -146,19 +146,10 @@ async function submitMakeMod(
} }
function Admintools({ function Admintools() {
canvasId, const maxDate = getToday();
canvases,
userlvl,
}) {
const curDate = new Date();
let day = curDate.getDate();
let month = curDate.getMonth() + 1;
if (month < 10) month = `0${month}`;
if (day < 10) day = `0${day}`;
const maxDate = `${curDate.getFullYear()}-${month}-${day}`;
const [selectedCanvas, selectCanvas] = useState(canvasId); const [selectedCanvas, selectCanvas] = useState(0);
const [imageAction, selectImageAction] = useState('build'); const [imageAction, selectImageAction] = useState('build');
const [iPAction, selectIPAction] = useState('ban'); const [iPAction, selectIPAction] = useState('ban');
const [protAction, selectProtAction] = useState('protect'); const [protAction, selectProtAction] = useState('protect');
@ -173,6 +164,20 @@ function Admintools({
const [modlist, setModList] = useState([]); const [modlist, setModList] = useState([]);
const [submitting, setSubmitting] = useState(false); const [submitting, setSubmitting] = useState(false);
const [
canvasId,
canvases,
userlvl,
] = useSelector((state) => [
state.canvas.canvasId,
state.canvas.canvases,
state.user.userlvl,
], shallowEqual);
useEffect(() => {
selectCanvas(canvasId);
}, [canvasId]);
let descAction; let descAction;
switch (imageAction) { switch (imageAction) {
case 'build': case 'build':
@ -597,10 +602,4 @@ function Admintools({
); );
} }
function mapStateToProps(state: State) { export default React.memo(Admintools);
const { canvasId, canvases } = state.canvas;
const { userlvl } = state.user;
return { canvasId, canvases, userlvl };
}
export default connect(mapStateToProps)(Admintools);

View File

@ -4,12 +4,11 @@
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux'; import { useSelector, shallowEqual } from 'react-redux';
import fileDownload from 'js-file-download'; import fileDownload from 'js-file-download';
import { utils, applyPalette } from 'image-q'; import { utils, applyPalette } from 'image-q';
import { jt, t } from 'ttag'; import { jt, t } from 'ttag';
import type { State } from '../reducers';
import printGIMPPalette from '../core/exportGPL'; import printGIMPPalette from '../core/exportGPL';
import { copyCanvasToClipboard } from '../utils/clipboard'; import { copyCanvasToClipboard } from '../utils/clipboard';
@ -208,12 +207,8 @@ async function renderOutputImage(opts) {
} }
function Converter({ function Converter() {
canvasId, const [selectedCanvas, selectCanvas] = useState(0);
canvases,
showHiddenCanvases,
}) {
const [selectedCanvas, selectCanvas] = useState(canvasId);
const [selectedFile, selectFile] = useState(null); const [selectedFile, selectFile] = useState(null);
const [selectedStrategy, selectStrategy] = useState('nearest'); const [selectedStrategy, selectStrategy] = useState('nearest');
const [selectedColorDist, selectColorDist] = useState('euclidean'); const [selectedColorDist, selectColorDist] = useState('euclidean');
@ -230,6 +225,21 @@ function Converter({
offsetX: 0, offsetX: 0,
offsetY: 0, offsetY: 0,
}); });
const [
canvasId,
canvases,
showHiddenCanvases,
] = useSelector((state) => [
state.canvas.canvasId,
state.canvas.canvases,
state.canvas.showHiddenCanvases,
], shallowEqual);
useEffect(() => {
selectCanvas(canvasId);
}, []);
const input = document.createElement('canvas'); const input = document.createElement('canvas');
useEffect(() => { useEffect(() => {
@ -615,13 +625,4 @@ function Converter({
); );
} }
function mapStateToProps(state: State) { export default React.memo(Converter);
const {
canvasId,
canvases,
showHiddenCanvases,
} = state.canvas;
return { canvasId, canvases, showHiddenCanvases };
}
export default connect(mapStateToProps)(Converter);

View File

@ -4,26 +4,24 @@
*/ */
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { useSelector } from 'react-redux';
import { import {
durationToString, durationToString,
} from '../core/utils'; } from '../core/utils';
import type { State } from '../reducers';
const CoolDownBox = ({ coolDown }) => ( const CoolDownBox = () => {
<div const coolDown = useSelector((state) => state.user.coolDown);
className={(coolDown && coolDown >= 300)
? 'cooldownbox show' : 'cooldownbox'}
>
{coolDown && durationToString(coolDown, true)}
</div>
);
function mapStateToProps(state: State) { return (
const { coolDown } = state.user; <div
return { coolDown }; className={(coolDown && coolDown >= 300)
} ? 'cooldownbox show' : 'cooldownbox'}
>
{coolDown && durationToString(coolDown, true)}
</div>
);
};
export default connect(mapStateToProps)(CoolDownBox); export default React.memo(CoolDownBox);

View File

@ -4,45 +4,38 @@
*/ */
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { t } from 'ttag'; import { t } from 'ttag';
import copy from '../utils/clipboard'; import copy from '../utils/clipboard';
import { notify } from '../actions'; import { notify } from '../actions';
import type { State } from '../reducers';
function renderCoordinates(cell): string { function renderCoordinates(cell): string {
return `(${cell.join(', ')})`; return `(${cell.join(', ')})`;
} }
const CoordinatesBox = ({ view, hover, notifyCopy }) => ( const CoordinatesBox = () => {
<div const view = useSelector((state) => state.canvas.view);
className="coorbox" const hover = useSelector((state) => state.gui.hover);
onClick={() => { copy(window.location.hash); notifyCopy(); }} const dispatch = useDispatch();
role="button"
title={t`Copy to Clipboard`}
tabIndex="0"
>{
renderCoordinates(hover
|| view.map(Math.round))
}</div>
);
function mapDispatchToProps(dispatch) { return (
return { <div
notifyCopy() { className="coorbox"
dispatch(notify(t`Copied!`)); onClick={() => {
}, copy(window.location.hash);
}; dispatch(notify(t`Copied!`));
} }}
role="button"
title={t`Copy to Clipboard`}
tabIndex="0"
>{
renderCoordinates(hover
|| view.map(Math.round))
}</div>
);
};
function mapStateToProps(state: State) { export default React.memo(CoordinatesBox);
const { view } = state.canvas;
const { hover } = state.gui;
return { view, hover };
}
export default connect(mapStateToProps, mapDispatchToProps)(CoordinatesBox);

View File

@ -8,7 +8,7 @@ import React, {
import { useSelector, shallowEqual, useDispatch } from 'react-redux'; import { useSelector, shallowEqual, useDispatch } from 'react-redux';
import { t } from 'ttag'; import { t } from 'ttag';
import { dateToString } from '../core/utils'; import { dateToString, getToday } from '../core/utils';
import { selectHistoricalTime } from '../actions'; import { selectHistoricalTime } from '../actions';
import { requestHistoricalTimes } from '../actions/fetch'; import { requestHistoricalTimes } from '../actions/fetch';
@ -25,15 +25,6 @@ function stringToTime(timeString) {
return `${timeString.substr(0, 2)}:${timeString.substr(2, 2)}`; return `${timeString.substr(0, 2)}:${timeString.substr(2, 2)}`;
} }
function getToday() {
const date = new Date();
let day = date.getDate();
let month = date.getMonth() + 1;
if (month < 10) month = `0${month}`;
if (day < 10) day = `0${day}`;
return `${date.getFullYear()}-${month}-${day}`;
}
const HistorySelect = () => { const HistorySelect = () => {
const dateSelect = useRef(null); const dateSelect = useRef(null);

View File

@ -4,37 +4,40 @@
*/ */
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { useSelector, shallowEqual } from 'react-redux';
import { FaUser, FaPaintBrush } from 'react-icons/fa'; import { FaUser, FaPaintBrush } from 'react-icons/fa';
import { t } from 'ttag'; import { t } from 'ttag';
import { numberToString } from '../core/utils'; import { numberToString } from '../core/utils';
import type { State } from '../reducers'; const OnlineBox = () => {
const [
online,
totalPixels,
name,
] = useSelector((state) => [
state.ranks.online,
state.ranks.totalPixels,
state.user.name,
], shallowEqual);
return (
<div>
{(online || name)
? (
<div className="onlinebox">
{(online)
&& <span title={t`User online`}>{online} <FaUser />&nbsp;</span>}
{(name != null)
&& (
<span title={t`Pixels placed`}>
{numberToString(totalPixels)} <FaPaintBrush />
</span>
)}
</div>
) : null}
</div>
);
};
const OnlineBox = ({ online, totalPixels, name }) => ( export default React.memo(OnlineBox);
<div>
{(online || name)
? (
<div className="onlinebox">
{(online)
&& <span title={t`User online`}>{online} <FaUser />&nbsp;</span>}
{(name != null)
&& (
<span title={t`Pixels placed`}>
{numberToString(totalPixels)} <FaPaintBrush />
</span>
)}
</div>
) : null}
</div>
);
function mapStateToProps(state: State) {
const { online, totalPixels } = state.ranks;
const { name } = state.user;
return { online, totalPixels, name };
}
export default connect(mapStateToProps)(OnlineBox);

View File

@ -4,10 +4,9 @@
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux'; import { useDispatch, useSelector, shallowEqual } from 'react-redux';
import { selectColor } from '../actions'; import { selectColor } from '../actions';
import type { State } from '../reducers';
import useWindowSize from './hooks/resize'; import useWindowSize from './hooks/resize';
@ -90,15 +89,22 @@ function getStylesByWindowSize(
}]; }];
} }
function Palette({ const Palette = () => {
colors,
selectedColor,
paletteOpen,
compactPalette,
select,
clrIgnore,
}) {
const [render, setRender] = useState(false); const [render, setRender] = useState(false);
const [
paletteOpen,
compactPalette,
colors,
clrIgnore,
selectedColor,
] = useSelector((state) => [
state.gui.paletteOpen,
state.gui.compactPalette,
state.canvas.palette.colors,
state.canvas.clrIgnore,
state.canvas.selectedColor,
], shallowEqual);
const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
window.setTimeout(() => { window.setTimeout(() => {
@ -139,32 +145,12 @@ function Palette({
? 'selected' ? 'selected'
: 'unselected'} : 'unselected'}
color={color} color={color}
onClick={() => select(index + clrIgnore)} onClick={() => dispatch(selectColor(index + clrIgnore))}
/> />
))} ))}
</div> </div>
) )
); );
} };
function mapStateToProps(state: State) { export default React.memo(Palette);
const { paletteOpen, compactPalette } = state.gui;
const { palette, clrIgnore, selectedColor } = state.canvas;
return {
colors: palette.colors,
selectedColor,
paletteOpen,
compactPalette,
clrIgnore,
};
}
function mapDispatchToProps(dispatch) {
return {
select(color) {
dispatch(selectColor(color));
},
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Palette);

View File

@ -4,21 +4,13 @@
*/ */
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { useSelector } from 'react-redux';
import type { State } from '../reducers'; function Style() {
const style = useSelector((state) => state.gui.style);
function Style({ style }) {
const cssUri = window.ssv.availableStyles[style]; const cssUri = window.ssv.availableStyles[style];
return (style === 'default') ? null return (style === 'default') ? null
: (<link rel="stylesheet" type="text/css" href={cssUri} />); : (<link rel="stylesheet" type="text/css" href={cssUri} />);
} }
function mapStateToProps(state: State) { export default React.memo(Style);
const {
style,
} = state.gui;
return { style };
}
export default connect(mapStateToProps)(Style);

View File

@ -4,9 +4,8 @@
*/ */
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { useSelector, shallowEqual } from 'react-redux';
import type { State } from '../reducers';
import CoolDownBox from './CoolDownBox'; import CoolDownBox from './CoolDownBox';
import NotifyBox from './NotifyBox'; import NotifyBox from './NotifyBox';
import GlobeButton from './buttons/GlobeButton'; import GlobeButton from './buttons/GlobeButton';
@ -25,13 +24,21 @@ const CONTEXT_MENUS = {
/* other context menus */ /* other context menus */
}; };
const UI = ({ const UI = () => {
isHistoricalView, const [
is3D, isHistoricalView,
isOnMobile, is3D,
menuOpen, isOnMobile,
menuType, menuOpen,
}) => { menuType,
] = useSelector((state) => [
state.canvas.isHistoricalView,
state.canvas.is3D,
state.user.isOnMobile,
state.contextMenu.menuOpen,
state.contextMenu.menuType,
], shallowEqual);
const contextMenu = (menuOpen && menuType) ? CONTEXT_MENUS[menuType] : null; const contextMenu = (menuOpen && menuType) ? CONTEXT_MENUS[menuType] : null;
if (isHistoricalView) { if (isHistoricalView) {
@ -52,25 +59,4 @@ const UI = ({
]; ];
}; };
function mapStateToProps(state: State) { export default React.memo(UI);
const {
isHistoricalView,
is3D,
} = state.canvas;
const {
isOnMobile,
} = state.user;
const {
menuOpen,
menuType,
} = state.contextMenu;
return {
isHistoricalView,
is3D,
isOnMobile,
menuOpen,
menuType,
};
}
export default connect(mapStateToProps)(UI);

View File

@ -4,7 +4,7 @@
*/ */
import React from 'react'; import React from 'react';
import { connect } from 'react-redux'; import { useSelector, useDispatch, shallowEqual } from 'react-redux';
import { c, t } from 'ttag'; import { c, t } from 'ttag';
import LanguageSelect from '../LanguageSelect'; import LanguageSelect from '../LanguageSelect';
@ -22,8 +22,6 @@ import {
selectStyle, selectStyle,
} from '../../actions'; } from '../../actions';
import type { State } from '../../reducers';
const flexy = { const flexy = {
display: 'flex', display: 'flex',
@ -97,28 +95,32 @@ const SettingsItem = ({
</div> </div>
); );
function Settings({ function Settings() {
isMuted, const [
isGridShown, isGridShown,
isPixelNotifyShown, isPixelNotifyShown,
isPotato, autoZoomIn,
isLightGrid, compactPalette,
isHistoricalView, isPotato,
onMute, isLightGrid,
autoZoomIn, selectedStyle,
compactPalette, isMuted,
selectedStyle, chatNotify,
onToggleGrid, isHistoricalView,
onTogglePixelNotify, ] = useSelector((state) => [
onToggleAutoZoomIn, state.gui.showGrid,
onToggleCompactPalette, state.gui.showPixelNotify,
onToggleChatNotify, state.gui.autoZoomIn,
onTogglePotatoMode, state.gui.compactPalette,
onToggleLightGrid, state.gui.isPotato,
onToggleHistoricalView, state.gui.isLightGrid,
onSelectStyle, state.gui.style,
chatNotify, state.audio.mute,
}) { state.audio.chatNotify,
state.canvas.isHistoricalView,
], shallowEqual);
const dispatch = useDispatch();
return ( return (
<div style={{ paddingLeft: '5%', paddingRight: '5%', paddingTop: 30 }}> <div style={{ paddingLeft: '5%', paddingRight: '5%', paddingTop: 30 }}>
<SettingsItem <SettingsItem
@ -126,14 +128,14 @@ function Settings({
description={t`Turn on grid to highlight pixel borders.`} description={t`Turn on grid to highlight pixel borders.`}
keyBind={c('keybinds').t`G`} keyBind={c('keybinds').t`G`}
value={isGridShown} value={isGridShown}
onToggle={onToggleGrid} onToggle={() => dispatch(toggleGrid())}
/> />
<SettingsItem <SettingsItem
title={t`Show Pixel Activity`} title={t`Show Pixel Activity`}
description={t`Show circles where pixels are placed.`} description={t`Show circles where pixels are placed.`}
keyBind={c('keybinds').t`X`} keyBind={c('keybinds').t`X`}
value={isPixelNotifyShown} value={isPixelNotifyShown}
onToggle={onTogglePixelNotify} onToggle={() => dispatch(togglePixelNotify())}
/> />
<SettingsItem <SettingsItem
title={t`Disable Game Sounds`} title={t`Disable Game Sounds`}
@ -141,39 +143,39 @@ function Settings({
description={t`All sound effects will be disabled.`} description={t`All sound effects will be disabled.`}
keyBind={c('keybinds').t`M`} keyBind={c('keybinds').t`M`}
value={isMuted} value={isMuted}
onToggle={onMute} onToggle={() => dispatch(toggleMute())}
/> />
<SettingsItem <SettingsItem
title={t`Enable chat notifications`} title={t`Enable chat notifications`}
description={t`Play a sound when new chat messages arrive`} description={t`Play a sound when new chat messages arrive`}
value={chatNotify} value={chatNotify}
onToggle={onToggleChatNotify} onToggle={() => dispatch(toggleChatNotify())}
/> />
<SettingsItem <SettingsItem
title={t`Auto Zoom In`} title={t`Auto Zoom In`}
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
description={t`Zoom in instead of placing a pixel when you tap the canvas and your zoom is small.`} description={t`Zoom in instead of placing a pixel when you tap the canvas and your zoom is small.`}
value={autoZoomIn} value={autoZoomIn}
onToggle={onToggleAutoZoomIn} onToggle={() => dispatch(toggleAutoZoomIn())}
/> />
<SettingsItem <SettingsItem
title={t`Compact Palette`} title={t`Compact Palette`}
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
description={t`Display Palette in a compact form that takes less screen space.`} description={t`Display Palette in a compact form that takes less screen space.`}
value={compactPalette} value={compactPalette}
onToggle={onToggleCompactPalette} onToggle={() => dispatch(toggleCompactPalette())}
/> />
<SettingsItem <SettingsItem
title={t`Potato Mode`} title={t`Potato Mode`}
description={t`For when you are playing on a potato.`} description={t`For when you are playing on a potato.`}
value={isPotato} value={isPotato}
onToggle={onTogglePotatoMode} onToggle={() => dispatch(togglePotatoMode())}
/> />
<SettingsItem <SettingsItem
title={t`Light Grid`} title={t`Light Grid`}
description={t`Show Grid in white instead of black.`} description={t`Show Grid in white instead of black.`}
value={isLightGrid} value={isLightGrid}
onToggle={onToggleLightGrid} onToggle={() => dispatch(toggleLightGrid())}
/> />
{(window.ssv && window.ssv.backupurl) && ( {(window.ssv && window.ssv.backupurl) && (
<SettingsItem <SettingsItem
@ -181,7 +183,7 @@ function Settings({
description={t`Check out past versions of the canvas.`} description={t`Check out past versions of the canvas.`}
value={isHistoricalView} value={isHistoricalView}
keyBind={c('keybinds').t`H`} keyBind={c('keybinds').t`H`}
onToggle={onToggleHistoricalView} onToggle={() => dispatch(toggleHistoricalView())}
/> />
)} )}
{(window.ssv && window.ssv.availableStyles) && ( {(window.ssv && window.ssv.availableStyles) && (
@ -190,7 +192,7 @@ function Settings({
description={t`How pixelplanet should look like.`} description={t`How pixelplanet should look like.`}
values={Object.keys(window.ssv.availableStyles)} values={Object.keys(window.ssv.availableStyles)}
selected={selectedStyle} selected={selectedStyle}
onSelect={onSelectStyle} onSelect={(style) => dispatch(selectStyle(style))}
/> />
)} )}
{(window.ssv && navigator.cookieEnabled && window.ssv.langs) && ( {(window.ssv && navigator.cookieEnabled && window.ssv.langs) && (
@ -207,70 +209,4 @@ function Settings({
); );
} }
function mapStateToProps(state: State) { export default React.memo(Settings);
const { mute, chatNotify } = state.audio;
const {
showGrid,
showPixelNotify,
autoZoomIn,
compactPalette,
isPotato,
isLightGrid,
style: selectedStyle,
} = state.gui;
const isMuted = mute;
const {
isHistoricalView,
} = state.canvas;
const isGridShown = showGrid;
const isPixelNotifyShown = showPixelNotify;
return {
isMuted,
isGridShown,
isPixelNotifyShown,
autoZoomIn,
compactPalette,
chatNotify,
isPotato,
isLightGrid,
isHistoricalView,
selectedStyle,
};
}
function mapDispatchToProps(dispatch) {
return {
onMute() {
dispatch(toggleMute());
},
onToggleGrid() {
dispatch(toggleGrid());
},
onTogglePixelNotify() {
dispatch(togglePixelNotify());
},
onToggleAutoZoomIn() {
dispatch(toggleAutoZoomIn());
},
onToggleCompactPalette() {
dispatch(toggleCompactPalette());
},
onToggleChatNotify() {
dispatch(toggleChatNotify());
},
onTogglePotatoMode() {
dispatch(togglePotatoMode());
},
onToggleLightGrid() {
dispatch(toggleLightGrid());
},
onToggleHistoricalView() {
dispatch(toggleHistoricalView());
},
onSelectStyle(style) {
dispatch(selectStyle(style));
},
};
}
export default connect(mapStateToProps, mapDispatchToProps)(Settings);

View File

@ -46,6 +46,18 @@ export function dateToString(date: string) {
return date.substr(0, 4) + date.substr(5, 2) + date.substr(8, 2); return date.substr(0, 4) + date.substr(5, 2) + date.substr(8, 2);
} }
/*
* get current date in YYYY-MM-DD
*/
export function getToday() {
const date = new Date();
let day = date.getDate();
let month = date.getMonth() + 1;
if (month < 10) month = `0${month}`;
if (day < 10) day = `0${day}`;
return `${date.getFullYear()}-${month}-${day}`;
}
// z is assumed to be height here // z is assumed to be height here
// in ui and rendeer, y is height // in ui and rendeer, y is height
export function getChunkOfPixel( export function getChunkOfPixel(