Change Modal layout

fix configure store error
add css transition effects
This commit is contained in:
HF 2020-05-11 09:13:34 +02:00
parent 0ed5193982
commit 0b3afeb6e0
24 changed files with 524 additions and 378 deletions

View File

@ -623,8 +623,8 @@ export function showCanvasSelectionModal(): Action {
return showModal('CANVAS_SELECTION');
}
export function showChatModal(): Action {
if (window.innerWidth > 604) { return toggleChatBox(); }
export function showChatModal(forceModal: boolean = false): Action {
if (window.innerWidth > 604 && !forceModal) { return toggleChatBox(); }
return showModal('CHAT');
}

View File

@ -5,37 +5,31 @@
import React from 'react';
import { connect } from 'react-redux';
// import FaFacebook from 'react-icons/lib/fa/facebook';
// import FaTwitter from 'react-icons/lib/fa/twitter';
// import FaRedditAlien from 'react-icons/lib/fa/reddit-alien';
import Modal from './Modal';
import CanvasItem from './CanvasItem';
import type { State } from '../reducers';
const CanvasSelectModal = ({ canvases }) => (
<Modal title="Canvas Selection">
<p style={{
textAlign: 'center',
paddingLeft: '5%',
paddingRight: '5%',
paddingTop: 20,
}}
>
<p className="modaltext">
Select the canvas you want to use.
Every canvas is unique and has different palettes,
cooldown and requirements.
</p>
{
Object.keys(canvases).map((canvasId) => (
<CanvasItem canvasId={canvasId} canvas={canvases[canvasId]} />
))
}
<p style={{
textAlign: 'center',
paddingLeft: '5%',
paddingRight: '5%',
paddingTop: 20,
}}
>
<p className="modaltext">
Select the canvas you want to use.
Every canvas is unique and has different palettes,
cooldown and requirements.
</p>
</Modal>
{
Object.keys(canvases).map((canvasId) => (
<CanvasItem canvasId={canvasId} canvas={canvases[canvasId]} />
))
}
</p>
);
function mapStateToProps(state: State) {
@ -43,4 +37,9 @@ function mapStateToProps(state: State) {
return { canvases };
}
export default connect(mapStateToProps)(CanvasSelectModal);
const data = {
content: connect(mapStateToProps)(CanvasSelectModal),
title: 'Canvas Selection',
};
export default data;

View File

@ -25,8 +25,8 @@ const Chat = ({ chatMessages, chatChannel }) => {
}, [channelMessages.length]);
return (
<div style={{ height: '100%' }}>
<ul className="chatarea" ref={listRef}>
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<ul className="chatarea" ref={listRef} style={{ flexGrow: 1 }}>
{
channelMessages.map((message) => (
<p className="chatmsg">

View File

@ -3,24 +3,66 @@
* @flow
*/
import React from 'react';
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import type { State } from '../reducers';
import useWindowSize from '../utils/reactHookResize';
import { showChatModal } from '../actions';
import Chat from './Chat';
const ChatBox = ({ chatOpen }) => (
<div className={(chatOpen) ? "chatbox show" : "chatbox"}>
<Chat />
</div>
);
function ChatBox({
chatOpen,
triggerModal,
}) {
const [render, setRender] = useState(false);
useEffect(() => {
window.setTimeout(() => {
if (chatOpen) setRender(true);
}, 10);
}, [chatOpen]);
const onTransitionEnd = () => {
if (!chatOpen) setRender(false);
};
const { width } = useWindowSize();
if (width < 604) {
triggerModal();
}
return (
(render || chatOpen) && (
<div
className={(chatOpen && render) ? 'chatbox show' : 'chatbox'}
onTransitionEnd={onTransitionEnd}
>
<div
id="chatlink"
onClick={triggerModal}
role="button"
tabIndex={-1}
></div>
<Chat />
</div>
)
);
}
// TODO optimize
function mapStateToProps(state: State) {
const { chatOpen } = state.modal;
return { chatOpen };
}
export default connect(mapStateToProps)(ChatBox);
function mapDispatchToProps(dispatch) {
return {
triggerModal() {
dispatch(showChatModal(true));
},
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ChatBox);

View File

@ -25,7 +25,7 @@ const ChatButton = ({ open }) => (
function mapDispatchToProps(dispatch) {
return {
open() {
dispatch(showChatModal());
dispatch(showChatModal(false));
},
};
}

View File

@ -49,33 +49,33 @@ class ChatInput extends React.Component {
<div className="chatinput">
<form
onSubmit={(e) => { this.handleSubmit(e, chatChannel); }}
style={{ display: 'inline' }}
style={{ display: 'flex', flexDirection: 'row' }}
>
<input
style={{ maxWidth: '58%', width: '240px' }}
style={{ flexGrow: 1, minWidth: 40 }}
value={message}
onChange={(evt) => this.setState({ message: evt.target.value })}
type="text"
placeholder="Chat here"
/>
<button
style={{ flexGrow: 0 }}
id="chatmsginput"
type="submit"
style={{ height: 22 }}
>
</button>
<select
style={{ flexGrow: 0 }}
onChange={(evt) => setChannel(evt.target.selectedIndex)}
>
{
CHAT_CHANNELS.map((ch) => (
<option selected={ch === selectedChannel}>{ch}</option>
))
}
</select>
</form>
<select
onChange={(evt) => setChannel(evt.target.selectedIndex)}
style={{ height: 22 }}
>
{
CHAT_CHANNELS.map((ch) => (
<option selected={ch === selectedChannel}>{ch}</option>
))
}
</select>
</div>
);
}

View File

@ -5,19 +5,40 @@
import React from 'react';
import Modal from './Modal';
import Chat from './Chat';
const ChatModal = () => (
<Modal title="Chat">
<div style={{
position: 'fixed',
top: 80,
padding: 10,
bottom: 10,
left: 10,
right: 10,
}}
>
<p style={{ textAlign: 'center' }}>
<p className="modaltext">Chat with other people here</p>
</p>
<div className="inarea" style={{ height: '65%' }}>
<div
className="inarea"
style={{
position: 'absolute',
bottom: 10,
top: 50,
left: 10,
right: 10,
}}
>
<Chat />
</div>
</Modal>
</div>
);
export default ChatModal;
const data = {
content: ChatModal,
title: 'Chat',
};
export default data;

View File

@ -19,8 +19,7 @@ function renderCoordinates(cell): string {
const CoordinatesBox = ({ view, hover, notifyCopy }) => (
<div
className="coorbox"
// eslint-disable-next-line no-restricted-globals
onClick={() => { copy(location.hash); notifyCopy(); }}
onClick={() => { copy(window.location.hash); notifyCopy(); }}
role="button"
title="Copy to Clipboard"
tabIndex="0"

View File

@ -6,24 +6,20 @@
import React from 'react';
import { connect } from 'react-redux';
import Modal from './Modal';
import { showUserAreaModal } from '../actions';
import NewPasswordForm from './NewPasswordForm';
const ForgotPasswordModal = ({ login }) => (
<Modal title="Restore my Password">
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
<p className="modaltext">
Enter your mail adress and we will send you a new password:
</p><br />
<p style={{ textAlign: 'center' }}>
<NewPasswordForm back={login} />
<p>Also join our Discord:&nbsp;
<a href="./discord" target="_blank">pixelplanet.fun/discord</a></p>
</p>
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
<p className="modaltext">
Enter your mail adress and we will send you a new password:
</p><br />
<p style={{ textAlign: 'center' }}>
<NewPasswordForm back={login} />
<p>Also join our Discord:&nbsp;
<a href="./discord" target="_blank">pixelplanet.fun/discord</a></p>
</p>
</Modal>
</p>
);
function mapDispatchToProps(dispatch) {
@ -34,5 +30,9 @@ function mapDispatchToProps(dispatch) {
};
}
const data = {
content: connect(null, mapDispatchToProps)(ForgotPasswordModal),
title: 'Restore my Password',
};
export default connect(null, mapDispatchToProps)(ForgotPasswordModal);
export default data;

View File

@ -10,59 +10,60 @@ import React from 'react';
/* eslint-disable max-len */
import Modal from './Modal';
const HelpModal = () => (
<Modal title="Welcome to PixelPlanet.fun">
<p style={{ textAlign: 'center', paddingLeft: '5%', paddingRight: '5%' }}>
<p className="modaltext">Place color pixels on a large canvas with other players online!
Our main canvas is a huge worldmap, you can place wherever you like, but you will have to wait a specific
Cooldown between pixels. You can check out the cooldown and requiremnts on the Canvas Selection menu (globe button on top).
Some canvases have a different cooldown for replacing a user-set pixels than placing on a unset pixel. i.e. 4s/7s means 4s on fresh
pixels and 7s on already set pixels.
Higher zoomlevels take some time to update, the 3D globe gets updated at least once per day.
Have fun!</p>
<p>Discord: <a href="./discord" target="_blank" rel="noopener noreferrer">pixelplanet.fun/discord</a></p>
<p>Source on <a href="https://github.com/pixelplanetdev/pixelplanet" target="_blank" rel="noopener noreferrer">github</a></p>
<p>Reddit: <a href="https://www.reddit.com/r/PixelPlanetFun/" target="_blank" rel="noopener noreferrer">r/PixelPlanetFun</a></p>
<p className="modaltitle">Map Data</p>
<p className="modaltext">The bare map data that we use, together with converted OpenStreetMap tiles for orientation,
can be downloaded from mega.nz here: <a href="https://mega.nz/#!JpkBwAbJ!EnSLlZmKv3kEBE0HDhakTgAZZycD3ELjduajJxPGaXo">pixelplanetmap.zip</a> (422MB)</p>
<p className="modaltitle">Detected as Proxy?</p>
<p className="modaltext">If you got detected as proxy, but you are none, please send us an e-mail with <a href="https://www.whatismyip.com/">your IP</a> to <a href="mailto:pixelplanetdev@gmail.com">pixelplanetdev@gmail.com</a>. Do not post your IP anywhere else. We are sorry for the inconvenience.</p>
<h3 className="modaltitle">2D Controls</h3>
<p className="modaltext">Click a color in palette to select</p>
<p className="modaltext">Press <kbd>G</kbd> to toggle grid</p>
<p className="modaltext">Press <kbd>X</kbd> to toggle showing of pixel activity</p>
<p className="modaltext">Press <kbd>R</kbd> to copy coordinates</p>
<p className="modaltext">Press <kbd>Q</kbd> or <kbd>E</kbd> to zoom</p>
<p className="modaltext">Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
<p className="modaltext">Press <kbd></kbd>,<kbd></kbd>,<kbd></kbd>, <kbd></kbd> to move</p>
<p className="modaltext">Drag mouse to move</p>
<p className="modaltext">Scroll mouse wheel to zoom</p>
<p className="modaltext">Click middle mouse button to current hovering color</p>
<p className="modaltext">Pinch to zoom (on touch devices)</p>
<p className="modaltext">Pan to move (on touch devices)</p>
<p className="modaltext">Click or tap to place a pixel</p>
<h3 className="modaltitle">3D Controls</h3>
<p className="modaltext">Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
<p className="modaltext">Press <kbd></kbd>,<kbd></kbd>,<kbd></kbd>, <kbd></kbd> to move</p>
<p className="modaltext">Scroll mouse wheel to zoom</p>
<p className="modaltext">Left click and drag mouse to rotate</p>
<p className="modaltext">Middle click and drag mouse to zoom</p>
<p className="modaltext">Right click and drag mouse to pan</p>
<p className="modaltext">Left Click or tap to place a pixel</p>
<p className="modaltext">Right Click of double tap to remove a pixel</p>
<p>Partners: <a href="https://www.crazygames.com/c/io" target="_blank" rel="noopener noreferrer">crazygames.com</a></p>
<p className="modaltext">
<small>This site is protected by reCAPTCHA and the Google
<a href="https://policies.google.com/privacy">Privacy Policy</a> and
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
</small>
</p>
<p style={{ textAlign: 'center', paddingLeft: '5%', paddingRight: '5%' }}>
<p className="modaltext">Place color pixels on a large canvas with other players online!
Our main canvas is a huge worldmap, you can place wherever you like, but you will have to wait a specific
Cooldown between pixels. You can check out the cooldown and requiremnts on the Canvas Selection menu (globe button on top).
Some canvases have a different cooldown for replacing a user-set pixels than placing on a unset pixel. i.e. 4s/7s means 4s on fresh
pixels and 7s on already set pixels.
Higher zoomlevels take some time to update, the 3D globe gets updated at least once per day.
Have fun!</p>
<p>Discord: <a href="./discord" target="_blank" rel="noopener noreferrer">pixelplanet.fun/discord</a></p>
<p>Source on <a href="https://github.com/pixelplanetdev/pixelplanet" target="_blank" rel="noopener noreferrer">github</a></p>
<p>Reddit: <a href="https://www.reddit.com/r/PixelPlanetFun/" target="_blank" rel="noopener noreferrer">r/PixelPlanetFun</a></p>
<p className="modaltitle">Map Data</p>
<p className="modaltext">The bare map data that we use, together with converted OpenStreetMap tiles for orientation,
can be downloaded from mega.nz here: <a href="https://mega.nz/#!JpkBwAbJ!EnSLlZmKv3kEBE0HDhakTgAZZycD3ELjduajJxPGaXo">pixelplanetmap.zip</a> (422MB)</p>
<p className="modaltitle">Detected as Proxy?</p>
<p className="modaltext">If you got detected as proxy, but you are none, please send us an e-mail with <a href="https://www.whatismyip.com/">your IP</a> to <a href="mailto:pixelplanetdev@gmail.com">pixelplanetdev@gmail.com</a>. Do not post your IP anywhere else. We are sorry for the inconvenience.</p>
<h3 className="modaltitle">2D Controls</h3>
<p className="modaltext">Click a color in palette to select</p>
<p className="modaltext">Press <kbd>G</kbd> to toggle grid</p>
<p className="modaltext">Press <kbd>X</kbd> to toggle showing of pixel activity</p>
<p className="modaltext">Press <kbd>R</kbd> to copy coordinates</p>
<p className="modaltext">Press <kbd>Q</kbd> or <kbd>E</kbd> to zoom</p>
<p className="modaltext">Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
<p className="modaltext">Press <kbd></kbd>,<kbd></kbd>,<kbd></kbd>, <kbd></kbd> to move</p>
<p className="modaltext">Drag mouse to move</p>
<p className="modaltext">Scroll mouse wheel to zoom</p>
<p className="modaltext">Click middle mouse button to current hovering color</p>
<p className="modaltext">Pinch to zoom (on touch devices)</p>
<p className="modaltext">Pan to move (on touch devices)</p>
<p className="modaltext">Click or tap to place a pixel</p>
<h3 className="modaltitle">3D Controls</h3>
<p className="modaltext">Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
<p className="modaltext">Press <kbd></kbd>,<kbd></kbd>,<kbd></kbd>, <kbd></kbd> to move</p>
<p className="modaltext">Scroll mouse wheel to zoom</p>
<p className="modaltext">Left click and drag mouse to rotate</p>
<p className="modaltext">Middle click and drag mouse to zoom</p>
<p className="modaltext">Right click and drag mouse to pan</p>
<p className="modaltext">Left Click or tap to place a pixel</p>
<p className="modaltext">Right Click of double tap to remove a pixel</p>
<p>Partners: <a href="https://www.crazygames.com/c/io" target="_blank" rel="noopener noreferrer">crazygames.com</a></p>
<p className="modaltext">
<small>This site is protected by reCAPTCHA and the Google
<a href="https://policies.google.com/privacy">Privacy Policy</a> and
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
</small>
</p>
</Modal>
</p>
);
export default HelpModal;
const data = {
content: HelpModal,
title: 'Welcome to PixelPlanet.fun',
};
export default data;

View File

@ -4,7 +4,7 @@
* @flow
*/
import React from 'react';
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import HelpButton from './HelpButton';
@ -13,15 +13,36 @@ import LogInButton from './LogInButton';
import DownloadButton from './DownloadButton';
import MinecraftButton from './MinecraftButton';
const Menu = ({ menuOpen }) => (
<div className={menuOpen ? 'menu show' : 'menu'}>
<SettingsButton />
<LogInButton />
<DownloadButton />
<MinecraftButton />
<HelpButton />
</div>
);
function Menu({
menuOpen,
}) {
const [render, setRender] = useState(false);
useEffect(() => {
window.setTimeout(() => {
if (menuOpen) setRender(true);
}, 10);
}, [menuOpen]);
const onTransitionEnd = () => {
if (!menuOpen) setRender(false);
};
return (
(render || menuOpen) && (
<div
className={menuOpen ? 'menu show' : 'menu'}
onTransitionEnd={onTransitionEnd}
>
<SettingsButton />
<LogInButton />
<DownloadButton />
<MinecraftButton />
<HelpButton />
</div>
)
);
}
function mapStateToProps(state: State) {
const { menuOpen } = state.gui;

View File

@ -6,17 +6,13 @@
import React from 'react';
import { connect } from 'react-redux';
import Modal from './Modal';
const MinecraftModal = () => (
<Modal title="PixelPlanet Minecraft Server">
<p style={{ textAlign: 'center' }}>
<p>You can also place pixels from our Minecraft Server at</p>
<p><input type="text" value="mc.pixelplanet.fun" readOnly /></p>
<p>Please Note that the Minecraft Server is down from time to time</p>
</p>
</Modal>
<p style={{ textAlign: 'center' }}>
<p>You can also place pixels from our Minecraft Server at</p>
<p><input type="text" value="mc.pixelplanet.fun" readOnly /></p>
<p>Please Note that the Minecraft Server is down from time to time</p>
</p>
);
function mapStateToProps(state: State) {
@ -24,4 +20,9 @@ function mapStateToProps(state: State) {
return { center };
}
export default connect(mapStateToProps)(MinecraftModal);
const data = {
content: connect(mapStateToProps)(MinecraftModal),
title: 'PixelPlanet Minecraft Server',
};
export default data;

View File

@ -1,47 +0,0 @@
/**
*
* @flow
*/
import React from 'react';
import Modal from 'react-modal';
import { connect } from 'react-redux';
import { MdClose } from 'react-icons/md';
import {
hideModal,
} from '../actions';
function MyModal({ close, title, children }) {
return (
<Modal
isOpen
onClose={close}
className="Modal"
overlayClassName="Overlay"
contentLabel={`${title} Modal`}
onRequestClose={close}
>
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
<div
onClick={close}
className="ModalClose"
role="button"
label="close"
tabIndex={-1}
><MdClose /></div>
{children}
</Modal>
);
}
function mapDispatchToProps(dispatch) {
return {
close() {
dispatch(hideModal());
},
};
}
export default connect(null, mapDispatchToProps)(MyModal);

View File

@ -6,7 +6,13 @@
*/
import React from 'react';
import Modal from 'react-modal';
import { connect } from 'react-redux';
import { MdClose } from 'react-icons/md';
import {
hideModal,
} from '../actions';
import HelpModal from './HelpModal';
import SettingsModal from './SettingsModal';
@ -19,6 +25,7 @@ import MinecraftModal from './MinecraftModal';
const MODAL_COMPONENTS = {
NONE: { content: <div />, title: '' },
HELP: HelpModal,
SETTINGS: SettingsModal,
USERAREA: UserAreaModal,
@ -30,15 +37,43 @@ const MODAL_COMPONENTS = {
/* other modals */
};
const ModalRoot = ({ modalType }) => {
if (!modalType) {
return null;
}
const SpecificModal = MODAL_COMPONENTS[modalType];
return <SpecificModal />;
const ModalRoot = ({ modalType, modalOpen, close }) => {
const choice = MODAL_COMPONENTS[modalType || 'NONE'];
const { content: SpecificModal, title } = choice;
return (
<Modal
isOpen={modalOpen}
onClose={close}
className="Modal"
overlayClassName="Overlay"
contentLabel={`${title} Modal`}
closeTimeoutMS={200}
onRequestClose={close}
>
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
<div
onClick={close}
className="ModalClose"
role="button"
label="close"
tabIndex={-1}
><MdClose /></div>
<SpecificModal />
</Modal>
);
};
export default connect(
(state) => state.modal,
)(ModalRoot);
function mapStateToProps(state: State) {
const { modalType, modalOpen } = state.modal;
return { modalType, modalOpen };
}
function mapDispatchToProps(dispatch) {
return {
close() {
dispatch(hideModal());
},
};
}
export default connect(mapStateToProps, mapDispatchToProps)(ModalRoot);

View File

@ -7,8 +7,8 @@ import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { selectColor } from '../actions';
import type { State } from '../reducers';
import useWindowSize from '../utils/reactHookResize';
/*
@ -90,27 +90,6 @@ function getStylesByWindowSize(
}];
}
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowSize;
}
function Palette({
colors,
selectedColor,
@ -119,8 +98,20 @@ function Palette({
select,
clrIgnore,
}) {
const [render, setRender] = useState(false);
useEffect(() => {
window.setTimeout(() => {
if (paletteOpen) setRender(true);
}, 10);
}, [paletteOpen]);
const onTransitionEnd = () => {
if (!paletteOpen) setRender(false);
};
const [paletteStyle, spanStyle] = getStylesByWindowSize(
paletteOpen,
(render && paletteOpen),
useWindowSize(),
colors,
clrIgnore,
@ -128,28 +119,31 @@ function Palette({
);
return (
<div
id="palettebox"
style={paletteStyle}
>
{colors.slice(2).map((color, index) => (
<span
style={{
backgroundColor: color,
...spanStyle,
}}
role="button"
tabIndex={0}
aria-label={`color ${index + 2}`}
key={color}
className={selectedColor === (index + clrIgnore)
? 'selected'
: 'unselected'}
color={color}
onClick={() => select(index + clrIgnore)}
/>
))}
</div>
(render || paletteOpen) && (
<div
id="palettebox"
style={paletteStyle}
onTransitionEnd={onTransitionEnd}
>
{colors.slice(2).map((color, index) => (
<span
style={{
backgroundColor: color,
...spanStyle,
}}
role="button"
tabIndex={0}
aria-label={`color ${index + 2}`}
key={color}
className={selectedColor === (index + clrIgnore)
? 'selected'
: 'unselected'}
color={color}
onClick={() => select(index + clrIgnore)}
/>
))}
</div>
)
);
}

View File

@ -6,8 +6,6 @@
import React from 'react';
import { connect } from 'react-redux';
import Modal from './Modal';
import { showUserAreaModal } from '../actions';
// import { send_registration } from '../ui/register';
@ -15,17 +13,15 @@ import SignUpForm from './SignUpForm';
const RegisterModal = ({ login }) => (
<Modal title="Register New Account">
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
<p className="modaltext">Register new account here</p><br />
<p style={{ textAlign: 'center' }}>
<SignUpForm back={login} />
<p>Also join our Discord:&nbsp;
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
</p>
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
<p className="modaltext">Register new account here</p><br />
<p style={{ textAlign: 'center' }}>
<SignUpForm back={login} />
<p>Also join our Discord:&nbsp;
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
</p>
</p>
</Modal>
</p>
);
function mapDispatchToProps(dispatch) {
@ -36,4 +32,9 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(null, mapDispatchToProps)(RegisterModal);
const data = {
content: connect(null, mapDispatchToProps)(RegisterModal),
title: 'Register New Account',
};
export default data;

View File

@ -6,7 +6,6 @@
import React from 'react';
import { connect } from 'react-redux';
import Modal from './Modal';
import MdToggleButtonHover from './MdToggleButtonHover';
import {
toggleGrid,
@ -118,82 +117,80 @@ function SettingsModal({
chatNotify,
}) {
return (
<Modal title="Settings">
<p style={{ paddingLeft: '5%', paddingRight: '5%', paddingTop: 30 }}>
<SettingsItem
title="Show Grid"
description="Turn on grid to highlight pixel borders."
keyBind="G"
value={isGridShown}
onToggle={onToggleGrid}
/>
<SettingsItem
title="Show Pixel Activity"
description="Show circles where pixels are placed."
keyBind="X"
value={isPixelNotifyShown}
onToggle={onTogglePixelNotify}
/>
<SettingsItem
title="Disable Game Sounds"
// eslint-disable-next-line max-len
description="All sound effects except Chat Notification will be disabled."
keyBind="M"
value={isMuted}
onToggle={onMute}
/>
<SettingsItem
title="Enable chat notifications"
description="Play a sound when new chat messages arrive"
value={chatNotify}
onToggle={onToggleChatNotify}
/>
<SettingsItem
title="Auto Zoom In"
// eslint-disable-next-line max-len
description="Zoom in instead of placing a pixel when you tap the canvas and your zoom is small."
value={autoZoomIn}
onToggle={onToggleAutoZoomIn}
/>
<SettingsItem
title="Compact Palette"
// eslint-disable-next-line max-len
description="Display Palette in a compact form that takes less screen space."
value={compactPalette}
onToggle={onToggleCompactPalette}
/>
<SettingsItem
title="Potato Mode"
description="For when you are playing on a potato."
value={isPotato}
onToggle={onTogglePotatoMode}
/>
<SettingsItem
title="Light Grid"
description="Show Grid in white instead of black."
value={isLightGrid}
onToggle={onToggleLightGrid}
/>
{ (window.backupurl)
? (
<SettingsItem
title="Historical View"
description="Check out past versions of the canvas."
value={isHistoricalView}
onToggle={onToggleHistoricalView}
/>
) : null }
{(typeof window.availableStyles !== 'undefined') && (
<SettingsItemSelect
title="Themes"
description="How pixelplanet should look like."
values={Object.keys(window.availableStyles)}
selected={selectedStyle}
onSelect={onSelectStyle}
<p style={{ paddingLeft: '5%', paddingRight: '5%', paddingTop: 30 }}>
<SettingsItem
title="Show Grid"
description="Turn on grid to highlight pixel borders."
keyBind="G"
value={isGridShown}
onToggle={onToggleGrid}
/>
<SettingsItem
title="Show Pixel Activity"
description="Show circles where pixels are placed."
keyBind="X"
value={isPixelNotifyShown}
onToggle={onTogglePixelNotify}
/>
<SettingsItem
title="Disable Game Sounds"
// eslint-disable-next-line max-len
description="All sound effects except Chat Notification will be disabled."
keyBind="M"
value={isMuted}
onToggle={onMute}
/>
<SettingsItem
title="Enable chat notifications"
description="Play a sound when new chat messages arrive"
value={chatNotify}
onToggle={onToggleChatNotify}
/>
<SettingsItem
title="Auto Zoom In"
// eslint-disable-next-line max-len
description="Zoom in instead of placing a pixel when you tap the canvas and your zoom is small."
value={autoZoomIn}
onToggle={onToggleAutoZoomIn}
/>
<SettingsItem
title="Compact Palette"
// eslint-disable-next-line max-len
description="Display Palette in a compact form that takes less screen space."
value={compactPalette}
onToggle={onToggleCompactPalette}
/>
<SettingsItem
title="Potato Mode"
description="For when you are playing on a potato."
value={isPotato}
onToggle={onTogglePotatoMode}
/>
<SettingsItem
title="Light Grid"
description="Show Grid in white instead of black."
value={isLightGrid}
onToggle={onToggleLightGrid}
/>
{ (window.backupurl)
? (
<SettingsItem
title="Historical View"
description="Check out past versions of the canvas."
value={isHistoricalView}
onToggle={onToggleHistoricalView}
/>
)}
</p>
</Modal>
) : null }
{(typeof window.availableStyles !== 'undefined') && (
<SettingsItemSelect
title="Themes"
description="How pixelplanet should look like."
values={Object.keys(window.availableStyles)}
selected={selectedStyle}
onSelect={onSelectStyle}
/>
)}
</p>
);
}
@ -263,4 +260,9 @@ function mapDispatchToProps(dispatch) {
};
}
export default connect(mapStateToProps, mapDispatchToProps)(SettingsModal);
const data = {
content: connect(mapStateToProps, mapDispatchToProps)(SettingsModal),
title: 'Settings',
};
export default data;

View File

@ -6,8 +6,6 @@
import React, { Suspense } from 'react';
import { connect } from 'react-redux';
import Modal from './Modal';
import type { State } from '../reducers';
@ -86,40 +84,38 @@ const LogInArea = ({ register, forgotPassword, me }) => (
const UserAreaModal = ({
name, register, forgotPassword, doMe, logout, setUserName, setUserMailreg,
}) => (
<Modal title="User Area">
<p style={{ textAlign: 'center' }}>
{(name === null)
? (
<LogInArea
register={register}
forgotPassword={forgotPassword}
me={doMe}
/>
)
: (
<Tabs>
<div label="Profile">
<UserArea
logout={logout}
setName={setUserName}
setMailreg={setUserMailreg}
/>
</div>
<div label="Ranking">
<Rankings />
</div>
<div label="Converter">
<Suspense fallback={<div>Loading...</div>}>
<Converter />
</Suspense>
</div>
</Tabs>
)}
<p>Also join our Discord:&nbsp;
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
</p>
<p style={{ textAlign: 'center' }}>
{(name === null)
? (
<LogInArea
register={register}
forgotPassword={forgotPassword}
me={doMe}
/>
)
: (
<Tabs>
<div label="Profile">
<UserArea
logout={logout}
setName={setUserName}
setMailreg={setUserMailreg}
/>
</div>
<div label="Ranking">
<Rankings />
</div>
<div label="Converter">
<Suspense fallback={<div>Loading...</div>}>
<Converter />
</Suspense>
</div>
</Tabs>
)}
<p>Also join our Discord:&nbsp;
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
</p>
</Modal>
</p>
);
function mapDispatchToProps(dispatch) {
@ -157,4 +153,9 @@ function mapStateToProps(state: State) {
return { name };
}
export default connect(mapStateToProps, mapDispatchToProps)(UserAreaModal);
const data = {
content: connect(mapStateToProps, mapDispatchToProps)(UserAreaModal),
title: 'User Area',
};
export default data;

View File

@ -7,11 +7,13 @@
import type { Action } from '../actions/types';
export type ModalState = {
modalOpen: boolean,
modalType: ?string,
chatOpen: boolean,
};
const initialState: ModalState = {
modalOpen: false,
modalType: null,
chatOpen: false,
};
@ -31,6 +33,7 @@ export default function modal(
...state,
modalType,
chatOpen,
modalOpen: true,
};
}
@ -38,7 +41,7 @@ export default function modal(
case 'HIDE_MODAL':
return {
...state,
modalType: null,
modalOpen: false,
};
case 'TOGGLE_CHAT_BOX': {

View File

@ -41,7 +41,7 @@ tr:nth-child(even) {
border-radius: 21px;
}
#menu > div {
.menu > div {
z-index: 1;
background-color: #15374fd1;
}
@ -81,6 +81,10 @@ tr:nth-child(even) {
border-color: #dcddde;
}
.ModalClose:hover {
background-color: #6f6f75;
}
.Overlay {
background-color: rgba(187, 187, 187, 0.75);
}
@ -89,6 +93,10 @@ tr:nth-child(even) {
color: white;
}
#chatlink {
color: #f9edde;
}
.statvalue {
color: #ecc9ff;
}
@ -98,7 +106,7 @@ tr:nth-child(even) {
border-radius: 21px;
}
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
.actionbuttons:hover, .coorbox:hover, .menu > div:hover {
background-color: #363637;
}

View File

@ -39,7 +39,7 @@ tr:nth-child(even) {
color: #f4f4f4;
}
#menu > div {
.menu > div {
z-index: 1;
background-color: #15374fd1;
}
@ -78,6 +78,10 @@ tr:nth-child(even) {
border-color: #dcddde;
}
.ModalClose:hover {
background-color: #6f6f75;
}
.Overlay {
background-color: rgba(187, 187, 187, 0.75);
}
@ -86,6 +90,10 @@ tr:nth-child(even) {
color: white;
}
#chatlink {
color: #f9edde;
}
.statvalue {
color: #ecc9ff;
}
@ -94,7 +102,7 @@ tr:nth-child(even) {
background-color: rgba(59, 59, 59, 0.8);
}
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
.actionbuttons:hover, .coorbox:hover, .menu > div:hover {
background-color: #363637;
}

View File

@ -162,7 +162,7 @@ tr:nth-child(even) {
.menu {
opacity: 0;
visibility: hidden;
transition: all .1s cubic-bezier(.46,.03,.52,.96);
transition: all .15s cubic-bezier(.46,.03,.52,.96);
}
.menu.show {
@ -341,6 +341,11 @@ tr:nth-child(even) {
border-color: #dcddde;
top: 30px;
right: 40px;
z-index: 5;
}
.ModalClose:hover {
background-color: #e3e3e4;
}
@media (max-width: 604px) {
@ -376,7 +381,6 @@ tr:nth-child(even) {
margin: 0px;
overflow-x: hidden;
overflow-y: scroll;
height: 95%;
}
.chatinput {
height: 22px;
@ -393,6 +397,15 @@ tr:nth-child(even) {
user-select: text;
margin: 0;
}
#chatlink {
position: absolute;
font-weight: bold;
font-size: 20px;
right: 17px;
top: 5px;
color: #4a4a49;
cursor: pointer;
}
.usermessages {
font-size: 14px;
@ -477,7 +490,7 @@ tr:nth-child(even) {
}
#palettebox, #palettebox span {
transition: 0.3s;
transition: 0.2s;
}
#palettebox .selected,
@ -506,3 +519,16 @@ tr:nth-child(even) {
.grecaptcha-badge {
visibility: hidden;
}
.ReactModal__Overlay {
opacity: 0;
transition: opacity 200ms ease-in-out;
}
.ReactModal__Overlay--after-open{
opacity: 1;
}
.ReactModal__Overlay--before-close{
opacity: 0;
}

View File

@ -5,6 +5,6 @@
import configureStore from '../store/configureStore';
const store = configureStore();
const store = configureStore(() => null);
export default store;

View File

@ -0,0 +1,31 @@
/*
* @flex
*
* can be used in react components
* to trigger on window resize
*/
import { useState, useEffect } from 'react';
function useWindowSize() {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
useEffect(() => {
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return windowSize;
}
export default useWindowSize;