forked from ppfun/pixelplanet
split stylesheet from js, style selection and fix all lsint errors
This commit is contained in:
parent
358b5a3ce0
commit
fb167337bb
|
@ -145,6 +145,10 @@ If you want to add a new canvas, be sure that you additionally create `public/lo
|
|||
|
||||
The default configuration values can be seen in `src/core/config.js` and for the canvases in `src/core/constats.js`
|
||||
|
||||
#### Styles
|
||||
|
||||
To add more css styles, create a new css file in `src/styles` based on `src/styles/default.css` and add it to the FILES array in `tools/minifyCss.js`
|
||||
|
||||
### Running
|
||||
|
||||
1. Make sure that mysql and redis are running
|
||||
|
@ -206,7 +210,7 @@ After=network.target mysql.service redis.service
|
|||
### Development
|
||||
|
||||
Run `npm run lint:src` to check for code errors and warnings or `npm run lint -- ./your/file.js` to check a single file.
|
||||
We have enough warnings already, just don't produce too many additional ones.
|
||||
Please do not produce too many additional warnings.
|
||||
|
||||
You can use `npm run babel-node ./your/script.js` to execute a script with local babel.
|
||||
|
||||
|
|
|
@ -1,25 +1,22 @@
|
|||
#!/bin/bash
|
||||
# This hook builds pixelplanet after a push, and deploys it
|
||||
# If it is the production branch, it will deploy it on the life system, and other branch will get deployed to the dev-canvas (a second canvas that is running on the server)
|
||||
# canvases.json, proxies.json and ecosystem.yml are already in the terget directories
|
||||
# Update messages will get sent via the Webhooks to Discord
|
||||
#
|
||||
# To set up a server to use this, you have to go through the building steps manually first.
|
||||
# This hook just builds the canvas, it does not install new yarn/npm packages if needed. So this has to be done manually first
|
||||
# Also keep in mind that running a dev-canvas and a life canvas independently together on one server needs two redis installations.
|
||||
# tl;dr: Don't just copy that script, try to know how that setup works first
|
||||
# This hook just builds the canvas, it does not install new packages if needed. So this has to be done manually first
|
||||
#
|
||||
#discord webhook for dev canvas
|
||||
WEBHOOK='https://discordapp.com/api/webhooks/'
|
||||
WEBHOOK='https://discordapp.com/api/webhooks/5440815510.....'
|
||||
#discord webhook for production canvas
|
||||
PWEBHOOK='https://discordapp.com/api/webhooks/'
|
||||
PWEBHOOK='https://discordapp.com/api/webhooks/54413213......'
|
||||
#folder for building the canvas (the git repository will get checkout there and the canvas will get buil thtere)
|
||||
BUILDDIR="pixelplanet-build"
|
||||
BUILDDIR="/home/pixelpla/pixelplanet-build"
|
||||
#folder for dev canvas
|
||||
DEVFOLDER="pixelplanet-dev"
|
||||
DEVFOLDER="/home/pixelpla/pixelplanet-dev"
|
||||
#folder for production canvas
|
||||
PFOLDER="pixelplanet"
|
||||
#proxies.json path
|
||||
PROXYFILE="/proxies.json"
|
||||
PFOLDER="/home/pixelpla/pixelplanet"
|
||||
|
||||
while read oldrev newrev refname
|
||||
do
|
||||
|
@ -33,35 +30,40 @@ do
|
|||
COMMITS=`echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\\n/g'`
|
||||
echo "---BUILDING pixelplanet---"
|
||||
cd "$BUILDDIR"
|
||||
cp "$PROXYFILE" ./src/
|
||||
yarn run build --release
|
||||
npm run build
|
||||
echo "---RESTARTING CANVAS---"
|
||||
cp -r build/* "${PFOLDER}/"
|
||||
cp -r build/*.js "${PFOLDER}/"
|
||||
cp -r build/public "${PFOLDER}/"
|
||||
cp -r build/package.json "${PFOLDER}/"
|
||||
cp -r build/assets.json "${PFOLDER}/"
|
||||
cp -r build/styleassets.json "${PFOLDER}/"
|
||||
mkdir -p "${PFOLDER}/log"
|
||||
#cp ecosystem-production.yml "${PFOLDER}/ecosystem.yml"
|
||||
cd "$PFOLDER"
|
||||
pm2 stop web
|
||||
pm2 start ecosystem.yml
|
||||
#make backup
|
||||
tar -cvJf /backup/pixelplanet-src/pixelplanet-src-`date +%Y%m%d`.tar.xz --exclude=node_modules --exclude=.git -C "${BUILDDIR}/.." "pixelplanet-build"
|
||||
#send update message to discord
|
||||
curl -H "Content-Type: application/json" --data-binary '{ "username": "PixelPlanet Server", "avatar_url": "https://pixelplanet.fun/favicon.ico", "content": "...Done", "embeds": [{"title": "New Commits", "url": "https://pixelplanet.fun", "description": "'"$COMMITS"'", "color": 15258703}] }' "$PWEBHOOK"
|
||||
else
|
||||
echo "---UPDATING REPO ON DEV SERVER---"
|
||||
pm2 stop web-dev
|
||||
GIT_WORK_TREE="$BUILDDIR" GIT_DIR="${BUILDDIR}/.git" git fetch --all
|
||||
GIT_WORK_TREE="$BUILDDIR" GIT_DIR="${BUILDDIR}/.git" git reset --hard "origin/$branch"
|
||||
curl -H "Content-Type: application/json" --data-binary '{ "username": "PixelPlanet Server", "avatar_url": "https://pixelplanet.fun/favicon.ico", "content": "Restarting pixelplanet development canvas for update..." }' "$WEBHOOK"
|
||||
#curl -H "Content-Type: application/json" --data-binary '{ "username": "PixelPlanet Server", "avatar_url": "https://pixelplanet.fun/favicon.ico", "content": "Restarting pixelplanet development canvas for update..." }' "$WEBHOOK"
|
||||
COMMITS=`git log --pretty=format:'- %s%b' $newrev ^$oldrev`
|
||||
COMMITS=`echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\\n/g'`
|
||||
echo "---BUILDING pixelplanet---"
|
||||
cd "$BUILDDIR"
|
||||
cp "$PROXYFILE" ./src/
|
||||
nice -n 19 yarn run build --release
|
||||
nice -n 19 npm run build
|
||||
echo "---RESTARTING CANVAS---"
|
||||
cp -r build/* "${DEVFOLDER}/"
|
||||
cp -r build/*.js "${DEVFOLDER}/"
|
||||
cp -r build/public "${DEVFOLDER}/"
|
||||
cp -r build/package.json "${DEVFOLDER}/"
|
||||
cp -r build/assets.json "${DEVFOLDER}/"
|
||||
cp -r build/styleassets.json "${DEVFOLDER}/"
|
||||
mkdir -p "${PFOLDER}/log"
|
||||
#cp ecosystem-dev.yml "${DEVFOLDER}/ecosystem.yml"
|
||||
cd "$DEVFOLDER"
|
||||
pm2 start ecosystem.yml
|
||||
curl -H "Content-Type: application/json" --data-binary '{ "username": "PixelPlanet Server", "avatar_url": "https://pixelplanet.fun/favicon.ico", "content": "...Done\nhttp://dev.pixelplanet.fun is now on branch '"$branch"'", "embeds": [{"title": "New Commits", "url": "https://pixelplanet.fun", "description": "'"$COMMITS"'", "color": 15258703}] }' "$WEBHOOK"
|
||||
#curl -H "Content-Type: application/json" --data-binary '{ "username": "PixelPlanet Server", "avatar_url": "https://pixelplanet.fun/favicon.ico", "content": "...Done\nhttp://dev.pixelplanet.fun is now on branch '"$branch"'", "embeds": [{"title": "New Commits", "url": "https://pixelplanet.fun", "description": "'"$COMMITS"'", "color": 15258703}] }' "$WEBHOOK"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
|
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -4210,6 +4210,23 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
|
||||
"integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"source-map": "~0.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli-boxes": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
|
||||
|
|
|
@ -112,6 +112,7 @@
|
|||
"@babel/preset-flow": "^7.9.0",
|
||||
"@babel/preset-react": "^7.9.4",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
"clean-css": "^4.2.3",
|
||||
"assets-webpack-plugin": "^3.9.12",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
|
|
|
@ -89,6 +89,13 @@ export function toggleOpenPalette(): Action {
|
|||
};
|
||||
}
|
||||
|
||||
export function selectStyle(style: string): Action {
|
||||
return {
|
||||
type: 'SELECT_STYLE',
|
||||
style,
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleOpenMenu(): Action {
|
||||
return {
|
||||
type: 'TOGGLE_OPEN_MENU',
|
||||
|
@ -581,11 +588,10 @@ export function initTimer(): ThunkAction {
|
|||
};
|
||||
}
|
||||
|
||||
export function showModal(modalType: string, modalProps: Object = {}): Action {
|
||||
export function showModal(modalType: string): Action {
|
||||
return {
|
||||
type: 'SHOW_MODAL',
|
||||
modalType,
|
||||
modalProps,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export type Action =
|
|||
| { type: 'TOGGLE_LIGHT_GRID' }
|
||||
| { type: 'TOGGLE_OPEN_MENU' }
|
||||
| { type: 'TOGGLE_HISTORICAL_VIEW' }
|
||||
| { type: 'SELECT_STYLE', style: string }
|
||||
| { type: 'SET_NOTIFICATION', notification: string }
|
||||
| { type: 'UNSET_NOTIFICATION' }
|
||||
| { type: 'SET_PLACE_ALLOWED', placeAllowed: boolean }
|
||||
|
@ -78,15 +79,10 @@ export type Action =
|
|||
| { type: 'SET_MINECRAFT_NAME', minecraftname: string }
|
||||
| { type: 'SET_MAILREG', mailreg: boolean }
|
||||
| { type: 'REM_FROM_MESSAGES', message: string }
|
||||
| { type: 'SHOW_MODAL', modalType: string, modalProps: obj }
|
||||
| { type: 'SHOW_MODAL', modalType: string }
|
||||
| { type: 'HIDE_MODAL' }
|
||||
| { type: 'RELOAD_URL' }
|
||||
| { type: 'SET_HISTORICAL_TIME', date: string, time: string }
|
||||
| { type: 'ON_VIEW_FINISH_CHANGE' };
|
||||
export type PromiseAction = Promise<Action>;
|
||||
export type Dispatch = (action: Action
|
||||
| ThunkAction
|
||||
| PromiseAction
|
||||
| Array<Action>) => any;
|
||||
export type GetState = () => State;
|
||||
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import fetch from 'isomorphic-fetch'; // TODO put in the beggining with webpack!
|
||||
|
||||
import './components/font.css';
|
||||
import './styles/font.css';
|
||||
|
||||
// import initAds, { requestAds } from './ui/ads';
|
||||
import onKeyPress from './controls/keypress';
|
||||
|
@ -24,7 +21,7 @@ import {
|
|||
import store from './ui/store';
|
||||
|
||||
|
||||
import App from './components/App';
|
||||
import renderApp from './components/App';
|
||||
|
||||
import { initRenderer, getRenderer } from './ui/renderer';
|
||||
import ProtocolClient from './socket/ProtocolClient';
|
||||
|
@ -97,12 +94,7 @@ function init() {
|
|||
init();
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>,
|
||||
document.getElementById('app'),
|
||||
);
|
||||
renderApp(document.getElementById('app'));
|
||||
|
||||
document.addEventListener('keydown', onKeyPress, false);
|
||||
|
||||
|
|
|
@ -4,8 +4,12 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { IconContext } from 'react-icons';
|
||||
|
||||
import store from '../ui/store';
|
||||
|
||||
import CoordinatesBox from './CoordinatesBox';
|
||||
import CanvasSwitchButton from './CanvasSwitchButton';
|
||||
import OnlineBox from './OnlineBox';
|
||||
|
@ -17,12 +21,8 @@ import ReCaptcha from './ReCaptcha';
|
|||
import ExpandMenuButton from './ExpandMenuButton';
|
||||
import ModalRoot from './ModalRoot';
|
||||
|
||||
import baseCss from './base.tcss';
|
||||
|
||||
const App = () => (
|
||||
<div>
|
||||
{/* eslint-disable-next-line react/no-danger */}
|
||||
<style dangerouslySetInnerHTML={{ __html: baseCss }} />
|
||||
<div id="outstreamContainer" />
|
||||
<ReCaptcha />
|
||||
<IconContext.Provider value={{ style: { verticalAlign: 'middle' } }}>
|
||||
|
@ -39,4 +39,13 @@ const App = () => (
|
|||
</div>
|
||||
);
|
||||
|
||||
export default App;
|
||||
function renderApp(domParent) {
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<App />
|
||||
</Provider>,
|
||||
domParent,
|
||||
);
|
||||
}
|
||||
|
||||
export default renderApp;
|
||||
|
|
|
@ -10,38 +10,6 @@ import { THREE_CANVAS_HEIGHT } from '../core/constants';
|
|||
import { selectCanvas } from '../actions';
|
||||
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
padding: 0,
|
||||
display: 'inline-block',
|
||||
verticalAlign: 'middle',
|
||||
marginTop: 3,
|
||||
marginBottom: 3,
|
||||
width: '75%',
|
||||
};
|
||||
|
||||
const infoStyle = {
|
||||
color: '#4f545c',
|
||||
fontSize: 15,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
};
|
||||
|
||||
const titleStyle = {
|
||||
color: '#4f545c',
|
||||
overflow: 'hidden',
|
||||
wordWrap: 'break-word',
|
||||
lineHeight: '26px',
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
|
||||
const buttonStyle = {
|
||||
marginTop: 8,
|
||||
marginBottom: 8,
|
||||
|
@ -71,29 +39,29 @@ const CanvasItem = ({ canvasId, canvas, changeCanvas }) => (
|
|||
alt="preview"
|
||||
src={`/preview${canvasId}.png`}
|
||||
/>
|
||||
<p style={textStyle}>
|
||||
<span style={titleStyle}>{canvas.title}</span><br />
|
||||
<span style={infoStyle}>{canvas.desc}</span><br />
|
||||
<p className="modalcvtext">
|
||||
<span className="modaltitle">{canvas.title}</span><br />
|
||||
<span className="modalinfo">{canvas.desc}</span><br />
|
||||
Cooldown:
|
||||
|
||||
<span style={infoStyle}>
|
||||
<span className="modalinfo">
|
||||
{(canvas.bcd !== canvas.pcd)
|
||||
? <span> {canvas.bcd / 1000}s / {canvas.pcd / 1000}s</span>
|
||||
: <span> {canvas.bcd / 1000}s</span>}
|
||||
</span><br />
|
||||
Stacking till
|
||||
<span style={infoStyle}> {canvas.cds / 1000}s</span><br />
|
||||
<span className="modalinfo"> {canvas.cds / 1000}s</span><br />
|
||||
Ranked:
|
||||
|
||||
<span style={infoStyle}>{(canvas.ranked) ? 'Yes' : 'No'}</span><br />
|
||||
<span className="modalinfo">{(canvas.ranked) ? 'Yes' : 'No'}</span><br />
|
||||
{(canvas.req !== -1) ? <span>Requirements:<br /></span> : null}
|
||||
<span style={infoStyle}>
|
||||
<span className="modalinfo">
|
||||
{(canvas.req !== -1) ? <span>User Account </span> : null}
|
||||
{(canvas.req > 0) ? <span> and {canvas.req} Pixels set</span> : null}
|
||||
</span>
|
||||
{(canvas.req !== -1) ? <br /> : null}
|
||||
Dimensions:
|
||||
<span style={infoStyle}> {canvas.size} x {canvas.size}
|
||||
<span className="modalinfo"> {canvas.size} x {canvas.size}
|
||||
{(canvas.v)
|
||||
? <span> x {THREE_CANVAS_HEIGHT} Voxels</span>
|
||||
: <span> Pixels</span>}
|
||||
|
|
|
@ -15,19 +15,6 @@ import CanvasItem from './CanvasItem';
|
|||
import type { State } from '../reducers';
|
||||
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
|
||||
const CanvasSelectModal = ({ canvases }) => (
|
||||
<Modal title="Canvas Selection">
|
||||
<p style={{
|
||||
|
@ -37,7 +24,7 @@ const CanvasSelectModal = ({ canvases }) => (
|
|||
paddingTop: 20,
|
||||
}}
|
||||
>
|
||||
<p style={textStyle}>
|
||||
<p className="modaltext">
|
||||
Select the canvas you want to use.
|
||||
Every canvas is unique and has different palettes,
|
||||
cooldown and requirements.
|
||||
|
|
|
@ -9,24 +9,19 @@ import { FaGlobe } from 'react-icons/fa';
|
|||
|
||||
import { showCanvasSelectionModal } from '../actions';
|
||||
|
||||
import type { State } from '../reducers';
|
||||
|
||||
|
||||
const CanvasSwitchButton = ({ open }) => (
|
||||
<div
|
||||
id="canvasbutton"
|
||||
className="actionbuttons"
|
||||
onClick={open}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<FaGlobe />
|
||||
</div>
|
||||
);
|
||||
|
||||
function mapStateToProps(state: State) {
|
||||
const { canvasId } = state.canvas;
|
||||
return { canvasId };
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
open() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import {
|
||||
validateName, validateEMail, validatePassword, parseAPIresponse,
|
||||
validateEMail, validatePassword, parseAPIresponse,
|
||||
} from '../utils/validation';
|
||||
|
||||
function validate(email, password) {
|
||||
|
@ -19,7 +19,7 @@ function validate(email, password) {
|
|||
return errors;
|
||||
}
|
||||
|
||||
async function submit_mailchange(email, password) {
|
||||
async function submitMailchange(email, password) {
|
||||
const body = JSON.stringify({
|
||||
email,
|
||||
password,
|
||||
|
@ -63,7 +63,7 @@ class ChangeMail extends React.Component {
|
|||
if (errors.length > 0) return;
|
||||
this.setState({ submitting: true });
|
||||
|
||||
const { errors: resperrors } = await submit_mailchange(email, password);
|
||||
const { errors: resperrors } = await submitMailchange(email, password);
|
||||
if (resperrors) {
|
||||
this.setState({
|
||||
errors: resperrors,
|
||||
|
@ -77,15 +77,24 @@ class ChangeMail extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (this.state.success) {
|
||||
const { success } = this.state;
|
||||
const { done } = this.props;
|
||||
if (success) {
|
||||
return (
|
||||
<div className="inarea">
|
||||
<p className="modalmessage">Changed Mail successfully. We sent you a verification mail, please verify your new mail adress.</p>
|
||||
<button type="button" onClick={this.props.done}>Close</button>
|
||||
<p
|
||||
className="modalmessage"
|
||||
>
|
||||
Changed Mail successfully.
|
||||
We sent you a verification mail, please verify your new mail adress.
|
||||
</p>
|
||||
<button type="button" onClick={done}>Close</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const { errors } = this.state;
|
||||
const {
|
||||
errors, password, email, submitting,
|
||||
} = this.state;
|
||||
return (
|
||||
<div className="inarea">
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
|
@ -93,21 +102,23 @@ class ChangeMail extends React.Component {
|
|||
<p key={error} className="errormessage">Error: {error}</p>
|
||||
))}
|
||||
<input
|
||||
value={this.state.password}
|
||||
value={password}
|
||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/>
|
||||
<br />
|
||||
<input
|
||||
value={this.state.email}
|
||||
value={email}
|
||||
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||
type="text"
|
||||
placeholder="New Mail"
|
||||
/>
|
||||
<br />
|
||||
<button type="submit">{(this.state.submitting) ? '...' : 'Save'}</button>
|
||||
<button type="button" onClick={this.props.done}>Cancel</button>
|
||||
<button type="submit">
|
||||
{(submitting) ? '...' : 'Save'}
|
||||
</button>
|
||||
<button type="button" onClick={done}>Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -16,7 +16,7 @@ function validate(name) {
|
|||
return errors;
|
||||
}
|
||||
|
||||
async function submit_namechange(name) {
|
||||
async function submitNamechange(name) {
|
||||
const body = JSON.stringify({
|
||||
name,
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ class ChangeName extends React.Component {
|
|||
if (errors.length > 0) return;
|
||||
this.setState({ submitting: true });
|
||||
|
||||
const { errors: resperrors } = await submit_namechange(name);
|
||||
const { errors: resperrors } = await submitNamechange(name);
|
||||
if (resperrors) {
|
||||
this.setState({
|
||||
errors: resperrors,
|
||||
|
@ -65,12 +65,14 @@ class ChangeName extends React.Component {
|
|||
});
|
||||
return;
|
||||
}
|
||||
this.props.set_name(name);
|
||||
this.props.done();
|
||||
const { setName, done } = this.props;
|
||||
setName(name);
|
||||
done();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { errors } = this.state;
|
||||
const { errors, name, submitting } = this.state;
|
||||
const { done } = this.props;
|
||||
return (
|
||||
<div className="inarea">
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
|
@ -78,14 +80,16 @@ class ChangeName extends React.Component {
|
|||
<p key={error} className="errormessage">Error: {error}</p>
|
||||
))}
|
||||
<input
|
||||
value={this.state.name}
|
||||
value={name}
|
||||
onChange={(evt) => this.setState({ name: evt.target.value })}
|
||||
type="text"
|
||||
placeholder="New Username"
|
||||
/>
|
||||
<br />
|
||||
<button type="submit">{(this.state.submitting) ? '...' : 'Save'}</button>
|
||||
<button type="button" onClick={this.props.done}>Cancel</button>
|
||||
<button type="submit">
|
||||
{(submitting) ? '...' : 'Save'}
|
||||
</button>
|
||||
<button type="button" onClick={done}>Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -6,27 +6,27 @@
|
|||
import React from 'react';
|
||||
import { validatePassword, parseAPIresponse } from '../utils/validation';
|
||||
|
||||
function validate(mailreg, password, new_password, confirm_password) {
|
||||
function validate(mailreg, password, newPassword, confirmPassword) {
|
||||
const errors = [];
|
||||
|
||||
if (mailreg) {
|
||||
const oldpasserror = validatePassword(password);
|
||||
if (oldpasserror) errors.push(oldpasserror);
|
||||
}
|
||||
if (new_password != confirm_password) {
|
||||
if (newPassword !== confirmPassword) {
|
||||
errors.push('Passwords do not match.');
|
||||
return errors;
|
||||
}
|
||||
const passerror = validatePassword(new_password);
|
||||
const passerror = validatePassword(newPassword);
|
||||
if (passerror) errors.push(passerror);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
async function submit_passwordchange(new_password, password) {
|
||||
async function submitPasswordChange(newPassword, password) {
|
||||
const body = JSON.stringify({
|
||||
password,
|
||||
new_password,
|
||||
newPassword,
|
||||
});
|
||||
const response = await fetch('./api/auth/change_passwd', {
|
||||
method: 'POST',
|
||||
|
@ -46,8 +46,8 @@ class ChangePassword extends React.Component {
|
|||
super();
|
||||
this.state = {
|
||||
password: '',
|
||||
new_password: '',
|
||||
confirm_password: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
success: false,
|
||||
submitting: false,
|
||||
|
||||
|
@ -61,17 +61,26 @@ class ChangePassword extends React.Component {
|
|||
e.preventDefault();
|
||||
|
||||
const {
|
||||
password, new_password, confirm_password, submitting,
|
||||
password, newPassword, confirmPassword, submitting,
|
||||
} = this.state;
|
||||
if (submitting) return;
|
||||
|
||||
const errors = validate(this.props.mailreg, password, new_password, confirm_password);
|
||||
const { mailreg } = this.props;
|
||||
const errors = validate(
|
||||
mailreg,
|
||||
password,
|
||||
newPassword,
|
||||
confirmPassword,
|
||||
);
|
||||
|
||||
this.setState({ errors });
|
||||
if (errors.length > 0) return;
|
||||
this.setState({ submitting: true });
|
||||
|
||||
const { errors: resperrors } = await submit_passwordchange(new_password, password);
|
||||
const { errors: resperrors } = await submitPasswordChange(
|
||||
newPassword,
|
||||
password,
|
||||
);
|
||||
if (resperrors) {
|
||||
this.setState({
|
||||
errors: resperrors,
|
||||
|
@ -85,25 +94,34 @@ class ChangePassword extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
if (this.state.success) {
|
||||
const { success } = this.state;
|
||||
if (success) {
|
||||
const { done } = this.props;
|
||||
return (
|
||||
<div className="inarea">
|
||||
<p className="modalmessage">Changed Password successfully.</p>
|
||||
<button type="button" onClick={this.props.done}>Close</button>
|
||||
<button type="button" onClick={done}>Close</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const { errors } = this.state;
|
||||
const {
|
||||
errors,
|
||||
password,
|
||||
newPassword,
|
||||
confirmPassword,
|
||||
submitting,
|
||||
} = this.state;
|
||||
const { cancel, mailreg } = this.props;
|
||||
return (
|
||||
<div className="inarea">
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
{errors.map((error) => (
|
||||
<p key={error} className="errormessage">Error: {error}</p>
|
||||
))}
|
||||
{(this.props.mailreg)
|
||||
{(mailreg)
|
||||
&& (
|
||||
<input
|
||||
value={this.state.password}
|
||||
value={password}
|
||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||
type="password"
|
||||
placeholder="Old Password"
|
||||
|
@ -111,21 +129,25 @@ class ChangePassword extends React.Component {
|
|||
)}
|
||||
<br />
|
||||
<input
|
||||
value={this.state.new_password}
|
||||
onChange={(evt) => this.setState({ new_password: evt.target.value })}
|
||||
value={newPassword}
|
||||
onChange={(evt) => this.setState({ newPassword: evt.target.value })}
|
||||
type="password"
|
||||
placeholder="New Password"
|
||||
/>
|
||||
<br />
|
||||
<input
|
||||
value={this.state.confirm_password}
|
||||
onChange={(evt) => this.setState({ confirm_password: evt.target.value })}
|
||||
value={confirmPassword}
|
||||
onChange={(evt) => this.setState({
|
||||
confirmPassword: evt.target.value,
|
||||
})}
|
||||
type="password"
|
||||
placeholder="Confirm New Password"
|
||||
/>
|
||||
<br />
|
||||
<button type="submit">{(this.state.submitting) ? '...' : 'Save'}</button>
|
||||
<button type="button" onClick={this.props.cancel}>Cancel</button>
|
||||
<button type="submit">
|
||||
{(submitting) ? '...' : 'Save'}
|
||||
</button>
|
||||
<button type="button" onClick={cancel}>Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,23 +9,10 @@ import Modal from './Modal';
|
|||
import Chat from './Chat';
|
||||
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
|
||||
const ChatModal = () => (
|
||||
<Modal title="Chat">
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<p style={textStyle}>Chat with other people here</p>
|
||||
<p className="modaltext">Chat with other people here</p>
|
||||
</p>
|
||||
<div className="inarea" style={{ height: '65%' }}>
|
||||
<Chat />
|
||||
|
|
|
@ -12,28 +12,6 @@ import type { State } from '../reducers';
|
|||
import printGIMPPalette from '../core/exportGPL';
|
||||
import { copyCanvasToClipboard } from '../utils/clipboard';
|
||||
|
||||
const titleStyle = {
|
||||
color: '#4f545c',
|
||||
marginLeft: 0,
|
||||
marginRight: 10,
|
||||
overflow: 'hidden',
|
||||
wordWrap: 'break-word',
|
||||
lineHeight: '24px',
|
||||
fontSize: 16,
|
||||
fontWeight: 500,
|
||||
marginTop: 4,
|
||||
marginBottom: 0,
|
||||
};
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
function downloadOutput() {
|
||||
const output = document.getElementById('imgoutput');
|
||||
|
@ -284,7 +262,7 @@ function Converter({
|
|||
|
||||
return (
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<p style={textStyle}>Choose Canvas:
|
||||
<p className="modalcotext">Choose Canvas:
|
||||
<select
|
||||
onChange={(e) => {
|
||||
const sel = e.target;
|
||||
|
@ -307,8 +285,8 @@ function Converter({
|
|||
}
|
||||
</select>
|
||||
</p>
|
||||
<h3 style={titleStyle}>Palette Download</h3>
|
||||
<p style={textStyle}>
|
||||
<h3 className="modaltitle">Palette Download</h3>
|
||||
<p className="modalcotext">
|
||||
Palette for <a href="https://www.gimp.org">GIMP</a>:
|
||||
<button
|
||||
type="button"
|
||||
|
@ -329,8 +307,8 @@ function Converter({
|
|||
<p>Credit for the Palette of the Moon goes to
|
||||
<a href="https://twitter.com/starhousedev">starhouse</a>.</p>
|
||||
</p>
|
||||
<h3 style={titleStyle}>Image Converter</h3>
|
||||
<p style={textStyle}>Convert an image to canvas colors</p>
|
||||
<h3 className="modaltitle">Image Converter</h3>
|
||||
<p className="modalcotext">Convert an image to canvas colors</p>
|
||||
<input
|
||||
type="file"
|
||||
id="imgfile"
|
||||
|
@ -341,7 +319,7 @@ function Converter({
|
|||
readFile(file, selectFile, setScaleData);
|
||||
}}
|
||||
/>
|
||||
<p style={textStyle}>Choose Strategy:
|
||||
<p className="modalcotext">Choose Strategy:
|
||||
<select
|
||||
onChange={(e) => {
|
||||
const sel = e.target;
|
||||
|
@ -368,7 +346,7 @@ function Converter({
|
|||
}
|
||||
</select>
|
||||
</p>
|
||||
<p style={textStyle}>Choose Color Mode:
|
||||
<p className="modalcotext">Choose Color Mode:
|
||||
<select
|
||||
onChange={(e) => {
|
||||
const sel = e.target;
|
||||
|
@ -395,7 +373,7 @@ function Converter({
|
|||
}
|
||||
</select>
|
||||
</p>
|
||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
||||
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={gridEnabled}
|
||||
|
@ -418,7 +396,7 @@ function Converter({
|
|||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
||||
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={gridLight}
|
||||
|
@ -431,7 +409,7 @@ function Converter({
|
|||
/>
|
||||
Light Grid
|
||||
</p>
|
||||
<span style={textStyle}>Offset X:
|
||||
<span className="modalcotext">Offset X:
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
|
@ -445,9 +423,9 @@ function Converter({
|
|||
offsetX: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>%
|
||||
/>
|
||||
</span>
|
||||
<span style={textStyle}>Offset Y:
|
||||
<span className="modalcotext">Offset Y:
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
|
@ -461,12 +439,12 @@ function Converter({
|
|||
offsetY: e.target.value,
|
||||
});
|
||||
}}
|
||||
/>%
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
: null}
|
||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
||||
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={scalingEnabled}
|
||||
|
@ -489,7 +467,7 @@ function Converter({
|
|||
display: 'inline-block',
|
||||
}}
|
||||
>
|
||||
<span style={textStyle}>Width:
|
||||
<span className="modalcotext">Width:
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
|
@ -504,6 +482,7 @@ function Converter({
|
|||
if (selectedScaleKeepRatio && selectedFile) {
|
||||
const ratio = selectedFile.width / selectedFile.height;
|
||||
const newHeight = Math.round(newWidth / ratio);
|
||||
if (newHeight <= 0) return;
|
||||
setScaleData({
|
||||
...scaleData,
|
||||
width: newWidth,
|
||||
|
@ -516,9 +495,9 @@ function Converter({
|
|||
width: newWidth,
|
||||
});
|
||||
}}
|
||||
/>%
|
||||
/>
|
||||
</span>
|
||||
<span style={textStyle}>Height:
|
||||
<span className="modalcotext">Height:
|
||||
<input
|
||||
type="number"
|
||||
step="1"
|
||||
|
@ -533,6 +512,7 @@ function Converter({
|
|||
if (selectedScaleKeepRatio && selectedFile) {
|
||||
const ratio = selectedFile.width / selectedFile.height;
|
||||
const nuWidth = Math.round(ratio * nuHeight);
|
||||
if (nuWidth <= 0) return;
|
||||
setScaleData({
|
||||
...scaleData,
|
||||
width: nuWidth,
|
||||
|
@ -545,9 +525,9 @@ function Converter({
|
|||
height: nuHeight,
|
||||
});
|
||||
}}
|
||||
/>%
|
||||
/>
|
||||
</span>
|
||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
||||
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={selectedScaleKeepRatio}
|
||||
|
@ -557,7 +537,7 @@ function Converter({
|
|||
/>
|
||||
Keep Ratio
|
||||
</p>
|
||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
||||
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={scalingAA}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
d="m 169.92806,224.8757 c 12.96191,0 174.83965,2.84395 174.83965,2.84395 1.031,45.06702 -0.18501,97.37311 -0.18501,144.3008 H 169.92691 c 8.5e-4,-48.64059 8.5e-4,-96.25484 8.5e-4,-147.14475 z m 443.64407,451.61505 c 0,0 -81.1844,-0.18967 -85.99494,-0.0279 -0.0349,0.0116 -0.0698,0.0302 -0.10705,0.0279 -0.19899,-0.0105 -0.14779,-0.021 0.10705,-0.0279 3.75627,-1.25326 -0.69004,-78.95949 -0.69004,-78.95949 -30.07804,0 -157.04976,0.33745 -181.70519,-0.35492 v 77.17678 c 0,0 -60.2026,0.13615 -86.31027,0.13615 V 450.98926 h 88.10464 V 377.78518 H 523.3194 v 69.88884 h 90.25273 z m 90.54596,-304.1119 H 527.47014 V 224.80121 h 176.64795 z"
|
||||
id="path4"
|
||||
inkscape:connector-curvature="0"
|
||||
style="clip-rule:evenodd;fill:#1a1a1a;fill-rule:evenodd;stroke-width:1.16365039"
|
||||
style="clip-rule:evenodd;fill:currentColor;fill-rule:evenodd;stroke-width:1.16365039"
|
||||
sodipodi:nodetypes="ccccccccccccccccccccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -15,7 +15,7 @@ function validate(password) {
|
|||
return errors;
|
||||
}
|
||||
|
||||
async function submit_delete_account(password) {
|
||||
async function submitDeleteAccount(password) {
|
||||
const body = JSON.stringify({
|
||||
password,
|
||||
});
|
||||
|
@ -56,7 +56,7 @@ class DeleteAccount extends React.Component {
|
|||
if (errors.length > 0) return;
|
||||
this.setState({ submitting: true });
|
||||
|
||||
const { errors: resperrors } = await submit_delete_account(password);
|
||||
const { errors: resperrors } = await submitDeleteAccount(password);
|
||||
if (resperrors) {
|
||||
this.setState({
|
||||
errors: resperrors,
|
||||
|
@ -64,11 +64,13 @@ class DeleteAccount extends React.Component {
|
|||
});
|
||||
return;
|
||||
}
|
||||
this.props.set_name(null);
|
||||
const { setName } = this.props;
|
||||
setName(null);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { errors } = this.state;
|
||||
const { errors, password, submitting } = this.state;
|
||||
const { done } = this.props;
|
||||
return (
|
||||
<div className="inarea" style={{ backgroundColor: '#ff6666' }}>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
|
@ -76,14 +78,16 @@ class DeleteAccount extends React.Component {
|
|||
<p key={error} className="errormessage">Error: {error}</p>
|
||||
))}
|
||||
<input
|
||||
value={this.state.password}
|
||||
value={password}
|
||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/>
|
||||
<br />
|
||||
<button type="submit">{(this.state.submitting) ? '...' : 'Yes, Delete My Account!'}</button>
|
||||
<button type="button" onClick={this.props.done}>Cancel</button>
|
||||
<button type="submit">
|
||||
{(submitting) ? '...' : 'Yes, Delete My Account!'}
|
||||
</button>
|
||||
<button type="button" onClick={done}>Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* espand menu / show other menu buttons
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
@ -9,7 +11,13 @@ import { MdExpandMore, MdExpandLess } from 'react-icons/md';
|
|||
import { toggleOpenMenu } from '../actions';
|
||||
|
||||
const ExpandMenuButton = ({ menuOpen, expand }) => (
|
||||
<div id="menubutton" className="actionbuttons" onClick={expand}>
|
||||
<div
|
||||
id="menubutton"
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
onClick={expand}
|
||||
>
|
||||
{(menuOpen) ? <MdExpandLess /> : <MdExpandMore /> }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -11,22 +11,10 @@ import Modal from './Modal';
|
|||
import { showUserAreaModal } from '../actions';
|
||||
import NewPasswordForm from './NewPasswordForm';
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
paddingLeft: '5%',
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
const ForgotPasswordModal = ({ login }) => (
|
||||
<Modal title="Restore my Password">
|
||||
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
||||
<p style={textStyle}>
|
||||
<p className="modaltext">
|
||||
Enter your mail adress and we will send you a new password:
|
||||
</p><br />
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
|
|
|
@ -8,29 +8,40 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom/server';
|
||||
|
||||
import Html from './Html';
|
||||
/* this will be set by webpack */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import assets from './assets.json';
|
||||
import { ASSET_SERVER } from '../core/config';
|
||||
|
||||
import globeCss from './globe.tcss';
|
||||
import globeCss from '../styles/globe.css';
|
||||
|
||||
const Globe = () => (
|
||||
<div>
|
||||
<style dangerouslySetInnerHTML={{ __html: globeCss }} />
|
||||
<div id="webgl" />
|
||||
<div id="coorbox">(0, 0)</div>
|
||||
<div id="info">Double click on globe to go back.</div>
|
||||
<div id="loading">Loading...</div>
|
||||
</div>
|
||||
);
|
||||
const styles = [{
|
||||
id: 'globe',
|
||||
cssText: globeCss,
|
||||
}];
|
||||
|
||||
const data = {
|
||||
title: 'PixelPlanet.fun 3DGlobe',
|
||||
description: '3D globe of our canvas',
|
||||
scripts: [
|
||||
ASSET_SERVER + assets.globe.js,
|
||||
],
|
||||
body: <Globe />,
|
||||
};
|
||||
const globeHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
||||
const title = 'PixelPlanet.fun 3DGlobe';
|
||||
const description = '3D globe of our canvas';
|
||||
const scripts = [
|
||||
ASSET_SERVER + assets.globe.js,
|
||||
];
|
||||
const body = <Globe />;
|
||||
const globeHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(
|
||||
<Html
|
||||
title={title}
|
||||
description={description}
|
||||
scripts={scripts}
|
||||
body={body}
|
||||
styles={styles}
|
||||
/>,
|
||||
)}`;
|
||||
|
||||
export default globeHtml;
|
||||
|
|
|
@ -15,6 +15,7 @@ import type { State } from '../reducers';
|
|||
*/
|
||||
function globe(canvasId, canvasIdent, canvasSize, view) {
|
||||
const [x, y] = view.map(Math.round);
|
||||
// eslint-disable-next-line max-len
|
||||
window.location.href = `globe#${canvasIdent},${canvasId},${canvasSize},${x},${y}`;
|
||||
}
|
||||
|
||||
|
@ -22,12 +23,17 @@ function globe(canvasId, canvasIdent, canvasSize, view) {
|
|||
const GlobeButton = ({
|
||||
canvasId, canvasIdent, canvasSize, view,
|
||||
}) => (
|
||||
<div id="globebutton" className="actionbuttons" onClick={() => globe(canvasId, canvasIdent, canvasSize, view)}>
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
id="globebutton"
|
||||
className="actionbuttons"
|
||||
onClick={() => globe(canvasId, canvasIdent, canvasSize, view)}
|
||||
>
|
||||
<Md3DRotation />
|
||||
</div>
|
||||
);
|
||||
|
||||
// TODO optimize
|
||||
function mapStateToProps(state: State) {
|
||||
const {
|
||||
canvasId, canvasIdent, canvasSize, view,
|
||||
|
|
|
@ -11,16 +11,16 @@ import { toggleGrid } from '../actions';
|
|||
|
||||
|
||||
const GridButton = ({ onToggleGrid }) => (
|
||||
<div className="actionbuttons" onClick={onToggleGrid}>
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="actionbuttons"
|
||||
onClick={onToggleGrid}
|
||||
>
|
||||
<FaTh />
|
||||
</div>
|
||||
);
|
||||
|
||||
// TODO simplify...
|
||||
function mapStateToProps(state: State) {
|
||||
return {};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
open() {
|
||||
|
@ -29,4 +29,4 @@ function mapDispatchToProps(dispatch) {
|
|||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(GridButton);
|
||||
export default connect(null, mapDispatchToProps)(GridButton);
|
||||
|
|
|
@ -11,7 +11,13 @@ import { showHelpModal } from '../actions';
|
|||
|
||||
|
||||
const HelpButton = ({ open }) => (
|
||||
<div id="helpbutton" className="actionbuttons" onClick={open}>
|
||||
<div
|
||||
id="helpbutton"
|
||||
className="actionbuttons"
|
||||
onClick={open}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<FaQuestion />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -13,75 +13,49 @@ import React from 'react';
|
|||
import Modal from './Modal';
|
||||
|
||||
|
||||
const titleStyle = {
|
||||
color: '#4f545c',
|
||||
marginLeft: 0,
|
||||
marginRight: 10,
|
||||
overflow: 'hidden',
|
||||
wordWrap: 'break-word',
|
||||
lineHeight: '24px',
|
||||
fontSize: 16,
|
||||
fontWeight: 500,
|
||||
// marginTop: 0,
|
||||
marginBottom: 0,
|
||||
};
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
|
||||
const HelpModal = () => (
|
||||
<Modal title="Welcome to PixelPlanet.fun">
|
||||
<p style={{ textAlign: 'center', paddingLeft: '5%', paddingRight: '5%' }}>
|
||||
<p style={textStyle}>Place color pixels on a large canvas with other players online!
|
||||
<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">pixelplanet.fun/discord</a></p>
|
||||
<p>Source on <a href="https://github.com/pixelplanetdev/pixelplanet" target="_blank">github</a></p>
|
||||
<p>Reddit: <a href="https://www.reddit.com/r/PixelPlanetFun/" target="_blank">r/PixelPlanetFun</a></p>
|
||||
<p style={titleStyle}>Map Data</p>
|
||||
<p style={textStyle}>The bare map data that we use, together with converted OpenStreetMap tiles for orientation,
|
||||
<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 style={titleStyle}>Detected as Proxy?</p>
|
||||
<p style={textStyle}>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 style={titleStyle}>2D Controls</h3>
|
||||
<p style={textStyle}>Click a color in palette to select</p>
|
||||
<p style={textStyle}>Press <kbd>G</kbd> to toggle grid</p>
|
||||
<p style={textStyle}>Press <kbd>X</kbd> to toggle showing of pixel activity</p>
|
||||
<p style={textStyle}>Press <kbd>R</kbd> to copy coordinates</p>
|
||||
<p style={textStyle}>Press <kbd>Q</kbd> or <kbd>E</kbd> to zoom</p>
|
||||
<p style={textStyle}>Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
|
||||
<p style={textStyle}>Press <kbd>↑</kbd>,<kbd>←</kbd>,<kbd>↓</kbd>, <kbd>→</kbd> to move</p>
|
||||
<p style={textStyle}>Drag mouse to move</p>
|
||||
<p style={textStyle}>Scroll mouse wheel to zoom</p>
|
||||
<p style={textStyle}>Click middle mouse button to current hovering color</p>
|
||||
<p style={textStyle}>Pinch to zoom (on touch devices)</p>
|
||||
<p style={textStyle}>Pan to move (on touch devices)</p>
|
||||
<p style={textStyle}>Click or tap to place a pixel</p>
|
||||
<h3 style={titleStyle}>3D Controls</h3>
|
||||
<p style={textStyle}>Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
|
||||
<p style={textStyle}>Press <kbd>↑</kbd>,<kbd>←</kbd>,<kbd>↓</kbd>, <kbd>→</kbd> to move</p>
|
||||
<p style={textStyle}>Scroll mouse wheel to zoom</p>
|
||||
<p style={textStyle}>Left click and drag mouse to rotate</p>
|
||||
<p style={textStyle}>Middle click and drag mouse to zoom</p>
|
||||
<p style={textStyle}>Right click and drag mouse to pan</p>
|
||||
<p style={textStyle}>Left Click or tap to place a pixel</p>
|
||||
<p style={textStyle}>Right Click of double tap to remove a pixel</p>
|
||||
<p>Partners: <a href="https://www.crazygames.com/c/io" target="_blank">crazygames.com</a></p>
|
||||
<p style={textStyle}>
|
||||
<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.
|
||||
|
|
|
@ -8,82 +8,81 @@
|
|||
* LICENSE.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
|
||||
import React from 'react';
|
||||
import { analytics, RECAPTCHA_SITEKEY } from '../core/config';
|
||||
|
||||
class Html extends React.Component {
|
||||
static defaultProps = {
|
||||
styles: [],
|
||||
scripts: [],
|
||||
};
|
||||
const Html = ({
|
||||
title,
|
||||
description,
|
||||
body,
|
||||
// array of css stylesheet urls
|
||||
css,
|
||||
// array of script urls
|
||||
scripts,
|
||||
// style as string
|
||||
styles,
|
||||
// code as string
|
||||
code,
|
||||
// if recaptcha should get loaded
|
||||
useRecaptcha,
|
||||
}) => (
|
||||
<html className="no-js" lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
{styles && styles.map((style) => (
|
||||
<style
|
||||
key={style.id}
|
||||
id={style.id}
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: style.cssText }}
|
||||
/>
|
||||
))}
|
||||
{RECAPTCHA_SITEKEY && useRecaptcha
|
||||
// eslint-disable-next-line react/no-danger
|
||||
&& <script dangerouslySetInnerHTML={{ __html: `window.sitekey="${RECAPTCHA_SITEKEY}"` }} />}
|
||||
{RECAPTCHA_SITEKEY && useRecaptcha && <script src="https://www.google.com/recaptcha/api.js" async defer />}
|
||||
{code && (
|
||||
<script
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: code }}
|
||||
/>
|
||||
)}
|
||||
{css && css.map((stylesheet) => (
|
||||
<link rel="stylesheet" type="text/css" id={stylesheet.id} href={stylesheet.uri} />
|
||||
))}
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
{body}
|
||||
</div>
|
||||
{scripts && scripts.map((script) => <script key={script} src={script} />)}
|
||||
{analytics.google.trackingId
|
||||
&& (
|
||||
<script
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
'window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;'
|
||||
+ `ga('create','${analytics.google.trackingId}','auto');ga('send','pageview')`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{analytics.google.trackingId
|
||||
&& <script src="https://www.google-analytics.com/analytics.js" async defer />}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
props: {
|
||||
title: string,
|
||||
description: string,
|
||||
styles: Array<{
|
||||
id: string,
|
||||
cssText: string,
|
||||
}>,
|
||||
scripts: Array<string>,
|
||||
body: string,
|
||||
code: string,
|
||||
useRecaptcha: boolean,
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
title, description, styles, scripts, body, code, useRecaptcha,
|
||||
} = this.props;
|
||||
return (
|
||||
<html className="no-js" lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="apple-touch-icon.png" />
|
||||
{styles.map((style) => (
|
||||
<style
|
||||
key={style.id}
|
||||
id={style.id}
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: style.cssText }}
|
||||
/>
|
||||
))}
|
||||
{RECAPTCHA_SITEKEY && useRecaptcha && <script dangerouslySetInnerHTML={{ __html: `window.sitekey="${RECAPTCHA_SITEKEY}"` }} />}
|
||||
{RECAPTCHA_SITEKEY && useRecaptcha && <script src="https://www.google.com/recaptcha/api.js" async defer />}
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
{body}
|
||||
</div>
|
||||
<script
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: code }}
|
||||
/>
|
||||
{scripts.map((script) => <script key={script} src={script} />)}
|
||||
{analytics.google.trackingId
|
||||
&& (
|
||||
<script
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
'window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;'
|
||||
+ `ga('create','${analytics.google.trackingId}','auto');ga('send','pageview')`,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{analytics.google.trackingId
|
||||
&& <script src="https://www.google-analytics.com/analytics.js" async defer />}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Html;
|
||||
|
|
|
@ -11,7 +11,13 @@ import { showUserAreaModal } from '../actions';
|
|||
|
||||
|
||||
const LogInButton = ({ open }) => (
|
||||
<div id="loginbutton" className="actionbuttons" onClick={open}>
|
||||
<div
|
||||
id="loginbutton"
|
||||
className="actionbuttons"
|
||||
onClick={open}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<MdPerson />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,22 +9,29 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom/server';
|
||||
|
||||
import Html from './Html';
|
||||
/* this one is set by webpack */
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import assets from './assets.json';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import styleassets from './styleassets.json';
|
||||
|
||||
import { ASSET_SERVER, BACKUP_URL } from '../core/config';
|
||||
|
||||
const data = {
|
||||
title: 'PixelPlanet.fun',
|
||||
description: 'Place color pixels on an map styled canvas '
|
||||
+ 'with other players online',
|
||||
// styles: [
|
||||
// { id: 'css', cssText: baseCss },
|
||||
// ],
|
||||
scripts: [
|
||||
ASSET_SERVER + assets.vendor.js,
|
||||
ASSET_SERVER + assets.client.js,
|
||||
],
|
||||
useRecaptcha: true,
|
||||
};
|
||||
// eslint-disable-next-line max-len
|
||||
let code = `window.assetserver="${ASSET_SERVER}";window.availableStyles=JSON.parse('${JSON.stringify(styleassets)}');`;
|
||||
if (BACKUP_URL) {
|
||||
code += `window.backupurl="${BACKUP_URL}";`;
|
||||
}
|
||||
const scripts = [
|
||||
ASSET_SERVER + assets.vendor.js,
|
||||
ASSET_SERVER + assets.client.js,
|
||||
];
|
||||
const css = [
|
||||
{
|
||||
id: 'globcss',
|
||||
uri: styleassets.default,
|
||||
},
|
||||
];
|
||||
|
||||
/*
|
||||
* generates string with html of main page
|
||||
|
@ -35,12 +42,18 @@ const data = {
|
|||
*/
|
||||
function generateMainPage(countryCoords: Cell): string {
|
||||
const [x, y] = countryCoords;
|
||||
let code = `window.coordx=${x};window.coordy=${y};window.assetserver="${ASSET_SERVER}";`;
|
||||
if (BACKUP_URL) {
|
||||
code += `window.backupurl="${BACKUP_URL}";`;
|
||||
}
|
||||
const htmldata = { ...data, code };
|
||||
const html = ReactDOM.renderToStaticMarkup(<Html {...htmldata} />);
|
||||
// eslint-disable-next-line
|
||||
const html = ReactDOM.renderToStaticMarkup(
|
||||
<Html
|
||||
title="PixelPlanet.fun"
|
||||
// eslint-disable-next-line max-len
|
||||
description="Place color pixels on an map styled canvas with other players online"
|
||||
scripts={scripts}
|
||||
css={css}
|
||||
code={`${code}window.coordx=${x};window.coordy=${y};`}
|
||||
useRecaptcha
|
||||
/>,
|
||||
);
|
||||
|
||||
return `<!doctype html>${html}`;
|
||||
}
|
||||
|
|
|
@ -6,14 +6,13 @@ import ToggleButton from 'react-toggle-button';
|
|||
import { MdCheck, MdClose } from 'react-icons/md';
|
||||
|
||||
|
||||
const MdToggleButton = ({ value, onToggle, ...props }) => (
|
||||
const MdToggleButton = ({ value, onToggle }) => (
|
||||
<ToggleButton
|
||||
inactiveLabel={<MdClose />}
|
||||
activeLabel={<MdCheck />}
|
||||
thumbAnimateRange={[-10, 36]}
|
||||
value={value}
|
||||
onToggle={onToggle}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -9,11 +9,14 @@ import Creeper from './Creeper.svg';
|
|||
|
||||
import { showMinecraftModal } from '../actions';
|
||||
|
||||
import type { State } from '../reducers';
|
||||
|
||||
|
||||
const MinecraftButton = ({ open }) => (
|
||||
<div id="minecraftbutton" className="actionbuttons" onClick={open}>
|
||||
<div
|
||||
id="minecraftbutton"
|
||||
className="actionbuttons"
|
||||
onClick={open}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<Creeper />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -9,13 +9,13 @@ import { MdNearMe } from 'react-icons/md';
|
|||
|
||||
import type { State } from '../reducers';
|
||||
|
||||
async function submit_minecraft_tp(view) {
|
||||
async function submitMinecraftTp(view) {
|
||||
const [x, y] = view.map(Math.round);
|
||||
const body = JSON.stringify({
|
||||
x,
|
||||
y,
|
||||
});
|
||||
const response = await fetch('./api/mctp', {
|
||||
await fetch('./api/mctp', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
|
@ -27,7 +27,13 @@ async function submit_minecraft_tp(view) {
|
|||
|
||||
|
||||
const MinecraftTPButton = ({ view }) => (
|
||||
<div id="minecrafttpbutton" className="actionbuttons" onClick={() => submit_minecraft_tp(view)}>
|
||||
<div
|
||||
id="minecrafttpbutton"
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
onClick={() => submitMinecraftTp(view)}
|
||||
>
|
||||
<MdNearMe />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -54,179 +54,171 @@ function cancelMovement() {
|
|||
renderer.controls.moveDown = false;
|
||||
}
|
||||
|
||||
class Mobile3DControls extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 46,
|
||||
left: 57,
|
||||
// bottom: 128,
|
||||
bottom: 139,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('FORWARD', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('FORWARD', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('FORWARD', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('FORWARD', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↑
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 46,
|
||||
left: 57,
|
||||
bottom: 98,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('BACKWARD', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('BACKWARD', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('BACKWARD', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('BACKWARD', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↓
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
left: 16,
|
||||
bottom: 98,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('LEFT', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('LEFT', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('LEFT', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('LEFT', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
←
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 76,
|
||||
left: 98,
|
||||
bottom: 98,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('RIGHT', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('RIGHT', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('RIGHT', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('RIGHT', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
→
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 76,
|
||||
left: 16,
|
||||
bottom: 139,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('UP', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('UP', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('UP', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('UP', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↖
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 76,
|
||||
left: 98,
|
||||
bottom: 139,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('DOWN', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('DOWN', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('DOWN', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('DOWN', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↘
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
const Mobile3DControls = () => (
|
||||
<div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 46,
|
||||
left: 57,
|
||||
// bottom: 128,
|
||||
bottom: 139,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('FORWARD', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('FORWARD', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('FORWARD', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('FORWARD', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↑
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 46,
|
||||
left: 57,
|
||||
bottom: 98,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('BACKWARD', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('BACKWARD', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('BACKWARD', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('BACKWARD', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↓
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
left: 16,
|
||||
bottom: 98,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('LEFT', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('LEFT', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('LEFT', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('LEFT', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
←
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 76,
|
||||
left: 98,
|
||||
bottom: 98,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('RIGHT', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('RIGHT', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('RIGHT', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('RIGHT', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
→
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 76,
|
||||
left: 16,
|
||||
bottom: 139,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('UP', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('UP', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('UP', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('UP', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↖
|
||||
</div>
|
||||
<div
|
||||
className="actionbuttons"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
style={{
|
||||
...btnStyle,
|
||||
// left: 76,
|
||||
left: 98,
|
||||
bottom: 139,
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
move('DOWN', true);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
move('DOWN', false);
|
||||
}}
|
||||
onTouchStart={() => {
|
||||
move('DOWN', true);
|
||||
}}
|
||||
onTouchEnd={() => {
|
||||
move('DOWN', false);
|
||||
}}
|
||||
onTouchCancel={cancelMovement}
|
||||
onMouseLeave={cancelMovement}
|
||||
>
|
||||
↘
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default Mobile3DControls;
|
||||
|
|
|
@ -13,26 +13,6 @@ import {
|
|||
} from '../actions';
|
||||
|
||||
|
||||
const closeStyles = {
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flex: '0 0 36px',
|
||||
borderWidth: 2,
|
||||
borderStyle: 'solid',
|
||||
borderRadius: '50%',
|
||||
width: 36,
|
||||
height: 36,
|
||||
cursor: 'pointer',
|
||||
backgroundColor: '#f6f6f7',
|
||||
borderColor: '#dcddde',
|
||||
top: 30,
|
||||
right: 40,
|
||||
};
|
||||
|
||||
|
||||
// TODO appear with animation
|
||||
function MyModal({ close, title, children }) {
|
||||
return (
|
||||
<Modal
|
||||
|
@ -45,8 +25,8 @@ function MyModal({ close, title, children }) {
|
|||
>
|
||||
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
|
||||
<div
|
||||
style={closeStyles}
|
||||
onClick={close}
|
||||
className="ModalClose"
|
||||
role="button"
|
||||
label="close"
|
||||
tabIndex={-1}
|
||||
|
|
|
@ -30,13 +30,13 @@ const MODAL_COMPONENTS = {
|
|||
/* other modals */
|
||||
};
|
||||
|
||||
const ModalRoot = ({ modalType, modalProps }) => {
|
||||
const ModalRoot = ({ modalType }) => {
|
||||
if (!modalType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const SpecificModal = MODAL_COMPONENTS[modalType];
|
||||
return <SpecificModal {...modalProps} />;
|
||||
return <SpecificModal />;
|
||||
};
|
||||
|
||||
export default connect(
|
||||
|
|
|
@ -73,17 +73,19 @@ class NewPasswordForm extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { errors } = this.state;
|
||||
if (this.state.success) {
|
||||
const { success } = this.state;
|
||||
const { back } = this.props;
|
||||
if (success) {
|
||||
return (
|
||||
<div>
|
||||
<p className="modalmessage">
|
||||
Sent you a mail with instructions to reset your password.
|
||||
</p>
|
||||
<button type="button" onClick={this.props.back}>Back</button>
|
||||
<button type="button" onClick={back}>Back</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const { errors, email, submitting } = this.state;
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
{errors.map((error) => (
|
||||
|
@ -91,16 +93,16 @@ class NewPasswordForm extends React.Component {
|
|||
))}
|
||||
<input
|
||||
style={inputStyles}
|
||||
value={this.state.email}
|
||||
value={email}
|
||||
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||
type="text"
|
||||
placeholder="Email"
|
||||
/>
|
||||
<br />
|
||||
<button type="submit">
|
||||
{(this.state.submitting) ? '...' : 'Submit'}
|
||||
{(submitting) ? '...' : 'Submit'}
|
||||
</button>
|
||||
<button type="button" onClick={this.props.back}>Cancel</button>
|
||||
<button type="button" onClick={back}>Cancel</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,49 +8,46 @@ import React from 'react';
|
|||
import TotalRankings from './TotalRankings';
|
||||
import DailyRankings from './DailyRankings';
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
class Rankings extends React.Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
order_daily: false,
|
||||
orderDaily: false,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { orderDaily } = this.state;
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
<span
|
||||
className={(!this.state.order_daily) ? 'modallinkselected' : 'modallink'}
|
||||
onClick={() => { this.setState({ order_daily: false }); }}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className={
|
||||
(!orderDaily) ? 'modallinkselected' : 'modallink'
|
||||
}
|
||||
onClick={() => {
|
||||
this.setState({ orderDaily: false });
|
||||
}}
|
||||
>Total</span> |
|
||||
<span
|
||||
className={(this.state.order_daily) ? 'modallinkselected' : 'modallink'}
|
||||
onClick={() => { this.setState({ order_daily: true }); }}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className={
|
||||
(orderDaily) ? 'modallinkselected' : 'modallink'
|
||||
}
|
||||
onClick={() => { this.setState({ orderDaily: true }); }}
|
||||
>Daily</span>
|
||||
</p>
|
||||
{(this.state.order_daily) ? <DailyRankings /> : <TotalRankings />}
|
||||
<p style={textStyle}>Ranking updates every 5 min. Daily rankings get reset at midnight UTC.</p>
|
||||
{(orderDaily) ? <DailyRankings /> : <TotalRankings />}
|
||||
<p className="modaltext">
|
||||
Ranking updates every 5 min. Daily rankings get reset at midnight UTC.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: State) {
|
||||
const { totalRanking } = state.user;
|
||||
return { totalRanking };
|
||||
}
|
||||
|
||||
export default Rankings;
|
||||
|
|
|
@ -12,8 +12,6 @@ import { requestPlacePixel } from '../actions';
|
|||
|
||||
|
||||
function onCaptcha(token: string) {
|
||||
console.log('token', token);
|
||||
|
||||
const { canvasId, coordinates, color } = window.pixel;
|
||||
|
||||
store.dispatch(requestPlacePixel(canvasId, coordinates, color, token));
|
||||
|
|
|
@ -8,32 +8,21 @@ import { connect } from 'react-redux';
|
|||
|
||||
import Modal from './Modal';
|
||||
|
||||
import { showUserAreaModal, receiveMe } from '../actions';
|
||||
import { showUserAreaModal } from '../actions';
|
||||
|
||||
// import { send_registration } from '../ui/register';
|
||||
import SignUpForm from './SignUpForm';
|
||||
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
paddingLeft: '5%',
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
const RegisterModal = ({ login, doMe }) => (
|
||||
const RegisterModal = ({ login }) => (
|
||||
<Modal title="Register New Account">
|
||||
<p style={textStyle}>Register new account here</p><br />
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<SignUpForm userarea={login} me={doMe} />
|
||||
<button type="button" onClick={login}>Cancel</button>
|
||||
<p>Also join our Discord:
|
||||
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
|
||||
<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:
|
||||
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
|
||||
</p>
|
||||
</p>
|
||||
</p>
|
||||
</Modal>
|
||||
|
@ -44,9 +33,6 @@ function mapDispatchToProps(dispatch) {
|
|||
login() {
|
||||
dispatch(showUserAreaModal());
|
||||
},
|
||||
doMe(me) {
|
||||
dispatch(receiveMe(me));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,15 @@ import { FaCog } from 'react-icons/fa';
|
|||
|
||||
import { showSettingsModal } from '../actions';
|
||||
|
||||
import type { State } from '../reducers';
|
||||
|
||||
|
||||
const SettingsButton = ({ open }) => (
|
||||
<div id="settingsbutton" className="actionbuttons" onClick={open}>
|
||||
<div
|
||||
id="settingsbutton"
|
||||
className="actionbuttons"
|
||||
onClick={open}
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
>
|
||||
<FaCog />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -18,6 +18,7 @@ import {
|
|||
togglePotatoMode,
|
||||
toggleLightGrid,
|
||||
toggleHistoricalView,
|
||||
selectStyle,
|
||||
} from '../actions';
|
||||
|
||||
import type { State } from '../reducers';
|
||||
|
@ -40,16 +41,6 @@ const itemStyles = {
|
|||
|
||||
const titleStyles = {
|
||||
flex: '1 1 auto',
|
||||
marginLeft: 0,
|
||||
marginRight: 10,
|
||||
color: '#4f545c',
|
||||
overflow: 'hidden',
|
||||
wordWrap: 'break-word',
|
||||
lineHeight: '24px',
|
||||
fontSize: 16,
|
||||
fontWeight: 500,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
};
|
||||
|
||||
const rowStyles = {
|
||||
|
@ -57,35 +48,50 @@ const rowStyles = {
|
|||
flexDirection: 'row',
|
||||
};
|
||||
|
||||
const descriptionStyle = {
|
||||
boxSizing: 'border-box',
|
||||
flex: '1 1 auto',
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
lineHeight: '20px',
|
||||
fontWeight: 500,
|
||||
marginTop: 4,
|
||||
};
|
||||
|
||||
const dividerStyles = {
|
||||
boxSizing: 'border-box',
|
||||
marginTop: 20,
|
||||
height: 1,
|
||||
width: '100%',
|
||||
backgroundColor: 'hsla(216, 4%, 74%, .3)',
|
||||
};
|
||||
|
||||
const SettingsItemSelect = ({
|
||||
title, description, values, selected, onSelect,
|
||||
}) => (
|
||||
<div style={itemStyles}>
|
||||
<div style={rowStyles}>
|
||||
<h3 style={titleStyles} className="modaltitle">{title}</h3>
|
||||
<select
|
||||
onChange={(e) => {
|
||||
const sel = e.target;
|
||||
onSelect(sel.options[sel.selectedIndex].value);
|
||||
}}
|
||||
>
|
||||
{
|
||||
values.map((value) => (
|
||||
<option
|
||||
selected={value === selected}
|
||||
value={value}
|
||||
>
|
||||
{value}
|
||||
</option>
|
||||
))
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
{description && <div className="modaldesc">{description} </div>}
|
||||
<div className="modaldivider" />
|
||||
</div>
|
||||
);
|
||||
|
||||
const SettingsItem = ({
|
||||
title, description, keyBind, value, onToggle,
|
||||
}) => (
|
||||
<div style={itemStyles}>
|
||||
<div style={rowStyles}>
|
||||
<h3 style={titleStyles}>{title} {keyBind && <kbd>{keyBind}</kbd>}</h3>
|
||||
<h3
|
||||
style={titleStyles}
|
||||
className="modaltitle"
|
||||
>
|
||||
{title} {keyBind && <kbd>{keyBind}</kbd>}
|
||||
</h3>
|
||||
<MdToggleButtonHover value={value} onToggle={onToggle} />
|
||||
</div>
|
||||
{description && <div style={descriptionStyle}>{description} </div>}
|
||||
<div style={dividerStyles} />
|
||||
{description && <div className="modaldesc">{description} </div>}
|
||||
<div className="modaldivider" />
|
||||
</div>
|
||||
);
|
||||
|
||||
|
@ -99,6 +105,7 @@ function SettingsModal({
|
|||
onMute,
|
||||
autoZoomIn,
|
||||
compactPalette,
|
||||
selectedStyle,
|
||||
onToggleGrid,
|
||||
onTogglePixelNotify,
|
||||
onToggleAutoZoomIn,
|
||||
|
@ -107,6 +114,7 @@ function SettingsModal({
|
|||
onTogglePotatoMode,
|
||||
onToggleLightGrid,
|
||||
onToggleHistoricalView,
|
||||
onSelectStyle,
|
||||
chatNotify,
|
||||
}) {
|
||||
return (
|
||||
|
@ -175,6 +183,15 @@ function SettingsModal({
|
|||
onToggle={onToggleHistoricalView}
|
||||
/>
|
||||
) : null }
|
||||
{(typeof window.availableStyles !== 'undefined') && (
|
||||
<SettingsItemSelect
|
||||
title="Styles"
|
||||
description="How pixelplanet should look like."
|
||||
values={Object.keys(window.availableStyles)}
|
||||
selected={selectedStyle}
|
||||
onSelect={onSelectStyle}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
</Modal>
|
||||
);
|
||||
|
@ -189,6 +206,7 @@ function mapStateToProps(state: State) {
|
|||
compactPalette,
|
||||
isPotato,
|
||||
isLightGrid,
|
||||
style: selectedStyle,
|
||||
} = state.gui;
|
||||
const isMuted = mute;
|
||||
const {
|
||||
|
@ -206,6 +224,7 @@ function mapStateToProps(state: State) {
|
|||
isPotato,
|
||||
isLightGrid,
|
||||
isHistoricalView,
|
||||
selectedStyle,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -238,6 +257,9 @@ function mapDispatchToProps(dispatch) {
|
|||
onToggleHistoricalView() {
|
||||
dispatch(toggleHistoricalView());
|
||||
},
|
||||
onSelectStyle(style) {
|
||||
dispatch(selectStyle(style));
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,14 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
validateEMail, validateName, validatePassword, parseAPIresponse,
|
||||
} from '../utils/validation';
|
||||
|
||||
import { showUserAreaModal, receiveMe } from '../actions';
|
||||
|
||||
|
||||
function validate(name, email, password, confirmPassword) {
|
||||
const errors = [];
|
||||
const mailerror = validateEMail(email);
|
||||
|
@ -90,12 +94,23 @@ class SignUpForm extends React.Component {
|
|||
});
|
||||
return;
|
||||
}
|
||||
this.props.me(me);
|
||||
this.props.userarea();
|
||||
const { doMe, userarea } = this.props;
|
||||
doMe(me);
|
||||
userarea();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { errors } = this.state;
|
||||
const {
|
||||
errors,
|
||||
name,
|
||||
email,
|
||||
password,
|
||||
confirmPassword,
|
||||
submitting,
|
||||
} = this.state;
|
||||
const {
|
||||
back,
|
||||
} = this.props;
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
{errors.map((error) => (
|
||||
|
@ -103,28 +118,28 @@ class SignUpForm extends React.Component {
|
|||
))}
|
||||
<input
|
||||
style={inputStyles}
|
||||
value={this.state.name}
|
||||
value={name}
|
||||
onChange={(evt) => this.setState({ name: evt.target.value })}
|
||||
type="text"
|
||||
placeholder="Name"
|
||||
/><br />
|
||||
<input
|
||||
style={inputStyles}
|
||||
value={this.state.email}
|
||||
value={email}
|
||||
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||
type="text"
|
||||
placeholder="Email"
|
||||
/><br />
|
||||
<input
|
||||
style={inputStyles}
|
||||
value={this.state.password}
|
||||
value={password}
|
||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||
type="password"
|
||||
placeholder="Password"
|
||||
/><br />
|
||||
<input
|
||||
style={inputStyles}
|
||||
value={this.state.confirmPassword}
|
||||
value={confirmPassword}
|
||||
onChange={(evt) => this.setState({
|
||||
confirmPassword: evt.target.value,
|
||||
})}
|
||||
|
@ -132,11 +147,29 @@ class SignUpForm extends React.Component {
|
|||
placeholder="Confirm Password"
|
||||
/><br />
|
||||
<button type="submit">
|
||||
{(this.state.submitting) ? '...' : 'Submit'}
|
||||
{(submitting) ? '...' : 'Submit'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={back}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default SignUpForm;
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
doMe(me) {
|
||||
dispatch(receiveMe(me));
|
||||
},
|
||||
userarea() {
|
||||
dispatch(showUserAreaModal());
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, mapDispatchToProps)(SignUpForm);
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Tab extends Component {
|
||||
static propTypes = {
|
||||
activeTab: PropTypes.string.isRequired,
|
||||
label: PropTypes.string.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
onClick = () => {
|
||||
const { label, onClick } = this.props;
|
||||
onClick(label);
|
||||
|
@ -30,6 +23,7 @@ class Tab extends Component {
|
|||
|
||||
return (
|
||||
<li
|
||||
role="presentation"
|
||||
className={className}
|
||||
onClick={onClick}
|
||||
>
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Tab from './Tab';
|
||||
|
||||
class Tabs extends Component {
|
||||
static propTypes = {
|
||||
children: PropTypes.instanceOf(Array).isRequired,
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { children } = this.props;
|
||||
this.state = {
|
||||
activeTab: this.props.children[0].props.label,
|
||||
activeTab: children[0].props.label,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -16,21 +16,10 @@ import DeleteAccount from './DeleteAccount';
|
|||
|
||||
import { numberToString } from '../core/utils';
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
const Stat = ({ text, value, rank }) => (
|
||||
<p>
|
||||
<span className="stattext">{(rank) ? `${text}: #` : `${text}: `}</span>
|
||||
|
||||
<span className="statvalue">{numberToString(value)}</span>
|
||||
</p>
|
||||
);
|
||||
|
@ -40,95 +29,131 @@ class UserArea extends React.Component {
|
|||
super();
|
||||
this.state = {
|
||||
// that should be an ENUM tbh
|
||||
change_name_extended: false,
|
||||
change_mail_extended: false,
|
||||
change_passwd_extended: false,
|
||||
delete_account_extended: false,
|
||||
changeNameExtended: false,
|
||||
changeMailExtended: false,
|
||||
changePasswdExtended: false,
|
||||
deleteAccountExtended: false,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
stats, name, logout, mailreg, setMailreg, setName,
|
||||
} = this.props;
|
||||
const {
|
||||
changeNameExtended,
|
||||
changeMailExtended,
|
||||
changePasswdExtended,
|
||||
deleteAccountExtended,
|
||||
} = this.state;
|
||||
return (
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<UserMessages />
|
||||
<Stat text="Todays Placed Pixels" value={this.props.stats.dailyTotalPixels} />
|
||||
<Stat text="Daily Rank" value={this.props.stats.dailyRanking} rank />
|
||||
<Stat text="Placed Pixels" value={this.props.stats.totalPixels} />
|
||||
<Stat text="Total Rank" value={this.props.stats.ranking} rank />
|
||||
<p style={textStyle}>
|
||||
<p>Your name is: {this.props.name}</p>(
|
||||
<Stat
|
||||
text="Todays Placed Pixels"
|
||||
value={stats.dailyTotalPixels}
|
||||
/>
|
||||
<Stat
|
||||
text="Daily Rank"
|
||||
value={stats.dailyRanking}
|
||||
rank
|
||||
/>
|
||||
<Stat
|
||||
text="Placed Pixels"
|
||||
value={stats.totalPixels}
|
||||
/>
|
||||
<Stat
|
||||
text="Total Rank"
|
||||
value={stats.ranking}
|
||||
rank
|
||||
/>
|
||||
<p className="modaltext">
|
||||
<p>Your name is: {name}</p>(
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={this.props.logout}
|
||||
onClick={logout}
|
||||
> Log out</span> |
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={(evt) => this.setState({
|
||||
change_name_extended: true,
|
||||
change_mail_extended: false,
|
||||
change_passwd_extended: false,
|
||||
delete_account_extended: false,
|
||||
onClick={() => this.setState({
|
||||
changeNameExtended: true,
|
||||
changeMailExtended: false,
|
||||
changePasswdExtended: false,
|
||||
deleteAccountExtended: false,
|
||||
})}
|
||||
> Change Username</span> |
|
||||
{(this.props.mailreg)
|
||||
{(mailreg)
|
||||
&& (
|
||||
<span>
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={(evt) => this.setState({
|
||||
change_name_extended: false,
|
||||
change_mail_extended: true,
|
||||
change_passwd_extended: false,
|
||||
delete_account_extended: false,
|
||||
onClick={() => this.setState({
|
||||
changeNameExtended: false,
|
||||
changeMailExtended: true,
|
||||
changePasswdExtended: false,
|
||||
deleteAccountExtended: false,
|
||||
})}
|
||||
> Change Mail</span> |
|
||||
</span>
|
||||
)}
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={(evt) => this.setState({
|
||||
change_name_extended: false,
|
||||
change_mail_extended: false,
|
||||
change_passwd_extended: true,
|
||||
delete_account_extended: false,
|
||||
onClick={() => this.setState({
|
||||
changeNameExtended: false,
|
||||
changeMailExtended: false,
|
||||
changePasswdExtended: true,
|
||||
deleteAccountExtended: false,
|
||||
})}
|
||||
> Change Password</span> |
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={(evt) => this.setState({
|
||||
change_name_extended: false,
|
||||
change_mail_extended: false,
|
||||
change_passwd_extended: false,
|
||||
delete_account_extended: true,
|
||||
onClick={() => this.setState({
|
||||
changeNameExtended: false,
|
||||
changeMailExtended: false,
|
||||
changePasswdExtended: false,
|
||||
deleteAccountExtended: true,
|
||||
})}
|
||||
> Delete Account</span> )
|
||||
</p>
|
||||
{(this.state.change_passwd_extended)
|
||||
{(changePasswdExtended)
|
||||
&& (
|
||||
<ChangePassword
|
||||
mailreg={this.props.mailreg}
|
||||
done={() => { this.props.set_mailreg(true); this.setState({ change_passwd_extended: false }); }}
|
||||
cancel={() => { this.setState({ change_passwd_extended: false }); }}
|
||||
mailreg={mailreg}
|
||||
done={() => {
|
||||
setMailreg(true);
|
||||
this.setState({ changePasswdExtended: false });
|
||||
}}
|
||||
cancel={() => { this.setState({ changePasswdExtended: false }); }}
|
||||
/>
|
||||
)}
|
||||
{(this.state.change_name_extended)
|
||||
{(changeNameExtended)
|
||||
&& (
|
||||
<ChangeName
|
||||
set_name={this.props.set_name}
|
||||
done={() => { this.setState({ change_name_extended: false }); }}
|
||||
setName={setName}
|
||||
done={() => { this.setState({ changeNameExtended: false }); }}
|
||||
/>
|
||||
)}
|
||||
{(this.state.change_mail_extended)
|
||||
{(changeMailExtended)
|
||||
&& (
|
||||
<ChangeMail
|
||||
done={() => { this.setState({ change_mail_extended: false }); }}
|
||||
done={() => { this.setState({ changeMailExtended: false }); }}
|
||||
/>
|
||||
)}
|
||||
{(this.state.delete_account_extended)
|
||||
{(deleteAccountExtended)
|
||||
&& (
|
||||
<DeleteAccount
|
||||
set_name={this.props.set_name}
|
||||
done={() => { this.setState({ delete_account_extended: false }); }}
|
||||
setName={setName}
|
||||
done={() => { this.setState({ deleteAccountExtended: false }); }}
|
||||
/>
|
||||
)}
|
||||
</p>
|
||||
|
|
|
@ -26,26 +26,15 @@ const logoStyle = {
|
|||
marginRight: 5,
|
||||
};
|
||||
|
||||
const textStyle = {
|
||||
color: 'hsla(218, 5%, 47%, .6)',
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
position: 'relative',
|
||||
textAlign: 'inherit',
|
||||
float: 'none',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
lineHeight: 'normal',
|
||||
};
|
||||
|
||||
const LogInArea = ({ register, forgot_password, me }) => (
|
||||
const LogInArea = ({ register, forgotPassword, me }) => (
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<p style={textStyle}>Login to access more features and stats.</p><br />
|
||||
<p className="modaltext">Login to access more features and stats.</p><br />
|
||||
<h2>Login with Mail:</h2>
|
||||
<LogInForm me={me} />
|
||||
<p
|
||||
className="modallink"
|
||||
onClick={forgot_password}
|
||||
onClick={forgotPassword}
|
||||
role="presentation"
|
||||
>
|
||||
I forgot my Password.</p>
|
||||
<h2>or login with:</h2>
|
||||
|
@ -95,7 +84,7 @@ const LogInArea = ({ register, forgot_password, me }) => (
|
|||
);
|
||||
|
||||
const UserAreaModal = ({
|
||||
name, register, forgot_password, doMe, logout, setUserName, setUserMailreg,
|
||||
name, register, forgotPassword, doMe, logout, setUserName, setUserMailreg,
|
||||
}) => (
|
||||
<Modal title="User Area">
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
|
@ -103,7 +92,7 @@ const UserAreaModal = ({
|
|||
? (
|
||||
<LogInArea
|
||||
register={register}
|
||||
forgot_password={forgot_password}
|
||||
forgotPassword={forgotPassword}
|
||||
me={doMe}
|
||||
/>
|
||||
)
|
||||
|
@ -112,8 +101,8 @@ const UserAreaModal = ({
|
|||
<div label="Profile">
|
||||
<UserArea
|
||||
logout={logout}
|
||||
set_name={setUserName}
|
||||
set_mailreg={setUserMailreg}
|
||||
setName={setUserName}
|
||||
setMailreg={setUserMailreg}
|
||||
/>
|
||||
</div>
|
||||
<div label="Ranking">
|
||||
|
@ -138,7 +127,7 @@ function mapDispatchToProps(dispatch) {
|
|||
register() {
|
||||
dispatch(showRegisterModal());
|
||||
},
|
||||
forgot_password() {
|
||||
forgotPassword() {
|
||||
dispatch(showForgotPasswordModal());
|
||||
},
|
||||
doMe(me) {
|
||||
|
|
|
@ -13,20 +13,21 @@ class UserMessages extends React.Component {
|
|||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
resent_verify: false,
|
||||
sent_link: false,
|
||||
verify_answer: null,
|
||||
link_answer: null,
|
||||
resentVerify: false,
|
||||
sentLink: false,
|
||||
verifyAnswer: null,
|
||||
linkAnswer: null,
|
||||
};
|
||||
|
||||
this.submit_resend_verify = this.submit_resend_verify.bind(this);
|
||||
this.submit_mc_link = this.submit_mc_link.bind(this);
|
||||
this.submitResendVerify = this.submitResendVerify.bind(this);
|
||||
this.submitMcLink = this.submitMcLink.bind(this);
|
||||
}
|
||||
|
||||
async submit_resend_verify() {
|
||||
if (this.state.resent_verify) return;
|
||||
async submitResendVerify() {
|
||||
const { resentVerify } = this.state;
|
||||
if (resentVerify) return;
|
||||
this.setState({
|
||||
resent_verify: true,
|
||||
resentVerify: true,
|
||||
});
|
||||
|
||||
const response = await fetch('./api/auth/resend_verify', {
|
||||
|
@ -34,16 +35,19 @@ class UserMessages extends React.Component {
|
|||
});
|
||||
|
||||
const { errors } = await parseAPIresponse(response);
|
||||
const verify_answer = (errors) ? errors[0] : 'A new verification mail is getting sent to you.';
|
||||
const verifyAnswer = (errors)
|
||||
? errors[0]
|
||||
: 'A new verification mail is getting sent to you.';
|
||||
this.setState({
|
||||
verify_answer,
|
||||
verifyAnswer,
|
||||
});
|
||||
}
|
||||
|
||||
async submit_mc_link(accepted) {
|
||||
if (this.state.sent_link) return;
|
||||
async submitMcLink(accepted) {
|
||||
const { sentLink } = this.state;
|
||||
if (sentLink) return;
|
||||
this.setState({
|
||||
sent_link: true,
|
||||
sentLink: true,
|
||||
});
|
||||
const body = JSON.stringify({ accepted });
|
||||
const rep = await fetch('./api/auth/mclink', {
|
||||
|
@ -56,43 +60,94 @@ class UserMessages extends React.Component {
|
|||
const { errors } = parseAPIresponse(rep);
|
||||
if (errors) {
|
||||
this.setState({
|
||||
link_answer: errors[0],
|
||||
linkAnswer: errors[0],
|
||||
});
|
||||
return;
|
||||
}
|
||||
const { setMCName, remFromUserMessages } = this.props;
|
||||
if (!accepted) {
|
||||
this.props.setMCName(null);
|
||||
setMCName(null);
|
||||
}
|
||||
this.props.rem_from_messages('not_mc_verified');
|
||||
remFromUserMessages('not_mc_verified');
|
||||
this.setState({
|
||||
link_answer: (accepted) ? 'You successfully linked your mc account.' : 'You denied.',
|
||||
linkAnswer: (accepted)
|
||||
? 'You successfully linked your mc account.'
|
||||
: 'You denied.',
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.props.messages) return null;
|
||||
const { messages: messagesr } = this.props;
|
||||
if (!messagesr) return null;
|
||||
// state variable is not allowed to be changed, make copy
|
||||
const messages = [...this.props.messages];
|
||||
const messages = [...messagesr];
|
||||
const { verifyAnswer, linkAnswer } = this.state;
|
||||
const { minecraftname } = this.props;
|
||||
|
||||
return (
|
||||
<div style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
||||
{(messages.includes('not_verified') && messages.splice(messages.indexOf('not_verified'), 1))
|
||||
{(messages.includes('not_verified')
|
||||
&& messages.splice(messages.indexOf('not_verified'), 1))
|
||||
? (
|
||||
<p className="usermessages">
|
||||
Please verify your mail address or your account could get deleted after a few days.
|
||||
{(this.state.verify_answer)
|
||||
? <span className="modallink">{this.state.verify_answer}</span>
|
||||
: <span className="modallink" onClick={this.submit_resend_verify}>Click here to request a new verification mail.</span>}
|
||||
Please verify your mail address
|
||||
or your account could get deleted after a few days.
|
||||
{(verifyAnswer)
|
||||
? (
|
||||
<span
|
||||
className="modallink"
|
||||
>
|
||||
{verifyAnswer}
|
||||
</span>
|
||||
)
|
||||
: (
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={this.submitResendVerify}
|
||||
>
|
||||
Click here to request a new verification mail.
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
) : null}
|
||||
{(messages.includes('not_mc_verified') && messages.splice(messages.indexOf('not_mc_verified'), 1))
|
||||
{(messages.includes('not_mc_verified')
|
||||
&& messages.splice(messages.indexOf('not_mc_verified'), 1))
|
||||
? (
|
||||
<p className="usermessages">You requested to link your mc account {this.props.minecraftname}.
|
||||
{(this.state.link_answer)
|
||||
? <span className="modallink">{this.state.link_answer}</span>
|
||||
<p className="usermessages">
|
||||
You requested to link your mc account {minecraftname}.
|
||||
|
||||
{(linkAnswer)
|
||||
? (
|
||||
<span
|
||||
className="modallink"
|
||||
>
|
||||
{linkAnswer}
|
||||
</span>
|
||||
)
|
||||
: (
|
||||
<span>
|
||||
<span className="modallink" onClick={() => { this.submit_mc_link(true); }}>Accept</span> or <span className="modallink" onClick={() => { this.submit_mc_link(false); }}>Deny</span>.
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={() => {
|
||||
this.submitMcLink(true);
|
||||
}}
|
||||
>
|
||||
Accept
|
||||
</span> or
|
||||
<span
|
||||
role="button"
|
||||
tabIndex={-1}
|
||||
className="modallink"
|
||||
onClick={() => {
|
||||
this.submitMcLink(false);
|
||||
}}
|
||||
>
|
||||
Deny
|
||||
</span>.
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
|
@ -110,7 +165,7 @@ function mapDispatchToProps(dispatch) {
|
|||
setMCName(minecraftname) {
|
||||
dispatch(setMinecraftName(minecraftname));
|
||||
},
|
||||
rem_from_messages(message) {
|
||||
remFromUserMessages(message) {
|
||||
dispatch(remFromMessages(message));
|
||||
},
|
||||
};
|
||||
|
|
|
@ -948,8 +948,8 @@ class VoxelPainterControls extends EventDispatcher {
|
|||
*/
|
||||
|
||||
// clamp to boundaries
|
||||
const state = scope.store.getState();
|
||||
const { canvasSize } = state.canvas;
|
||||
const reduxState = scope.store.getState();
|
||||
const { canvasSize } = reduxState.canvas;
|
||||
const bound = canvasSize / 2;
|
||||
scope.target.clamp({
|
||||
x: -bound,
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
*
|
||||
*/
|
||||
|
||||
// Tile creation is allowed to be slow
|
||||
/* eslint-disable no-await-in-loop */
|
||||
|
||||
import RedisCanvas from '../data/models/RedisCanvas';
|
||||
import logger from './logger';
|
||||
import { getChunkOfPixel } from './utils';
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
* @flow
|
||||
* */
|
||||
|
||||
// Tile creation is allowed to be slow
|
||||
/* eslint-disable no-await-in-loop */
|
||||
|
||||
import sharp from 'sharp';
|
||||
import fs from 'fs';
|
||||
|
||||
|
@ -14,7 +17,8 @@ import { getMaxTiledZoom } from './utils';
|
|||
import { TILE_SIZE, TILE_ZOOM_LEVEL } from './constants';
|
||||
|
||||
/*
|
||||
* Deletes a subtile from a tile (paints it in color 0), if we wouldn't do it, it would be black
|
||||
* Deletes a subtile from a tile (paints it in color 0),
|
||||
* if we wouldn't do it, it would be black
|
||||
* @param palette Palette to use
|
||||
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
||||
* @param cell subtile to delete [dx, dy]
|
||||
|
@ -32,8 +36,11 @@ function deleteSubtilefromTile(
|
|||
let channelOffset = (offset + row * TILE_SIZE * subtilesInTile) * 3;
|
||||
const max = channelOffset + TILE_SIZE * 3;
|
||||
while (channelOffset < max) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
buffer[channelOffset++] = palette.rgb[0];
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
buffer[channelOffset++] = palette.rgb[1];
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
buffer[channelOffset++] = palette.rgb[2];
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +59,7 @@ function addRGBSubtiletoTile(
|
|||
buffer: Uint8Array,
|
||||
) {
|
||||
const [dx, dy] = cell;
|
||||
const chunkOffset = (dx + dy * subtilesInTile * TILE_SIZE) * TILE_SIZE; // offset in pixels
|
||||
const chunkOffset = (dx + dy * subtilesInTile * TILE_SIZE) * TILE_SIZE;
|
||||
let pos: number = 0;
|
||||
for (let row = 0; row < TILE_SIZE; row += 1) {
|
||||
let channelOffset = (chunkOffset + row * TILE_SIZE * subtilesInTile) * 3;
|
||||
|
@ -80,7 +87,7 @@ function addIndexedSubtiletoTile(
|
|||
buffer: Uint8Array,
|
||||
) {
|
||||
const [dx, dy] = cell;
|
||||
const chunkOffset = (dx + dy * subtilesInTile * TILE_SIZE) * TILE_SIZE; // offset in pixels
|
||||
const chunkOffset = (dx + dy * subtilesInTile * TILE_SIZE) * TILE_SIZE;
|
||||
let pos: number = 0;
|
||||
let clr: number;
|
||||
for (let row = 0; row < TILE_SIZE; row += 1) {
|
||||
|
@ -194,6 +201,7 @@ export async function createZoomedTile(
|
|||
const na = [];
|
||||
for (let dy = 0; dy < TILE_ZOOM_LEVEL; dy += 1) {
|
||||
for (let dx = 0; dx < TILE_ZOOM_LEVEL; dx += 1) {
|
||||
// eslint-disable-next-line max-len
|
||||
const chunkfile = `${canvasTileFolder}/${z + 1}/${x * TILE_ZOOM_LEVEL + dx}/${y * TILE_ZOOM_LEVEL + dy}.png`;
|
||||
if (!fs.existsSync(chunkfile)) {
|
||||
na.push([dx, dy]);
|
||||
|
@ -244,8 +252,11 @@ export async function createEmptyTile(
|
|||
let i = 0;
|
||||
const max = TILE_SIZE * TILE_SIZE * 3;
|
||||
while (i < max) {
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
tileRGBBuffer[i++] = palette.rgb[0];
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
tileRGBBuffer[i++] = palette.rgb[1];
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
tileRGBBuffer[i++] = palette.rgb[2];
|
||||
}
|
||||
const filename = `${canvasTileFolder}/emptytile.png`;
|
||||
|
@ -416,6 +427,7 @@ export async function initializeTiles(
|
|||
}
|
||||
}
|
||||
logger.info(
|
||||
// eslint-disable-next-line max-len
|
||||
`Tiling: Created ${cnts} / ${cnt} tiles for zoom ${zoom} for canvas${canvasId}`,
|
||||
);
|
||||
}
|
||||
|
@ -429,6 +441,7 @@ export async function initializeTiles(
|
|||
);
|
||||
//--
|
||||
logger.info(
|
||||
// eslint-disable-next-line max-len
|
||||
`Tiling: Elapsed Time: ${Math.round((Date.now() - startTime) / 1000)} for canvas${canvasId}`,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,11 @@ const logger = proxyLogger;
|
|||
* @param ip IP to check
|
||||
* @return true if proxy, false if not
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
async function getIPIntel(ip: string): Promise<boolean> {
|
||||
// eslint-disable-next-line max-len
|
||||
const email = `${Math.random().toString(36).substring(8)}-${Math.random().toString(36).substring(4)}@gmail.com`;
|
||||
// eslint-disable-next-line max-len
|
||||
const url = `http://check.getipintel.net/check.php?ip=${ip}&contact=${email}&flags=m`;
|
||||
logger.info(`PROXYCHECK fetching getipintel ${url}`);
|
||||
const response = await fetch(url, {
|
||||
|
@ -27,6 +30,7 @@ async function getIPIntel(ip: string): Promise<boolean> {
|
|||
Accept: '*/*',
|
||||
'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
|
||||
Referer: 'http://check.getipintel.net/',
|
||||
// eslint-disable-next-line max-len
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
|
||||
},
|
||||
});
|
||||
|
@ -54,6 +58,7 @@ async function getProxyCheck(ip: string): Promise<boolean> {
|
|||
logger.info('PROXYCHECK fetching proxycheck %s', url);
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
// eslint-disable-next-line max-len
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
|
||||
},
|
||||
});
|
||||
|
@ -63,7 +68,7 @@ async function getProxyCheck(ip: string): Promise<boolean> {
|
|||
}
|
||||
const data = await response.json();
|
||||
logger.info('PROXYCHECK proxycheck is proxy?', data);
|
||||
return data.status == 'ok' && data[ip].proxy === 'yes';
|
||||
return data.status === 'ok' && data[ip].proxy === 'yes';
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -75,11 +80,13 @@ async function getProxyCheck(ip: string): Promise<boolean> {
|
|||
*/
|
||||
async function getShroomey(ip: string): Promise<boolean> {
|
||||
logger.info('PROXYCHECK fetching shroomey %s', ip);
|
||||
// eslint-disable-next-line max-len
|
||||
const response = await fetch(`http://www.shroomery.org/ythan/proxycheck.php?ip=${ip}`, {
|
||||
headers: {
|
||||
Accept: '*/*',
|
||||
'Accept-Language': 'es-ES,es;q=0.8,en;q=0.6',
|
||||
Referer: 'http://www.shroomery.org/',
|
||||
// eslint-disable-next-line max-len
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36',
|
||||
},
|
||||
});
|
||||
|
@ -89,21 +96,6 @@ async function getShroomey(ip: string): Promise<boolean> {
|
|||
return body === 'Y';
|
||||
}
|
||||
|
||||
/*
|
||||
* check shroomey, and if positive there, check
|
||||
* getipintel
|
||||
* @param ip IP to check
|
||||
* @return true if proxy, false if not
|
||||
*/
|
||||
async function getCombined(ip: string): Promise<boolean> {
|
||||
if (ip.indexOf(':') == -1) {
|
||||
const shroom = await getShroomey(ip);
|
||||
if (!shroom) return false;
|
||||
}
|
||||
const ipintel = await getIPIntel(ip);
|
||||
return ipintel;
|
||||
}
|
||||
|
||||
/*
|
||||
* check MYSQL Blacklist table
|
||||
* @param ip IP to check
|
||||
|
@ -150,7 +142,14 @@ async function dummy(): Promise<boolean> {
|
|||
async function withoutCache(f, ip) {
|
||||
if (!ip) return true;
|
||||
const ipKey = getIPv6Subnet(ip);
|
||||
return !(await isWhitelisted(ipKey)) && (await isBlacklisted(ipKey) || await f(ip));
|
||||
if (await isWhitelisted(ipKey)) {
|
||||
return false;
|
||||
}
|
||||
if (await isBlacklisted(ipKey)) {
|
||||
return true;
|
||||
}
|
||||
const result = f(ip);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -170,7 +169,12 @@ async function withCache(f, ip) {
|
|||
const cache = await redis.getAsync(key);
|
||||
if (cache) {
|
||||
const str = cache.toString('utf8');
|
||||
logger.debug('PROXYCHECK fetch isproxy from cache %s %s %s %s %s', key, cache, typeof cache, str, typeof str);
|
||||
logger.debug('PROXYCHECK fetch isproxy from cache %s %s %s %s %s',
|
||||
key,
|
||||
cache,
|
||||
typeof cache,
|
||||
str,
|
||||
typeof str);
|
||||
return str === 'y';
|
||||
}
|
||||
logger.debug('PROXYCHECK fetch isproxy not from cache %s', key);
|
||||
|
@ -178,7 +182,7 @@ async function withCache(f, ip) {
|
|||
// else make asynchronous ipcheck and assume no proxy in the meantime
|
||||
// use lock to just check three at a time
|
||||
// do not check ip that currently gets checked
|
||||
if (checking.indexOf(ipKey) == -1 && lock > 0) {
|
||||
if (checking.indexOf(ipKey) === -1 && lock > 0) {
|
||||
lock -= 1;
|
||||
checking.push(ipKey);
|
||||
withoutCache(f, ip)
|
||||
|
@ -199,16 +203,16 @@ async function withCache(f, ip) {
|
|||
return false;
|
||||
}
|
||||
|
||||
export async function cheapDetector(ip: string): Promise<boolean> {
|
||||
return (await withCache(getProxyCheck, ip));
|
||||
export function cheapDetector(ip: string): Promise<boolean> {
|
||||
return withCache(getProxyCheck, ip);
|
||||
}
|
||||
|
||||
export async function strongDetector(ip: string): Promise<boolean> {
|
||||
return (await withCache(getShroomey, ip));
|
||||
export function strongDetector(ip: string): Promise<boolean> {
|
||||
return withCache(getShroomey, ip);
|
||||
}
|
||||
|
||||
export async function blacklistDetector(ip: string): Promise<boolean> {
|
||||
return (await withCache(dummy, ip));
|
||||
export function blacklistDetector(ip: string): Promise<boolean> {
|
||||
return withCache(dummy, ip);
|
||||
}
|
||||
|
||||
// export default cheapDetector;
|
||||
|
|
|
@ -15,7 +15,7 @@ class Minecraft {
|
|||
this.online = {};
|
||||
}
|
||||
|
||||
async report_login(minecraftid, minecraftname) {
|
||||
async reportLogin(minecraftid, minecraftname) {
|
||||
const user = new User();
|
||||
user.minecraftname = minecraftname;
|
||||
const reguser = await RegUser.findOne({ where: { minecraftid } });
|
||||
|
@ -35,26 +35,27 @@ class Minecraft {
|
|||
}
|
||||
*/
|
||||
|
||||
report_logout(minecraftid) {
|
||||
reportLogout(minecraftid) {
|
||||
delete this.online[minecraftid];
|
||||
}
|
||||
|
||||
report_userlist(list) {
|
||||
reportUserlist(list) {
|
||||
this.online = {};
|
||||
list.forEach((user) => {
|
||||
const [minecraftid, minecraftname] = user;
|
||||
this.report_login(minecraftid, minecraftname);
|
||||
this.reportLogin(minecraftid, minecraftname);
|
||||
});
|
||||
}
|
||||
|
||||
async linkacc(minecraftid, minecraftname, name) {
|
||||
static async linkacc(minecraftid, minecraftname, name) {
|
||||
try {
|
||||
const finduser = await RegUser.findOne({ where: { minecraftid } });
|
||||
if (finduser) {
|
||||
if (finduser.name == name) {
|
||||
if (finduser.name === name) {
|
||||
if (finduser.mcVerified) {
|
||||
return 'You are already verified';
|
||||
}
|
||||
// eslint-disable-next-line max-len
|
||||
return 'You already got a verification message in the pixelplanet UserArea. Please refresh the page if you do not see it.';
|
||||
}
|
||||
return `You already linked to other account ${finduser.name}.`;
|
||||
|
@ -62,6 +63,7 @@ class Minecraft {
|
|||
const reguser = await RegUser.findOne({ where: { name } });
|
||||
if (reguser) {
|
||||
if (reguser.minecraftid) {
|
||||
// eslint-disable-next-line max-len
|
||||
return `This pixelplanet account is already linked to ${reguser.minecraftname}`;
|
||||
}
|
||||
reguser.update({ minecraftname, minecraftid });
|
||||
|
@ -95,8 +97,11 @@ class Minecraft {
|
|||
|
||||
minecraftname2User(minecraftname: string): User {
|
||||
const searchstring = minecraftname;
|
||||
for (const [minecraftid, user] of Object.entries(this.online)) {
|
||||
if (user.minecraftname == searchstring) { return user; }
|
||||
const onlineIds = Object.keys(this.online);
|
||||
for (let i = 0; i < onlineIds.length; i += 1) {
|
||||
const id = onlineIds[i];
|
||||
const user = this.online[id];
|
||||
if (user.minecraftname === searchstring) { return user; }
|
||||
}
|
||||
|
||||
const user = new User();
|
||||
|
|
|
@ -62,7 +62,7 @@ async function exportVox(
|
|||
return zc - 1;
|
||||
}
|
||||
const zcMax = zc + VOX_OBJECT_CSIZE / 2 + 1;
|
||||
return (zcMin <= posMax) ? zcMax : zc;
|
||||
return (zcMax <= posMax) ? zcMax : zc;
|
||||
});
|
||||
|
||||
// Size Chunk
|
||||
|
@ -79,7 +79,7 @@ async function exportVox(
|
|||
// 4 bytes numVoxels
|
||||
// 4 bytes (x, y, z, clr) for every voxel
|
||||
let numVoxels = 0;
|
||||
for (let j = yxcMin; j <= ycMax; j += 1) {
|
||||
for (let j = ycMin; j <= ycMax; j += 1) {
|
||||
for (let i = xcMin; i <= xcMax; i += 1) {
|
||||
const key = `${i}:${j}`;
|
||||
const { buffer } = chunks.get(key);
|
||||
|
|
|
@ -18,6 +18,7 @@ export type GUIState = {
|
|||
paletteOpen: boolean,
|
||||
menuOpen: boolean,
|
||||
chatChannel: number,
|
||||
style: string,
|
||||
};
|
||||
|
||||
const initialState: GUIState = {
|
||||
|
@ -33,6 +34,7 @@ const initialState: GUIState = {
|
|||
paletteOpen: true,
|
||||
menuOpen: false,
|
||||
chatChannel: 0,
|
||||
style: 'default',
|
||||
};
|
||||
|
||||
|
||||
|
@ -97,6 +99,14 @@ export default function gui(
|
|||
};
|
||||
}
|
||||
|
||||
case 'SELECT_STYLE': {
|
||||
const { style } = action;
|
||||
return {
|
||||
...state,
|
||||
style,
|
||||
};
|
||||
}
|
||||
|
||||
case 'SET_CHAT_CHANNEL': {
|
||||
return {
|
||||
...state,
|
||||
|
|
|
@ -8,13 +8,11 @@ import type { Action } from '../actions/types';
|
|||
|
||||
export type ModalState = {
|
||||
modalType: ?string,
|
||||
modalProps: object,
|
||||
chatOpen: boolean,
|
||||
};
|
||||
|
||||
const initialState: ModalState = {
|
||||
modalType: null,
|
||||
modalProps: {},
|
||||
chatOpen: false,
|
||||
};
|
||||
|
||||
|
@ -27,12 +25,11 @@ export default function modal(
|
|||
// clear hover when placing a pixel
|
||||
// fixes a bug with iPad
|
||||
case 'SHOW_MODAL': {
|
||||
const { modalType, modalProps } = action;
|
||||
const { modalType } = action;
|
||||
const chatOpen = (modalType === 'CHAT') ? false : state.chatOpen;
|
||||
return {
|
||||
...state,
|
||||
modalType,
|
||||
modalProps,
|
||||
chatOpen,
|
||||
};
|
||||
}
|
||||
|
@ -42,7 +39,6 @@ export default function modal(
|
|||
return {
|
||||
...state,
|
||||
modalType: null,
|
||||
modalProps: {},
|
||||
};
|
||||
|
||||
case 'TOGGLE_CHAT_BOX': {
|
||||
|
|
|
@ -19,7 +19,7 @@ function validate(newPassword) {
|
|||
}
|
||||
|
||||
export default async (req: Request, res: Response) => {
|
||||
const { new_password: newPassword, password } = req.body;
|
||||
const { newPassword, password } = req.body;
|
||||
const errors = validate(newPassword);
|
||||
if (errors.length > 0) {
|
||||
res.status(400);
|
||||
|
|
|
@ -45,23 +45,35 @@ router.use(bodyParser.urlencoded({ extended: true }));
|
|||
* Check for POST parameters,
|
||||
* if invalid password is given, ignore it and go to next
|
||||
*/
|
||||
router.post('/', async (req: Request, res: Response, next) => {
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
const { pass, passconf, code } = req.body;
|
||||
if (!pass || !passconf || !code) {
|
||||
const html = getPasswordResetHtml(null, null, 'You sent an empty password or invalid data :(');
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
'You sent an empty password or invalid data :(',
|
||||
);
|
||||
res.status(400).send(html);
|
||||
return;
|
||||
}
|
||||
|
||||
const email = mailProvider.checkCode(code);
|
||||
if (!email) {
|
||||
const html = getPasswordResetHtml(null, null, "This password-reset link isn't valid anymore :(");
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
"This password-reset link isn't valid anymore :(",
|
||||
);
|
||||
res.status(401).send(html);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pass != passconf) {
|
||||
const html = getPasswordResetHtml(null, null, 'Your passwords do not match :(');
|
||||
if (pass !== passconf) {
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
'Your passwords do not match :(',
|
||||
);
|
||||
res.status(400).send(html);
|
||||
return;
|
||||
}
|
||||
|
@ -69,15 +81,24 @@ router.post('/', async (req: Request, res: Response, next) => {
|
|||
// set password
|
||||
const reguser = await RegUser.findOne({ where: { email } });
|
||||
if (!reguser) {
|
||||
// eslint-disable-next-line max-len
|
||||
logger.error(`${email} from PasswordReset page does not exist in database`);
|
||||
const html = getPasswordResetHtml(null, null, "User doesn't exist in our database :(");
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
"User doesn't exist in our database :(",
|
||||
);
|
||||
res.status(400).send(html);
|
||||
return;
|
||||
}
|
||||
await reguser.update({ password: pass });
|
||||
|
||||
logger.info(`Changed password of ${email} via passowrd reset form`);
|
||||
const html = getPasswordResetHtml(null, null, 'Passowrd successfully changed.');
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
'Passowrd successfully changed.',
|
||||
);
|
||||
res.status(200).send(html);
|
||||
});
|
||||
|
||||
|
@ -85,17 +106,26 @@ router.post('/', async (req: Request, res: Response, next) => {
|
|||
/*
|
||||
* Check GET parameters for action to execute
|
||||
*/
|
||||
router.get('/', async (req: Request, res: Response, next) => {
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
const { token } = req.query;
|
||||
if (!token) {
|
||||
const html = getPasswordResetHtml(null, null, 'Invalid url :( Please check your mail again.');
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
'Invalid url :( Please check your mail again.',
|
||||
);
|
||||
res.status(400).send(html);
|
||||
return;
|
||||
}
|
||||
|
||||
const email = mailProvider.checkCode(token);
|
||||
if (!email) {
|
||||
const html = getPasswordResetHtml(null, null, 'This passwort reset link is wrong or already expired, please request a new one (Note: you can use those links just once)');
|
||||
const html = getPasswordResetHtml(
|
||||
null,
|
||||
null,
|
||||
// eslint-disable-next-line max-len
|
||||
'This passwort reset link is wrong or already expired, please request a new one (Note: you can use those links just once)',
|
||||
);
|
||||
res.status(401).send(html);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ class APISocketServer extends WebSocketEvents {
|
|||
logger.info(`APISocket message ${message}`);
|
||||
if (command === 'login') {
|
||||
const [minecraftid, minecraftname, ip] = packet;
|
||||
const user = await this.mc.report_login(minecraftid, minecraftname);
|
||||
const user = await this.mc.reportLogin(minecraftid, minecraftname);
|
||||
// get userinfo
|
||||
user.ip = ip;
|
||||
const wait = await user.getWait(0);
|
||||
|
@ -234,12 +234,12 @@ class APISocketServer extends WebSocketEvents {
|
|||
logger.error('Got invalid minecraft userlist on APISocketServer');
|
||||
return;
|
||||
}
|
||||
this.mc.report_userlist(userlist);
|
||||
this.mc.reportUserlist(userlist);
|
||||
return;
|
||||
}
|
||||
if (command === 'logout') {
|
||||
const [minecraftid] = packet;
|
||||
this.mc.report_logout(minecraftid);
|
||||
this.mc.reportLogout(minecraftid);
|
||||
return;
|
||||
}
|
||||
if (command === 'mcchat') {
|
||||
|
@ -260,7 +260,7 @@ class APISocketServer extends WebSocketEvents {
|
|||
}
|
||||
if (command === 'linkacc') {
|
||||
const [minecraftid, minecraftname, name] = packet;
|
||||
const ret = await this.mc.linkacc(minecraftid, minecraftname, name);
|
||||
const ret = await Minecraft.linkacc(minecraftid, minecraftname, name);
|
||||
if (!ret) {
|
||||
webSockets.notifyChangedMe(name);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
* @flow
|
||||
*/
|
||||
|
||||
// allow the websocket to be noisy on the console
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import EventEmitter from 'events';
|
||||
|
||||
import CoolDownPacket from './packets/CoolDownPacket';
|
||||
|
@ -44,9 +47,9 @@ class ProtocolClient extends EventEmitter {
|
|||
console.log('WebSocket already open, not starting');
|
||||
}
|
||||
this.timeConnected = Date.now();
|
||||
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const url = `${protocol}//${location.hostname}${
|
||||
location.port ? `:${location.port}` : ''
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const url = `${protocol}//${window.location.hostname}${
|
||||
window.location.port ? `:${window.location.port}` : ''
|
||||
}/ws`;
|
||||
this.ws = new WebSocket(url);
|
||||
this.ws.binaryType = 'arraybuffer';
|
||||
|
|
|
@ -9,6 +9,7 @@ import audio from './audio';
|
|||
import swal from './sweetAlert';
|
||||
import protocolClientHook from './protocolClientHook';
|
||||
import rendererHook from './rendererHook';
|
||||
import styleHook from './styleHook';
|
||||
// import ads from './ads';
|
||||
// import analytics from './analytics';
|
||||
import array from './array';
|
||||
|
@ -40,6 +41,7 @@ const store = createStore(
|
|||
title,
|
||||
protocolClientHook,
|
||||
rendererHook,
|
||||
styleHook,
|
||||
// ads,
|
||||
// analytics,
|
||||
logger,
|
||||
|
@ -49,7 +51,9 @@ const store = createStore(
|
|||
|
||||
|
||||
export default function configureStore(onComplete: ?() => void) {
|
||||
persistStore(store, null, onComplete);
|
||||
persistStore(store, null, () => {
|
||||
onComplete(store);
|
||||
});
|
||||
if (isDebuggingInChrome) {
|
||||
window.store = store;
|
||||
}
|
||||
|
|
22
src/store/styleHook.js
Normal file
22
src/store/styleHook.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import setStyle from '../ui/setStyle';
|
||||
|
||||
export default () => (next) => (action) => {
|
||||
switch (action.type) {
|
||||
case 'SELECT_STYLE': {
|
||||
const {
|
||||
style,
|
||||
} = action;
|
||||
setStyle(style);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
|
||||
return next(action);
|
||||
};
|
|
@ -3,7 +3,6 @@
|
|||
*/
|
||||
|
||||
import swal from 'sweetalert2';
|
||||
import 'sweetalert2/src/sweetalert2.scss';
|
||||
|
||||
export default () => (next) => (action) => {
|
||||
switch (action.type) {
|
||||
|
|
484
src/styles/dark-round.css
Normal file
484
src/styles/dark-round.css
Normal file
|
@ -0,0 +1,484 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
user-select: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
html, body {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/benweet/stackedit/issues/212
|
||||
*/
|
||||
kbd {
|
||||
padding: 0.1em 0.6em;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 11px;
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
background-color: #f7f7f7;
|
||||
color: #333;
|
||||
-moz-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
display: inline-block;
|
||||
margin: 0 0.1em;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #91ffe0;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #b5d06d;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #d9f68a;
|
||||
}
|
||||
|
||||
.modallink {
|
||||
text-decoration: none;
|
||||
color: #91ffe0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.modallink:hover){
|
||||
font-weight: bold;
|
||||
color: #d9f68a;
|
||||
}
|
||||
|
||||
.inarea {
|
||||
border-style: solid;
|
||||
border-color: #d5d5d5;
|
||||
padding: 4px;
|
||||
margin-top: 4px;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.tab-list-item {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin-bottom: -1px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.tab-list-active {
|
||||
background-color: #7b7b7b;
|
||||
border: solid #ccc;
|
||||
border-width: 1px 1px 0 1px;
|
||||
}
|
||||
|
||||
table {
|
||||
font-family: arial, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #dddddd;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
position: absolute;
|
||||
background-color: rgba(59, 59, 59, 0.8);
|
||||
width: 350px;
|
||||
height: 200px;
|
||||
bottom: 16px;
|
||||
right: 98px;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
}
|
||||
|
||||
.actionbuttons, .coorbox, .onlinebox, .cooldownbox, .palettebox {
|
||||
position: absolute;
|
||||
background-color: rgba(59, 59, 59, 0.8);
|
||||
color: #f4f4f4;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 36px;
|
||||
height: 36px;
|
||||
width: auto;
|
||||
padding: 0 16px;
|
||||
border: solid black;
|
||||
border-radius: 21px;
|
||||
border-width: thin;
|
||||
}
|
||||
.coorbox {
|
||||
left: 16px;
|
||||
cursor: pointer;
|
||||
bottom: 16px;
|
||||
}
|
||||
.onlinebox {
|
||||
left: 16px;
|
||||
bottom: 57px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#menubutton {
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
#menu > div {
|
||||
z-index: 1;
|
||||
background-color: #15374fd1;
|
||||
}
|
||||
|
||||
#helpbutton {
|
||||
left: 16px;
|
||||
top: 221px;
|
||||
}
|
||||
#minecraftbutton {
|
||||
left: 16px;
|
||||
top: 180px;
|
||||
}
|
||||
#settingsbutton {
|
||||
left: 16px;
|
||||
top: 57px;
|
||||
}
|
||||
#loginbutton {
|
||||
left: 16px;
|
||||
top: 98px;
|
||||
}
|
||||
#downloadbutton {
|
||||
left: 16px;
|
||||
top: 139px;
|
||||
}
|
||||
#globebutton {
|
||||
left: 98px;
|
||||
top: 16px;
|
||||
}
|
||||
#voxelbutton {
|
||||
left: 180px;
|
||||
top: 16px;
|
||||
}
|
||||
#canvasbutton {
|
||||
left: 57px;
|
||||
top: 16px;
|
||||
}
|
||||
#minecrafttpbutton {
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
#palselbutton {
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
#chatbutton {
|
||||
bottom: 16px;
|
||||
right: 57px;
|
||||
}
|
||||
|
||||
#historyselect {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 70px;
|
||||
width: 140px;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hsar {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.Modal {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
background: #444242 none repeat scroll 0 0;;
|
||||
color: #f4f4f4;
|
||||
overflow-y: auto;
|
||||
border-radius: 4px;
|
||||
outline: currentcolor none medium;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 80%;
|
||||
max-height: 900px;
|
||||
width: 70%;
|
||||
transition: all 0.5s ease 0s;
|
||||
border-radius: 21px;
|
||||
}
|
||||
|
||||
.modaltext, .modalcotext {
|
||||
color: #f4f4f4;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.modaltext {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modaltitle {
|
||||
color: #d7e5fb;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
margin-left: 0;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modaldesc {
|
||||
box-sizing: border-box;
|
||||
flex: 1 1 auto;
|
||||
color: hsla(220, 100%, 95.3%, 0.6);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.modaldivider {
|
||||
box-sizing: border-box;
|
||||
margin-top: 20px;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: hsla(216, 4%, 74%, .3);
|
||||
}
|
||||
|
||||
.modalinfo {
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modalcvtext {
|
||||
color: hsla(220, 100%, 95.3%, 0.6);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.ModalClose {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 0 0 36px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
background-color: #55555d;
|
||||
border-color: #dcddde;
|
||||
top: 30px;
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
@media (max-width: 604px) {
|
||||
.Modal {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
height: 95%;
|
||||
width: 90%;
|
||||
transform: none;
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
padding: 5%;
|
||||
}
|
||||
}
|
||||
.Overlay {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: rgba(255, 255, 255, 0.75);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.chatbox div .chatarea {
|
||||
height: 174px;
|
||||
}
|
||||
.chatarea {
|
||||
padding: 3px 3px 0px 3px;
|
||||
margin: 0px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
height: 95%;
|
||||
}
|
||||
.chatinput {
|
||||
height: 22px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.chatname {
|
||||
color: #4B0000;
|
||||
font-size: 13px;
|
||||
user-select: all;
|
||||
}
|
||||
.chatmsg {
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
user-select: text;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.usermessages {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
.stattext {
|
||||
font-size: 18px;
|
||||
}
|
||||
.statvalue {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #ecc9ff;
|
||||
}
|
||||
|
||||
.pressed {
|
||||
box-shadow:0 0 3px 2px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.notifyboxvis, .notifyboxhid {
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
position: absolute;
|
||||
top: 57px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 30px;
|
||||
width: 20px;
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.notifyboxvis {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: visibility 0s, opacity 0.5s linear;
|
||||
}
|
||||
.notifyboxhid {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility 0.5s, opacity 0.5s linear;
|
||||
}
|
||||
|
||||
.cooldownbox {
|
||||
top: 16px;
|
||||
width: 48px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.actionbuttons {
|
||||
vertical-align: text-bottom;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
|
||||
background-color: #363637;
|
||||
}
|
||||
|
||||
.palettebox {
|
||||
z-index: 1;
|
||||
bottom: 59px;
|
||||
padding: 3px;
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#colors .selected,
|
||||
#colors span:hover {
|
||||
z-index: 2 !important;
|
||||
outline: rgb(234, 234, 234) solid 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.80) 0px 0px 5px 2px;
|
||||
-ms-transform: scale(1.10,1.10); /* IE 9 */
|
||||
-webkit-transform: scale(1.10,1.10); /* Safari */
|
||||
transform: scale(1.10,1.10); /* Standard syntax */
|
||||
}
|
||||
|
||||
#outstreamContainer {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
z-index: 9000;
|
||||
}
|
||||
|
||||
.grecaptcha-badge {
|
||||
visibility: hidden;
|
||||
}
|
481
src/styles/dark.css
Normal file
481
src/styles/dark.css
Normal file
|
@ -0,0 +1,481 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
user-select: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
html, body {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/benweet/stackedit/issues/212
|
||||
*/
|
||||
kbd {
|
||||
padding: 0.1em 0.6em;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 11px;
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
background-color: #f7f7f7;
|
||||
color: #333;
|
||||
-moz-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
display: inline-block;
|
||||
margin: 0 0.1em;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
a:link {
|
||||
color: #91ffe0;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #b5d06d;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #d9f68a;
|
||||
}
|
||||
|
||||
.modallink {
|
||||
text-decoration: none;
|
||||
color: #91ffe0;
|
||||
cursor: pointer;
|
||||
}
|
||||
.modallink:hover){
|
||||
font-weight: bold;
|
||||
color: #d9f68a;
|
||||
}
|
||||
|
||||
.inarea {
|
||||
border-style: solid;
|
||||
border-color: #d5d5d5;
|
||||
padding: 4px;
|
||||
margin-top: 4px;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.tab-list-item {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin-bottom: -1px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.tab-list-active {
|
||||
background-color: #7b7b7b;
|
||||
border: solid #ccc;
|
||||
border-width: 1px 1px 0 1px;
|
||||
}
|
||||
|
||||
table {
|
||||
font-family: arial, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #dddddd;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #505050;
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
position: absolute;
|
||||
background-color: rgba(59, 59, 59, 0.8);
|
||||
width: 350px;
|
||||
height: 200px;
|
||||
bottom: 16px;
|
||||
right: 98px;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
}
|
||||
|
||||
.actionbuttons, .coorbox, .onlinebox, .cooldownbox, .palettebox {
|
||||
position: absolute;
|
||||
background-color: rgba(59, 59, 59, 0.8);
|
||||
color: #f4f4f4;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 36px;
|
||||
height: 36px;
|
||||
width: auto;
|
||||
padding: 0 16px;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
}
|
||||
.coorbox {
|
||||
left: 16px;
|
||||
cursor: pointer;
|
||||
bottom: 16px;
|
||||
}
|
||||
.onlinebox {
|
||||
left: 16px;
|
||||
bottom: 57px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#menubutton {
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
#menu > div {
|
||||
z-index: 1;
|
||||
background-color: #15374fd1;
|
||||
}
|
||||
|
||||
#helpbutton {
|
||||
left: 16px;
|
||||
top: 221px;
|
||||
}
|
||||
#minecraftbutton {
|
||||
left: 16px;
|
||||
top: 180px;
|
||||
}
|
||||
#settingsbutton {
|
||||
left: 16px;
|
||||
top: 57px;
|
||||
}
|
||||
#loginbutton {
|
||||
left: 16px;
|
||||
top: 98px;
|
||||
}
|
||||
#downloadbutton {
|
||||
left: 16px;
|
||||
top: 139px;
|
||||
}
|
||||
#globebutton {
|
||||
left: 98px;
|
||||
top: 16px;
|
||||
}
|
||||
#voxelbutton {
|
||||
left: 180px;
|
||||
top: 16px;
|
||||
}
|
||||
#canvasbutton {
|
||||
left: 57px;
|
||||
top: 16px;
|
||||
}
|
||||
#minecrafttpbutton {
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
#palselbutton {
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
#chatbutton {
|
||||
bottom: 16px;
|
||||
right: 57px;
|
||||
}
|
||||
|
||||
#historyselect {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 70px;
|
||||
width: 140px;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hsar {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.Modal {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
background: #444242 none repeat scroll 0 0;;
|
||||
color: #f4f4f4;
|
||||
overflow-y: auto;
|
||||
border-radius: 4px;
|
||||
outline: currentcolor none medium;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 80%;
|
||||
max-height: 900px;
|
||||
width: 70%;
|
||||
transition: all 0.5s ease 0s;
|
||||
}
|
||||
|
||||
.modaltext, .modalcotext {
|
||||
color: #f4f4f4;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.modaltext {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modaltitle {
|
||||
color: #d7e5fb;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
margin-left: 0;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modaldesc {
|
||||
box-sizing: border-box;
|
||||
flex: 1 1 auto;
|
||||
color: hsla(220, 100%, 95.3%, 0.6);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.modaldivider {
|
||||
box-sizing: border-box;
|
||||
margin-top: 20px;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: hsla(216, 4%, 74%, .3);
|
||||
}
|
||||
|
||||
.modalinfo {
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modalcvtext {
|
||||
color: hsla(220, 100%, 95.3%, 0.6);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.ModalClose {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 0 0 36px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
background-color: #55555d;
|
||||
border-color: #dcddde;
|
||||
top: 30px;
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
@media (max-width: 604px) {
|
||||
.Modal {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
height: 95%;
|
||||
width: 90%;
|
||||
transform: none;
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
padding: 5%;
|
||||
}
|
||||
}
|
||||
.Overlay {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: rgba(255, 255, 255, 0.75);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.chatbox div .chatarea {
|
||||
height: 174px;
|
||||
}
|
||||
.chatarea {
|
||||
padding: 3px 3px 0px 3px;
|
||||
margin: 0px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
height: 95%;
|
||||
}
|
||||
.chatinput {
|
||||
height: 22px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.chatname {
|
||||
color: #4B0000;
|
||||
font-size: 13px;
|
||||
user-select: all;
|
||||
}
|
||||
.chatmsg {
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
user-select: text;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.usermessages {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
.stattext {
|
||||
font-size: 18px;
|
||||
}
|
||||
.statvalue {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #ecc9ff;
|
||||
}
|
||||
|
||||
.pressed {
|
||||
box-shadow:0 0 3px 2px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.notifyboxvis, .notifyboxhid {
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
position: absolute;
|
||||
top: 57px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 30px;
|
||||
width: 20px;
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.notifyboxvis {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: visibility 0s, opacity 0.5s linear;
|
||||
}
|
||||
.notifyboxhid {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility 0.5s, opacity 0.5s linear;
|
||||
}
|
||||
|
||||
.cooldownbox {
|
||||
top: 16px;
|
||||
width: 48px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.actionbuttons {
|
||||
vertical-align: text-bottom;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
|
||||
background-color: #363637;
|
||||
}
|
||||
|
||||
.palettebox {
|
||||
z-index: 1;
|
||||
bottom: 59px;
|
||||
padding: 3px;
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
#colors .selected,
|
||||
#colors span:hover {
|
||||
z-index: 2 !important;
|
||||
outline: rgb(234, 234, 234) solid 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.80) 0px 0px 5px 2px;
|
||||
-ms-transform: scale(1.10,1.10); /* IE 9 */
|
||||
-webkit-transform: scale(1.10,1.10); /* Safari */
|
||||
transform: scale(1.10,1.10); /* Standard syntax */
|
||||
}
|
||||
|
||||
#outstreamContainer {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
z-index: 9000;
|
||||
}
|
||||
|
||||
.grecaptcha-badge {
|
||||
visibility: hidden;
|
||||
}
|
|
@ -38,17 +38,17 @@ kbd {
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:global(.modallink) {
|
||||
.modallink {
|
||||
text-decoration: none;
|
||||
color: #428bca;
|
||||
cursor: pointer;
|
||||
}
|
||||
:global(.modallink:hover){
|
||||
.modallink:hover){
|
||||
font-weight: bold;
|
||||
color: #226baa;
|
||||
}
|
||||
|
||||
:global(.inarea) {
|
||||
.inarea {
|
||||
border-style: solid;
|
||||
border-color: #d5d5d5;
|
||||
padding: 4px;
|
||||
|
@ -56,41 +56,41 @@ kbd {
|
|||
border-width: 1px;
|
||||
}
|
||||
|
||||
:global(.tab-list) {
|
||||
.tab-list {
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
:global(.tab-list-item) {
|
||||
.tab-list-item {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin-bottom: -1px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
:global(.tab-list-active) {
|
||||
.tab-list-active {
|
||||
background-color: white;
|
||||
border: solid #ccc;
|
||||
border-width: 1px 1px 0 1px;
|
||||
}
|
||||
|
||||
:global(table) {
|
||||
table {
|
||||
font-family: arial, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:global(td, th) {
|
||||
td, th {
|
||||
border: 1px solid #dddddd;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
:global(tr:nth-child(even)) {
|
||||
tr:nth-child(even) {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
|
||||
:global(.chatbox) {
|
||||
.chatbox {
|
||||
position: absolute;
|
||||
background-color: rgba(226, 226, 226, 0.92);
|
||||
width: 350px;
|
||||
|
@ -101,7 +101,7 @@ kbd {
|
|||
border-width: thin;
|
||||
}
|
||||
|
||||
:global(.actionbuttons), :global(.coorbox), :global(.onlinebox), :global(.cooldownbox), :global(.palettebox) {
|
||||
.actionbuttons, .coorbox, .onlinebox, .cooldownbox, .palettebox {
|
||||
position: absolute;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
|
@ -114,114 +114,202 @@ kbd {
|
|||
border: solid black;
|
||||
border-width: thin;
|
||||
}
|
||||
:global(.coorbox) {
|
||||
.coorbox {
|
||||
left: 16px;
|
||||
cursor: pointer;
|
||||
bottom: 16px;
|
||||
}
|
||||
:global(.onlinebox) {
|
||||
.onlinebox {
|
||||
left: 16px;
|
||||
bottom: 57px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
:global(#menubutton) {
|
||||
#menubutton {
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
:global(#menu > div) {
|
||||
#menu > div {
|
||||
z-index: 1;
|
||||
background-color: rgb(213, 238, 255);
|
||||
}
|
||||
|
||||
:global(#helpbutton) {
|
||||
#helpbutton {
|
||||
left: 16px;
|
||||
top: 221px;
|
||||
}
|
||||
:global(#minecraftbutton) {
|
||||
#minecraftbutton {
|
||||
left: 16px;
|
||||
top: 180px;
|
||||
}
|
||||
:global(#settingsbutton) {
|
||||
#settingsbutton {
|
||||
left: 16px;
|
||||
top: 57px;
|
||||
}
|
||||
:global(#loginbutton) {
|
||||
#loginbutton {
|
||||
left: 16px;
|
||||
top: 98px;
|
||||
}
|
||||
:global(#downloadbutton) {
|
||||
#downloadbutton {
|
||||
left: 16px;
|
||||
top: 139px;
|
||||
}
|
||||
:global(#globebutton) {
|
||||
#globebutton {
|
||||
left: 98px;
|
||||
top: 16px;
|
||||
}
|
||||
:global(#voxelbutton) {
|
||||
#voxelbutton {
|
||||
left: 180px;
|
||||
top: 16px;
|
||||
}
|
||||
:global(#canvasbutton) {
|
||||
#canvasbutton {
|
||||
left: 57px;
|
||||
top: 16px;
|
||||
}
|
||||
:global(#minecrafttpbutton) {
|
||||
#minecrafttpbutton {
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
:global(#palselbutton) {
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
#palselbutton {
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
:global(#chatbutton) {
|
||||
#chatbutton {
|
||||
bottom: 16px;
|
||||
right: 57px;
|
||||
}
|
||||
|
||||
:global(#historyselect) {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 70px;
|
||||
width: 140px;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
#historyselect {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 70px;
|
||||
width: 140px;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
:global(.hsar) {
|
||||
|
||||
.hsar {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:global(.Modal) {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
background: rgb(255, 255, 255) none repeat scroll 0% 0%;
|
||||
overflow-y: auto;
|
||||
border-radius: 4px;
|
||||
outline: currentcolor none medium;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 80%;
|
||||
max-height: 900px;
|
||||
width: 70%;
|
||||
transition: all 0.5s ease 0s;
|
||||
.Modal {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
background: rgb(255, 255, 255) none repeat scroll 0% 0%;
|
||||
overflow-y: auto;
|
||||
border-radius: 4px;
|
||||
outline: currentcolor none medium;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 80%;
|
||||
max-height: 900px;
|
||||
width: 70%;
|
||||
transition: all 0.5s ease 0s;
|
||||
}
|
||||
|
||||
.modaltext, .modalcotext {
|
||||
color: hsla(218, 5%, 47%, .6);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.modaltext {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modaltitle {
|
||||
color: #4f545c;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
margin-left: 0;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modaldesc {
|
||||
box-sizing: border-box;
|
||||
flex: 1 1 auto;
|
||||
color: hsla(218, 5%, 47%, .6);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.modaldivider {
|
||||
box-sizing: border-box;
|
||||
margin-top: 20px;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: hsla(216, 4%, 74%, .3);
|
||||
}
|
||||
|
||||
.modalinfo {
|
||||
color: #4f545c;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modalcvtext {
|
||||
color: hsla(218, 5%, 47%, .6);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.ModalClose {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 0 0 36px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
background-color: #f6f6f7;
|
||||
border-color: #dcddde;
|
||||
top: 30px;
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
@media (max-width: 604px) {
|
||||
:global(.Modal) {
|
||||
.Modal {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
|
@ -235,7 +323,7 @@ kbd {
|
|||
padding: 5%;
|
||||
}
|
||||
}
|
||||
:global(.Overlay) {
|
||||
.Overlay {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
|
@ -245,54 +333,51 @@ kbd {
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
:global(.chatbox div .chatarea ) {
|
||||
.chatbox div .chatarea {
|
||||
height: 174px;
|
||||
}
|
||||
:global(.chatarea) {
|
||||
.chatarea {
|
||||
padding: 3px 3px 0px 3px;
|
||||
margin: 0px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
height: 95%;
|
||||
}
|
||||
:global(.Modal div chatarea) {
|
||||
max-height: 600px;
|
||||
}
|
||||
:global(.chatinput) {
|
||||
.chatinput {
|
||||
height: 22px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
:global(.chatname) {
|
||||
.chatname {
|
||||
color: #4B0000;
|
||||
font-size: 13px;
|
||||
user-select: all;
|
||||
}
|
||||
:global(.chatmsg) {
|
||||
.chatmsg {
|
||||
color: #030303;
|
||||
font-size: 13px;
|
||||
user-select: text;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:global(.usermessages) {
|
||||
.usermessages {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
:global(.stattext) {
|
||||
.stattext {
|
||||
font-size: 18px;
|
||||
}
|
||||
:global(.statvalue) {
|
||||
.statvalue {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #2d0045;
|
||||
}
|
||||
|
||||
:global(.pressed) {
|
||||
.pressed {
|
||||
box-shadow:0 0 3px 2px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
:global(.notifyboxvis), :global(.notifyboxhid) {
|
||||
.notifyboxvis, .notifyboxhid {
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
position: absolute;
|
||||
top: 57px;
|
||||
|
@ -313,18 +398,18 @@ kbd {
|
|||
z-index: 2;
|
||||
}
|
||||
|
||||
:global(.notifyboxvis) {
|
||||
.notifyboxvis {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: visibility 0s, opacity 0.5s linear;
|
||||
}
|
||||
:global(.notifyboxhid) {
|
||||
.notifyboxhid {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility 0.5s, opacity 0.5s linear;
|
||||
}
|
||||
|
||||
:global(.cooldownbox) {
|
||||
.cooldownbox {
|
||||
top: 16px;
|
||||
width: 48px;
|
||||
left: 0px;
|
||||
|
@ -334,18 +419,18 @@ kbd {
|
|||
z-index: 2;
|
||||
}
|
||||
|
||||
:global(.actionbuttons) {
|
||||
.actionbuttons {
|
||||
vertical-align: text-bottom;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:global(.actionbuttons:hover) {
|
||||
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
|
||||
background-color: #d2d2d2cc;
|
||||
}
|
||||
|
||||
:global(.palettebox) {
|
||||
.palettebox {
|
||||
z-index: 1;
|
||||
bottom: 59px;
|
||||
padding: 3px;
|
||||
|
@ -355,8 +440,8 @@ kbd {
|
|||
margin-right: auto;
|
||||
}
|
||||
|
||||
:global(#colors) :global(.selected),
|
||||
:global(#colors) span:hover {
|
||||
#colors .selected,
|
||||
#colors span:hover {
|
||||
z-index: 2 !important;
|
||||
outline: rgb(234, 234, 234) solid 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.80) 0px 0px 5px 2px;
|
||||
|
@ -365,7 +450,7 @@ kbd {
|
|||
transform: scale(1.10,1.10); /* Standard syntax */
|
||||
}
|
||||
|
||||
:global(#outstreamContainer) {
|
||||
#outstreamContainer {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
|
@ -378,6 +463,6 @@ kbd {
|
|||
z-index: 9000;
|
||||
}
|
||||
|
||||
:global(.grecaptcha-badge) {
|
||||
.grecaptcha-badge {
|
||||
visibility: hidden;
|
||||
}
|
|
@ -6,13 +6,13 @@ body {
|
|||
font-family: Montserrat,sans-serif;
|
||||
}
|
||||
|
||||
:global(.tm) {
|
||||
.tm {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
:global(.webgl-error) {
|
||||
.webgl-error {
|
||||
font: 15px/30px monospace;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
|
@ -20,12 +20,12 @@ body {
|
|||
}
|
||||
|
||||
|
||||
:global(.webgl-error) a {
|
||||
.webgl-error a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
:global(#coorbox) {
|
||||
#coorbox {
|
||||
position: absolute;
|
||||
background-color: hsla(0,0%,89%,.8);
|
||||
color: #000;
|
||||
|
@ -42,7 +42,7 @@ body {
|
|||
}
|
||||
|
||||
|
||||
:global(#info) {
|
||||
#info {
|
||||
font-size: 13px;
|
||||
position: absolute;
|
||||
background-color: hsla(0,0%,89%,.8);
|
||||
|
@ -59,7 +59,7 @@ body {
|
|||
top: 16px
|
||||
}
|
||||
|
||||
:global(#loading) {
|
||||
#loading {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
471
src/styles/light-round.css
Normal file
471
src/styles/light-round.css
Normal file
|
@ -0,0 +1,471 @@
|
|||
body {
|
||||
margin: 0;
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
user-select: none;
|
||||
background: white;
|
||||
}
|
||||
|
||||
html, body {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* https://github.com/benweet/stackedit/issues/212
|
||||
*/
|
||||
kbd {
|
||||
padding: 0.1em 0.6em;
|
||||
border: 1px solid #ccc;
|
||||
font-size: 11px;
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
background-color: #f7f7f7;
|
||||
color: #333;
|
||||
-moz-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
-webkit-box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
box-shadow: 0 1px 0px rgba(0, 0, 0, 0.2),0 0 0 2px #ffffff inset;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
display: inline-block;
|
||||
margin: 0 0.1em;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
line-height: 1.4;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.modallink {
|
||||
text-decoration: none;
|
||||
color: #428bca;
|
||||
cursor: pointer;
|
||||
}
|
||||
.modallink:hover){
|
||||
font-weight: bold;
|
||||
color: #226baa;
|
||||
}
|
||||
|
||||
.inarea {
|
||||
border-style: solid;
|
||||
border-color: #d5d5d5;
|
||||
padding: 4px;
|
||||
margin-top: 4px;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
.tab-list {
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.tab-list-item {
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
margin-bottom: -1px;
|
||||
padding: 0.5rem 0.75rem;
|
||||
}
|
||||
|
||||
.tab-list-active {
|
||||
background-color: white;
|
||||
border: solid #ccc;
|
||||
border-width: 1px 1px 0 1px;
|
||||
}
|
||||
|
||||
table {
|
||||
font-family: arial, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td, th {
|
||||
border: 1px solid #dddddd;
|
||||
text-align: left;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #dddddd;
|
||||
}
|
||||
|
||||
.chatbox {
|
||||
position: absolute;
|
||||
background-color: rgba(226, 226, 226, 0.92);
|
||||
width: 350px;
|
||||
height: 200px;
|
||||
bottom: 16px;
|
||||
right: 98px;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
}
|
||||
|
||||
.actionbuttons, .coorbox, .onlinebox, .cooldownbox, .palettebox {
|
||||
position: absolute;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 36px;
|
||||
height: 36px;
|
||||
width: auto;
|
||||
padding: 0 16px;
|
||||
border: solid black;
|
||||
border-radius: 21px;
|
||||
border-width: thin;
|
||||
}
|
||||
.coorbox {
|
||||
left: 16px;
|
||||
cursor: pointer;
|
||||
bottom: 16px;
|
||||
}
|
||||
.onlinebox {
|
||||
left: 16px;
|
||||
bottom: 57px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#menubutton {
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
}
|
||||
|
||||
#menu > div {
|
||||
z-index: 1;
|
||||
background-color: rgb(213, 238, 255);
|
||||
}
|
||||
|
||||
#helpbutton {
|
||||
left: 16px;
|
||||
top: 221px;
|
||||
}
|
||||
#minecraftbutton {
|
||||
left: 16px;
|
||||
top: 180px;
|
||||
}
|
||||
#settingsbutton {
|
||||
left: 16px;
|
||||
top: 57px;
|
||||
}
|
||||
#loginbutton {
|
||||
left: 16px;
|
||||
top: 98px;
|
||||
}
|
||||
#downloadbutton {
|
||||
left: 16px;
|
||||
top: 139px;
|
||||
}
|
||||
#globebutton {
|
||||
left: 98px;
|
||||
top: 16px;
|
||||
}
|
||||
#voxelbutton {
|
||||
left: 180px;
|
||||
top: 16px;
|
||||
}
|
||||
#canvasbutton {
|
||||
left: 57px;
|
||||
top: 16px;
|
||||
}
|
||||
#minecrafttpbutton {
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
#palselbutton {
|
||||
bottom: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
#chatbutton {
|
||||
bottom: 16px;
|
||||
right: 57px;
|
||||
}
|
||||
|
||||
#historyselect {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 70px;
|
||||
width: 140px;
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
text-align: center;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hsar {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.Modal {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
background: rgb(255, 255, 255) none repeat scroll 0% 0%;
|
||||
overflow-y: auto;
|
||||
border-radius: 4px;
|
||||
outline: currentcolor none medium;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 80%;
|
||||
max-height: 900px;
|
||||
width: 70%;
|
||||
transition: all 0.5s ease 0s;
|
||||
border-radius: 21px;
|
||||
}
|
||||
|
||||
.modaltext, .modalcotext {
|
||||
color: hsla(218, 5%, 47%, .6);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.modaltext {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modaltitle {
|
||||
color: #4f545c;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
margin-left: 0;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.modaldesc {
|
||||
box-sizing: border-box;
|
||||
flex: 1 1 auto;
|
||||
color: hsla(218, 5%, 47%, .6);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.modaldivider {
|
||||
box-sizing: border-box;
|
||||
margin-top: 20px;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: hsla(216, 4%, 74%, .3);
|
||||
}
|
||||
|
||||
.modalinfo {
|
||||
color: #4f545c;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
text-align: inherit;
|
||||
float: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.modalcvtext {
|
||||
color: hsla(218, 5%, 47%, .6);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 3px;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.ModalClose {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex: 0 0 36px;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
background-color: #f6f6f7;
|
||||
border-color: #dcddde;
|
||||
top: 30px;
|
||||
right: 40px;
|
||||
}
|
||||
|
||||
@media (max-width: 604px) {
|
||||
.Modal {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
height: 95%;
|
||||
width: 90%;
|
||||
transform: none;
|
||||
max-width: none;
|
||||
max-height: none;
|
||||
padding: 5%;
|
||||
}
|
||||
}
|
||||
.Overlay {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: rgba(255, 255, 255, 0.75);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.chatbox div .chatarea {
|
||||
height: 174px;
|
||||
}
|
||||
.chatarea {
|
||||
padding: 3px 3px 0px 3px;
|
||||
margin: 0px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
height: 95%;
|
||||
}
|
||||
.chatinput {
|
||||
height: 22px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.chatname {
|
||||
color: #4B0000;
|
||||
font-size: 13px;
|
||||
user-select: all;
|
||||
}
|
||||
.chatmsg {
|
||||
color: #030303;
|
||||
font-size: 13px;
|
||||
user-select: text;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.usermessages {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
.stattext {
|
||||
font-size: 18px;
|
||||
}
|
||||
.statvalue {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #2d0045;
|
||||
}
|
||||
|
||||
.pressed {
|
||||
box-shadow:0 0 3px 2px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.notifyboxvis, .notifyboxhid {
|
||||
background-color: rgba(226, 226, 226, 0.80);
|
||||
position: absolute;
|
||||
top: 57px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
height: 30px;
|
||||
width: 20px;
|
||||
color: black;
|
||||
font-size: 14px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border: solid black;
|
||||
border-width: thin;
|
||||
padding: 0 24px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.notifyboxvis {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: visibility 0s, opacity 0.5s linear;
|
||||
}
|
||||
.notifyboxhid {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility 0.5s, opacity 0.5s linear;
|
||||
}
|
||||
|
||||
.cooldownbox {
|
||||
top: 16px;
|
||||
width: 48px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.actionbuttons {
|
||||
vertical-align: text-bottom;
|
||||
cursor: pointer;
|
||||
width: 36px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
|
||||
background-color: #d2d2d2cc;
|
||||
}
|
||||
|
||||
.palettebox {
|
||||
z-index: 1;
|
||||
bottom: 59px;
|
||||
padding: 3px;
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#colors .selected,
|
||||
#colors span:hover {
|
||||
z-index: 2 !important;
|
||||
outline: rgb(234, 234, 234) solid 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.80) 0px 0px 5px 2px;
|
||||
-ms-transform: scale(1.10,1.10); /* IE 9 */
|
||||
-webkit-transform: scale(1.10,1.10); /* Safari */
|
||||
transform: scale(1.10,1.10); /* Standard syntax */
|
||||
}
|
||||
|
||||
#outstreamContainer {
|
||||
position: fixed;
|
||||
display: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: black;
|
||||
z-index: 9000;
|
||||
}
|
||||
|
||||
.grecaptcha-badge {
|
||||
visibility: hidden;
|
||||
}
|
|
@ -159,7 +159,9 @@ class Renderer {
|
|||
canvasSize,
|
||||
) {
|
||||
pixelNotify.updateScale(viewscale);
|
||||
let tiledScale = (viewscale > 0.5) ? 0 : Math.round(Math.log2(viewscale) / 2);
|
||||
let tiledScale = (viewscale > 0.5)
|
||||
? 0
|
||||
: Math.round(Math.log2(viewscale) / 2);
|
||||
tiledScale = 4 ** tiledScale;
|
||||
const tiledZoom = canvasMaxTiledZoom + Math.log2(tiledScale) / 2;
|
||||
const relScale = viewscale / tiledScale;
|
||||
|
@ -174,7 +176,11 @@ class Renderer {
|
|||
updateView(view, canvasSize) {
|
||||
const [x, y] = view;
|
||||
let [cx, cy] = this.centerChunk;
|
||||
const [curcx, curcy] = getTileOfPixel(this.tiledScale, [x, y], canvasSize);
|
||||
const [curcx, curcy] = getTileOfPixel(
|
||||
this.tiledScale,
|
||||
[x, y],
|
||||
canvasSize,
|
||||
);
|
||||
if (cx !== curcx || cy !== curcy) {
|
||||
cx = curcx;
|
||||
cy = curcy;
|
||||
|
@ -233,8 +239,12 @@ class Renderer {
|
|||
return false;
|
||||
}
|
||||
const { width, height } = this.viewport;
|
||||
const CHUNK_RENDER_RADIUS_X = Math.ceil(width / TILE_SIZE / 2 / this.relScale);
|
||||
const CHUNK_RENDER_RADIUS_Y = Math.ceil(height / TILE_SIZE / 2 / this.relScale);
|
||||
const CHUNK_RENDER_RADIUS_X = Math.ceil(
|
||||
width / TILE_SIZE / 2 / this.relScale,
|
||||
);
|
||||
const CHUNK_RENDER_RADIUS_Y = Math.ceil(
|
||||
height / TILE_SIZE / 2 / this.relScale,
|
||||
);
|
||||
const [xc, yc] = this.centerChunk;
|
||||
if (Math.abs(cx - xc)
|
||||
<= CHUNK_RENDER_RADIUS_X && Math.abs(cy - yc)
|
||||
|
@ -450,15 +460,21 @@ class Renderer {
|
|||
viewportCtx.scale(viewscale, viewscale);
|
||||
viewportCtx.drawImage(
|
||||
this.canvas,
|
||||
width / 2 / viewscale - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
||||
height / 2 / viewscale - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
||||
width / 2 / viewscale - CANVAS_WIDTH / 2 + (
|
||||
(cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
||||
height / 2 / viewscale - CANVAS_HEIGHT / 2 + (
|
||||
(cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
||||
);
|
||||
viewportCtx.restore();
|
||||
} else {
|
||||
viewportCtx.drawImage(
|
||||
this.canvas,
|
||||
Math.floor(width / 2 - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - x) * viewscale),
|
||||
Math.floor(height / 2 - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - y) * viewscale),
|
||||
Math.floor(width / 2 - CANVAS_WIDTH / 2
|
||||
+ ((cx + 0.5) * TILE_SIZE / this.tiledScale
|
||||
- canvasCenter - x) * viewscale),
|
||||
Math.floor(height / 2 - CANVAS_HEIGHT / 2
|
||||
+ ((cy + 0.5) * TILE_SIZE / this.tiledScale
|
||||
- canvasCenter - y) * viewscale),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -653,14 +669,18 @@ class Renderer {
|
|||
viewportCtx.scale(viewscale, viewscale);
|
||||
viewportCtx.drawImage(
|
||||
this.canvas,
|
||||
// eslint-disable-next-line max-len
|
||||
width / 2 / viewscale - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
||||
// eslint-disable-next-line max-len
|
||||
height / 2 / viewscale - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
||||
);
|
||||
viewportCtx.restore();
|
||||
} else {
|
||||
viewportCtx.drawImage(
|
||||
this.canvas,
|
||||
// eslint-disable-next-line max-len
|
||||
Math.floor(width / 2 - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x) * viewscale),
|
||||
// eslint-disable-next-line max-len
|
||||
Math.floor(height / 2 - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y) * viewscale),
|
||||
);
|
||||
}
|
||||
|
|
12
src/ui/setStyle.js
Normal file
12
src/ui/setStyle.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
export default function setStyle(style) {
|
||||
const cssUri = window.availableStyles[style];
|
||||
const domStyle = document.getElementById('globcss');
|
||||
const curUri = domStyle.getAttribute('href');
|
||||
if (curUri !== cssUri) {
|
||||
domStyle.setAttribute('href', cssUri);
|
||||
}
|
||||
}
|
|
@ -4,8 +4,11 @@
|
|||
*/
|
||||
|
||||
import configureStore from '../store/configureStore';
|
||||
import setStyle from './setStyle';
|
||||
|
||||
|
||||
const store = configureStore();
|
||||
const store = configureStore(() => {
|
||||
const state = store.getState();
|
||||
setStyle(state.gui.style);
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import run from './run';
|
||||
import clean from './clean';
|
||||
import copy from './copy';
|
||||
import minifyCss from './minifyCss';
|
||||
import bundle from './bundle';
|
||||
|
||||
/**
|
||||
|
@ -20,6 +21,7 @@ import bundle from './bundle';
|
|||
async function build() {
|
||||
await run(clean);
|
||||
await run(copy);
|
||||
await run(minifyCss);
|
||||
await run(bundle);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ function bundle() {
|
|||
fileContent = fileContent.replace(regex, 'core-js/features/set-immediate');
|
||||
fs.writeFileSync(file, fileContent);
|
||||
});
|
||||
console.log('Pathing image-q done');
|
||||
} catch {
|
||||
console.log('Error while patching image-q');
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ import pkg from '../package.json';
|
|||
*/
|
||||
async function copy() {
|
||||
await makeDir('build');
|
||||
await makeDir('build/log');
|
||||
await Promise.all([
|
||||
makeDir('build/log'),
|
||||
copyFile('LICENSE', 'build/LICENSE'),
|
||||
copyDir('public', 'build/public'),
|
||||
copyFile('src/canvases.json', 'build/canvases.json'),
|
||||
|
@ -20,6 +20,7 @@ async function copy() {
|
|||
copyFile('tools/example-ecosystem.yml', 'build/ecosystem.example.yml'),
|
||||
copyFile('tools/example-ecosystem-backup.yml', 'build/ecosystem-backup.example.yml'),
|
||||
]);
|
||||
await makeDir('build/public/assets');
|
||||
}
|
||||
|
||||
export default copy;
|
||||
|
|
43
tools/minifyCss.js
Normal file
43
tools/minifyCss.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import CleanCSS from 'clean-css';
|
||||
import crypto from 'crypto';
|
||||
|
||||
const FOLDER = './src/styles';
|
||||
const FILES = [ 'default.css', 'dark.css', 'light-round.css', 'dark-round.css' ];
|
||||
|
||||
async function minifyCss() {
|
||||
console.log('Minifying css');
|
||||
const assets = {};
|
||||
FILES.forEach((file) => {
|
||||
const input = fs.readFileSync(`${FOLDER}/${file}`, 'utf8');
|
||||
const options = {};
|
||||
const output = new CleanCSS(options).minify(input);
|
||||
if (output.warnings && output.warnings.length > 0) {
|
||||
for (let i = 0; i < output.warnings.length; i += 1) {
|
||||
console.log('\x1b[33m%s\x1b[0m', output.warnings[i]);
|
||||
}
|
||||
}
|
||||
if (output.errors && output.errors.length > 0) {
|
||||
for (let i = 0; i < output.errors.length; i += 1) {
|
||||
console.log('\x1b[31m%s\x1b[0m', output.errors[i]);
|
||||
}
|
||||
throw new Error("Minify CSS Error Occured");
|
||||
}
|
||||
// eslint-disable-next-line max-len
|
||||
console.log('\x1b[33m%s\x1b[0m', `Minified ${file} by ${Math.round(output.stats.efficiency * 100)}%`);
|
||||
const hash = crypto.createHash('md5').update(output.styles).digest('hex');
|
||||
const key = file.substr(0, file.indexOf('.'));
|
||||
const filename = `${key}.${hash.substr(0, 8)}.css`;
|
||||
fs.writeFileSync(`./build/public/assets/${filename}`, output.styles, 'utf8');
|
||||
assets[key] = `/assets/${filename}`;
|
||||
});
|
||||
const json = JSON.stringify(assets);
|
||||
fs.writeFileSync('./build/styleassets.json', json);
|
||||
}
|
||||
|
||||
export default minifyCss;
|
|
@ -44,60 +44,6 @@ const config = {
|
|||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, '../src'),
|
||||
],
|
||||
query: {
|
||||
// https://github.com/babel/babel-loader#options
|
||||
cacheDirectory: isDebug,
|
||||
|
||||
// https://babeljs.io/docs/usage/options/
|
||||
babelrc: false,
|
||||
presets: [
|
||||
// A Babel preset that can automatically determine the Babel plugins and polyfills
|
||||
// https://github.com/babel/babel-preset-env
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: pkg.browserslist,
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: 'usage',
|
||||
corejs: {
|
||||
version: 3,
|
||||
},
|
||||
debug: false,
|
||||
}],
|
||||
"@babel/typescript",
|
||||
// JSX, Flow
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
|
||||
'@babel/react',
|
||||
],
|
||||
plugins: [
|
||||
'@babel/transform-flow-strip-types',
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
'@babel/plugin-proposal-function-sent',
|
||||
'@babel/plugin-proposal-export-namespace-from',
|
||||
'@babel/plugin-proposal-numeric-separator',
|
||||
'@babel/plugin-proposal-throw-expressions',
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
'@babel/proposal-object-rest-spread',
|
||||
// Adds component stack to warning messages
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
|
||||
...isDebug ? ['@babel/transform-react-jsx-source'] : [],
|
||||
// Adds __self attribute to JSX which React will use for some warnings
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
|
||||
...isDebug ? ['@babel/transform-react-jsx-self'] : [],
|
||||
// react-optimize
|
||||
'@babel/transform-react-constant-elements',
|
||||
'@babel/transform-react-inline-elements',
|
||||
'transform-react-remove-prop-types',
|
||||
'transform-react-pure-class-to-function',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
|
@ -133,21 +79,6 @@ const config = {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.tcss/,
|
||||
use: [
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
// CSS Loader https://github.com/webpack/css-loader
|
||||
importLoaders: 1,
|
||||
sourceMap: isDebug,
|
||||
// CSS Modules https://github.com/css-modules/css-modules
|
||||
modules: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.scss/,
|
||||
use: [
|
||||
|
@ -165,20 +96,6 @@ const config = {
|
|||
'sass-loader',
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css/,
|
||||
use: ['style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
// CSS Loader https://github.com/webpack/css-loader
|
||||
sourceMap: isDebug,
|
||||
// CSS Modules https://github.com/css-modules/css-modules
|
||||
modules: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
|
||||
|
@ -242,6 +159,81 @@ const clientConfig = {
|
|||
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].js',
|
||||
},
|
||||
|
||||
module: {
|
||||
...config.module,
|
||||
rules: [
|
||||
...config.module.rules,
|
||||
{
|
||||
test: /\.(js|jsx|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, '../src'),
|
||||
],
|
||||
query: {
|
||||
// https://github.com/babel/babel-loader#options
|
||||
cacheDirectory: isDebug,
|
||||
|
||||
// https://babeljs.io/docs/usage/options/
|
||||
babelrc: false,
|
||||
presets: [
|
||||
// A Babel preset that can automatically determine the Babel plugins and polyfills
|
||||
// https://github.com/babel/babel-preset-env
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: pkg.browserslist,
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: 'usage',
|
||||
corejs: {
|
||||
version: 3,
|
||||
},
|
||||
debug: false,
|
||||
}],
|
||||
"@babel/typescript",
|
||||
// JSX, Flow
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
|
||||
'@babel/react',
|
||||
],
|
||||
plugins: [
|
||||
'@babel/transform-flow-strip-types',
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
'@babel/plugin-proposal-function-sent',
|
||||
'@babel/plugin-proposal-export-namespace-from',
|
||||
'@babel/plugin-proposal-numeric-separator',
|
||||
'@babel/plugin-proposal-throw-expressions',
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
'@babel/proposal-object-rest-spread',
|
||||
// Adds component stack to warning messages
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
|
||||
...isDebug ? ['@babel/transform-react-jsx-source'] : [],
|
||||
// Adds __self attribute to JSX which React will use for some warnings
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
|
||||
...isDebug ? ['@babel/transform-react-jsx-self'] : [],
|
||||
// react-optimize
|
||||
'@babel/transform-react-constant-elements',
|
||||
'@babel/transform-react-inline-elements',
|
||||
'transform-react-remove-prop-types',
|
||||
'transform-react-pure-class-to-function',
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css/,
|
||||
use: ['style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
// CSS Loader https://github.com/webpack/css-loader
|
||||
sourceMap: isDebug,
|
||||
// CSS Modules https://github.com/css-modules/css-modules
|
||||
modules: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// Define free variables
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
||||
|
@ -315,26 +307,85 @@ const webConfig = {
|
|||
...config.module,
|
||||
|
||||
// Override babel-preset-env configuration for Node.js
|
||||
rules: config.module.rules.map((rule) => (rule.loader !== 'babel-loader' ? rule : {
|
||||
...rule,
|
||||
query: {
|
||||
...rule.query,
|
||||
presets: rule.query.presets.map((preset) => (preset[0] !== '@babel/preset-env' ? preset : ['@babel/preset-env', {
|
||||
targets: {
|
||||
node: pkg.engines.node.replace(/^\D+/g, ''),
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false,
|
||||
debug: false,
|
||||
}])),
|
||||
rules: [
|
||||
...config.module.rules,
|
||||
{
|
||||
test: /\.(js|jsx|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, '../src'),
|
||||
],
|
||||
query: {
|
||||
// https://github.com/babel/babel-loader#options
|
||||
cacheDirectory: isDebug,
|
||||
|
||||
// https://babeljs.io/docs/usage/options/
|
||||
babelrc: false,
|
||||
presets: [
|
||||
// A Babel preset that can automatically determine the Babel plugins and polyfills
|
||||
// https://github.com/babel/babel-preset-env
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
node: pkg.engines.node.replace(/^\D+/g, ''),
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: false,
|
||||
corejs: {
|
||||
version: 3,
|
||||
},
|
||||
debug: false,
|
||||
}],
|
||||
"@babel/typescript",
|
||||
// JSX, Flow
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
|
||||
'@babel/react',
|
||||
],
|
||||
plugins: [
|
||||
'@babel/transform-flow-strip-types',
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
'@babel/plugin-proposal-function-sent',
|
||||
'@babel/plugin-proposal-export-namespace-from',
|
||||
'@babel/plugin-proposal-numeric-separator',
|
||||
'@babel/plugin-proposal-throw-expressions',
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
'@babel/proposal-object-rest-spread',
|
||||
// Adds component stack to warning messages
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
|
||||
...isDebug ? ['@babel/transform-react-jsx-source'] : [],
|
||||
// Adds __self attribute to JSX which React will use for some warnings
|
||||
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
|
||||
...isDebug ? ['@babel/transform-react-jsx-self'] : [],
|
||||
// react-optimize
|
||||
'@babel/transform-react-constant-elements',
|
||||
'@babel/transform-react-inline-elements',
|
||||
'transform-react-remove-prop-types',
|
||||
'transform-react-pure-class-to-function',
|
||||
],
|
||||
},
|
||||
},
|
||||
})),
|
||||
{
|
||||
test: /\.css/,
|
||||
use: [
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
// CSS Loader https://github.com/webpack/css-loader
|
||||
importLoaders: 1,
|
||||
sourceMap: isDebug,
|
||||
// CSS Modules https://github.com/css-modules/css-modules
|
||||
modules: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// needed because webpack tries to pack socket.io
|
||||
externals: [
|
||||
/\/proxies\.json$/,
|
||||
/\/canvases\.json$/,
|
||||
/^\.\/styleassets\.json$/,
|
||||
/^\.\/assets\.json$/,
|
||||
(context, request, callback) => {
|
||||
const isExternal = request.match(/^[@a-z][a-z/.\-0-9]*$/i)
|
||||
|
|
|
@ -18,8 +18,6 @@ def on_message(ws, message):
|
|||
x = unpack_from('B', message, 1)[0]
|
||||
y = unpack_from('B', message, 2)[0]
|
||||
a = unpack_from('!h', message, 4)[0]
|
||||
if x != 10000 and y != 10000:
|
||||
return
|
||||
color = int(unpack_from('!B', message, 6)[0])
|
||||
if color == 0:
|
||||
color = 19
|
||||
|
@ -29,6 +27,8 @@ def on_message(ws, message):
|
|||
number = (65520 & a) >> 4
|
||||
x = int(x * 256 + a % 256 - 256 * 256 / 2)
|
||||
y = int(y * 256 + a // 256 + 256 - 256 * 256 / 2)
|
||||
if x != 10000 and y != 10000:
|
||||
return
|
||||
print('Pixel Received: @%s,%s - color %s' % (str(x), str(y), str(color)))
|
||||
|
||||
def on_error(ws, error):
|
||||
|
|
Loading…
Reference in New Issue
Block a user