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`
|
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
|
### Running
|
||||||
|
|
||||||
1. Make sure that mysql and redis are running
|
1. Make sure that mysql and redis are running
|
||||||
|
@ -206,7 +210,7 @@ After=network.target mysql.service redis.service
|
||||||
### Development
|
### 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.
|
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.
|
You can use `npm run babel-node ./your/script.js` to execute a script with local babel.
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# This hook builds pixelplanet after a push, and deploys it
|
# 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)
|
# 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
|
# 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.
|
# 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
|
# This hook just builds the canvas, it does not install new 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
|
|
||||||
#
|
#
|
||||||
#discord webhook for dev canvas
|
#discord webhook for dev canvas
|
||||||
WEBHOOK='https://discordapp.com/api/webhooks/'
|
WEBHOOK='https://discordapp.com/api/webhooks/5440815510.....'
|
||||||
#discord webhook for production canvas
|
#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)
|
#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
|
#folder for dev canvas
|
||||||
DEVFOLDER="pixelplanet-dev"
|
DEVFOLDER="/home/pixelpla/pixelplanet-dev"
|
||||||
#folder for production canvas
|
#folder for production canvas
|
||||||
PFOLDER="pixelplanet"
|
PFOLDER="/home/pixelpla/pixelplanet"
|
||||||
#proxies.json path
|
|
||||||
PROXYFILE="/proxies.json"
|
|
||||||
|
|
||||||
while read oldrev newrev refname
|
while read oldrev newrev refname
|
||||||
do
|
do
|
||||||
|
@ -33,35 +30,40 @@ do
|
||||||
COMMITS=`echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\\n/g'`
|
COMMITS=`echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\\n/g'`
|
||||||
echo "---BUILDING pixelplanet---"
|
echo "---BUILDING pixelplanet---"
|
||||||
cd "$BUILDDIR"
|
cd "$BUILDDIR"
|
||||||
cp "$PROXYFILE" ./src/
|
npm run build
|
||||||
yarn run build --release
|
|
||||||
echo "---RESTARTING CANVAS---"
|
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"
|
#cp ecosystem-production.yml "${PFOLDER}/ecosystem.yml"
|
||||||
cd "$PFOLDER"
|
cd "$PFOLDER"
|
||||||
pm2 stop web
|
pm2 stop web
|
||||||
pm2 start ecosystem.yml
|
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"
|
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
|
else
|
||||||
echo "---UPDATING REPO ON DEV SERVER---"
|
echo "---UPDATING REPO ON DEV SERVER---"
|
||||||
pm2 stop web-dev
|
pm2 stop web-dev
|
||||||
GIT_WORK_TREE="$BUILDDIR" GIT_DIR="${BUILDDIR}/.git" git fetch --all
|
GIT_WORK_TREE="$BUILDDIR" GIT_DIR="${BUILDDIR}/.git" git fetch --all
|
||||||
GIT_WORK_TREE="$BUILDDIR" GIT_DIR="${BUILDDIR}/.git" git reset --hard "origin/$branch"
|
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=`git log --pretty=format:'- %s%b' $newrev ^$oldrev`
|
||||||
COMMITS=`echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\\n/g'`
|
COMMITS=`echo "$COMMITS" | sed ':a;N;$!ba;s/\n/\\\n/g'`
|
||||||
echo "---BUILDING pixelplanet---"
|
echo "---BUILDING pixelplanet---"
|
||||||
cd "$BUILDDIR"
|
cd "$BUILDDIR"
|
||||||
cp "$PROXYFILE" ./src/
|
nice -n 19 npm run build
|
||||||
nice -n 19 yarn run build --release
|
|
||||||
echo "---RESTARTING CANVAS---"
|
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"
|
#cp ecosystem-dev.yml "${DEVFOLDER}/ecosystem.yml"
|
||||||
cd "$DEVFOLDER"
|
cd "$DEVFOLDER"
|
||||||
pm2 start ecosystem.yml
|
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
|
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": {
|
"cli-boxes": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
|
"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-flow": "^7.9.0",
|
||||||
"@babel/preset-react": "^7.9.4",
|
"@babel/preset-react": "^7.9.4",
|
||||||
"@babel/preset-typescript": "^7.9.0",
|
"@babel/preset-typescript": "^7.9.0",
|
||||||
|
"clean-css": "^4.2.3",
|
||||||
"assets-webpack-plugin": "^3.9.12",
|
"assets-webpack-plugin": "^3.9.12",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-loader": "^8.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 {
|
export function toggleOpenMenu(): Action {
|
||||||
return {
|
return {
|
||||||
type: 'TOGGLE_OPEN_MENU',
|
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 {
|
return {
|
||||||
type: 'SHOW_MODAL',
|
type: 'SHOW_MODAL',
|
||||||
modalType,
|
modalType,
|
||||||
modalProps,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ export type Action =
|
||||||
| { type: 'TOGGLE_LIGHT_GRID' }
|
| { type: 'TOGGLE_LIGHT_GRID' }
|
||||||
| { type: 'TOGGLE_OPEN_MENU' }
|
| { type: 'TOGGLE_OPEN_MENU' }
|
||||||
| { type: 'TOGGLE_HISTORICAL_VIEW' }
|
| { type: 'TOGGLE_HISTORICAL_VIEW' }
|
||||||
|
| { type: 'SELECT_STYLE', style: string }
|
||||||
| { type: 'SET_NOTIFICATION', notification: string }
|
| { type: 'SET_NOTIFICATION', notification: string }
|
||||||
| { type: 'UNSET_NOTIFICATION' }
|
| { type: 'UNSET_NOTIFICATION' }
|
||||||
| { type: 'SET_PLACE_ALLOWED', placeAllowed: boolean }
|
| { type: 'SET_PLACE_ALLOWED', placeAllowed: boolean }
|
||||||
|
@ -78,15 +79,10 @@ export type Action =
|
||||||
| { type: 'SET_MINECRAFT_NAME', minecraftname: string }
|
| { type: 'SET_MINECRAFT_NAME', minecraftname: string }
|
||||||
| { type: 'SET_MAILREG', mailreg: boolean }
|
| { type: 'SET_MAILREG', mailreg: boolean }
|
||||||
| { type: 'REM_FROM_MESSAGES', message: string }
|
| { type: 'REM_FROM_MESSAGES', message: string }
|
||||||
| { type: 'SHOW_MODAL', modalType: string, modalProps: obj }
|
| { type: 'SHOW_MODAL', modalType: string }
|
||||||
| { type: 'HIDE_MODAL' }
|
| { type: 'HIDE_MODAL' }
|
||||||
| { type: 'RELOAD_URL' }
|
| { type: 'RELOAD_URL' }
|
||||||
| { type: 'SET_HISTORICAL_TIME', date: string, time: string }
|
| { type: 'SET_HISTORICAL_TIME', date: string, time: string }
|
||||||
| { type: 'ON_VIEW_FINISH_CHANGE' };
|
| { type: 'ON_VIEW_FINISH_CHANGE' };
|
||||||
export type PromiseAction = Promise<Action>;
|
export type PromiseAction = Promise<Action>;
|
||||||
export type Dispatch = (action: Action
|
|
||||||
| ThunkAction
|
|
||||||
| PromiseAction
|
|
||||||
| Array<Action>) => any;
|
|
||||||
export type GetState = () => State;
|
export type GetState = () => State;
|
||||||
export type ThunkAction = (dispatch: Dispatch, getState: GetState) => any;
|
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
/* @flow */
|
/* @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 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 initAds, { requestAds } from './ui/ads';
|
||||||
import onKeyPress from './controls/keypress';
|
import onKeyPress from './controls/keypress';
|
||||||
|
@ -24,7 +21,7 @@ import {
|
||||||
import store from './ui/store';
|
import store from './ui/store';
|
||||||
|
|
||||||
|
|
||||||
import App from './components/App';
|
import renderApp from './components/App';
|
||||||
|
|
||||||
import { initRenderer, getRenderer } from './ui/renderer';
|
import { initRenderer, getRenderer } from './ui/renderer';
|
||||||
import ProtocolClient from './socket/ProtocolClient';
|
import ProtocolClient from './socket/ProtocolClient';
|
||||||
|
@ -97,12 +94,7 @@ function init() {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
ReactDOM.render(
|
renderApp(document.getElementById('app'));
|
||||||
<Provider store={store}>
|
|
||||||
<App />
|
|
||||||
</Provider>,
|
|
||||||
document.getElementById('app'),
|
|
||||||
);
|
|
||||||
|
|
||||||
document.addEventListener('keydown', onKeyPress, false);
|
document.addEventListener('keydown', onKeyPress, false);
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Provider } from 'react-redux';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
import { IconContext } from 'react-icons';
|
import { IconContext } from 'react-icons';
|
||||||
|
|
||||||
|
import store from '../ui/store';
|
||||||
|
|
||||||
import CoordinatesBox from './CoordinatesBox';
|
import CoordinatesBox from './CoordinatesBox';
|
||||||
import CanvasSwitchButton from './CanvasSwitchButton';
|
import CanvasSwitchButton from './CanvasSwitchButton';
|
||||||
import OnlineBox from './OnlineBox';
|
import OnlineBox from './OnlineBox';
|
||||||
|
@ -17,12 +21,8 @@ import ReCaptcha from './ReCaptcha';
|
||||||
import ExpandMenuButton from './ExpandMenuButton';
|
import ExpandMenuButton from './ExpandMenuButton';
|
||||||
import ModalRoot from './ModalRoot';
|
import ModalRoot from './ModalRoot';
|
||||||
|
|
||||||
import baseCss from './base.tcss';
|
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<div>
|
<div>
|
||||||
{/* eslint-disable-next-line react/no-danger */}
|
|
||||||
<style dangerouslySetInnerHTML={{ __html: baseCss }} />
|
|
||||||
<div id="outstreamContainer" />
|
<div id="outstreamContainer" />
|
||||||
<ReCaptcha />
|
<ReCaptcha />
|
||||||
<IconContext.Provider value={{ style: { verticalAlign: 'middle' } }}>
|
<IconContext.Provider value={{ style: { verticalAlign: 'middle' } }}>
|
||||||
|
@ -39,4 +39,13 @@ const App = () => (
|
||||||
</div>
|
</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';
|
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 = {
|
const buttonStyle = {
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
marginBottom: 8,
|
marginBottom: 8,
|
||||||
|
@ -71,29 +39,29 @@ const CanvasItem = ({ canvasId, canvas, changeCanvas }) => (
|
||||||
alt="preview"
|
alt="preview"
|
||||||
src={`/preview${canvasId}.png`}
|
src={`/preview${canvasId}.png`}
|
||||||
/>
|
/>
|
||||||
<p style={textStyle}>
|
<p className="modalcvtext">
|
||||||
<span style={titleStyle}>{canvas.title}</span><br />
|
<span className="modaltitle">{canvas.title}</span><br />
|
||||||
<span style={infoStyle}>{canvas.desc}</span><br />
|
<span className="modalinfo">{canvas.desc}</span><br />
|
||||||
Cooldown:
|
Cooldown:
|
||||||
|
|
||||||
<span style={infoStyle}>
|
<span className="modalinfo">
|
||||||
{(canvas.bcd !== canvas.pcd)
|
{(canvas.bcd !== canvas.pcd)
|
||||||
? <span> {canvas.bcd / 1000}s / {canvas.pcd / 1000}s</span>
|
? <span> {canvas.bcd / 1000}s / {canvas.pcd / 1000}s</span>
|
||||||
: <span> {canvas.bcd / 1000}s</span>}
|
: <span> {canvas.bcd / 1000}s</span>}
|
||||||
</span><br />
|
</span><br />
|
||||||
Stacking till
|
Stacking till
|
||||||
<span style={infoStyle}> {canvas.cds / 1000}s</span><br />
|
<span className="modalinfo"> {canvas.cds / 1000}s</span><br />
|
||||||
Ranked:
|
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}
|
{(canvas.req !== -1) ? <span>Requirements:<br /></span> : null}
|
||||||
<span style={infoStyle}>
|
<span className="modalinfo">
|
||||||
{(canvas.req !== -1) ? <span>User Account </span> : null}
|
{(canvas.req !== -1) ? <span>User Account </span> : null}
|
||||||
{(canvas.req > 0) ? <span> and {canvas.req} Pixels set</span> : null}
|
{(canvas.req > 0) ? <span> and {canvas.req} Pixels set</span> : null}
|
||||||
</span>
|
</span>
|
||||||
{(canvas.req !== -1) ? <br /> : null}
|
{(canvas.req !== -1) ? <br /> : null}
|
||||||
Dimensions:
|
Dimensions:
|
||||||
<span style={infoStyle}> {canvas.size} x {canvas.size}
|
<span className="modalinfo"> {canvas.size} x {canvas.size}
|
||||||
{(canvas.v)
|
{(canvas.v)
|
||||||
? <span> x {THREE_CANVAS_HEIGHT} Voxels</span>
|
? <span> x {THREE_CANVAS_HEIGHT} Voxels</span>
|
||||||
: <span> Pixels</span>}
|
: <span> Pixels</span>}
|
||||||
|
|
|
@ -15,19 +15,6 @@ import CanvasItem from './CanvasItem';
|
||||||
import type { State } from '../reducers';
|
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 }) => (
|
const CanvasSelectModal = ({ canvases }) => (
|
||||||
<Modal title="Canvas Selection">
|
<Modal title="Canvas Selection">
|
||||||
<p style={{
|
<p style={{
|
||||||
|
@ -37,7 +24,7 @@ const CanvasSelectModal = ({ canvases }) => (
|
||||||
paddingTop: 20,
|
paddingTop: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p style={textStyle}>
|
<p className="modaltext">
|
||||||
Select the canvas you want to use.
|
Select the canvas you want to use.
|
||||||
Every canvas is unique and has different palettes,
|
Every canvas is unique and has different palettes,
|
||||||
cooldown and requirements.
|
cooldown and requirements.
|
||||||
|
|
|
@ -9,24 +9,19 @@ import { FaGlobe } from 'react-icons/fa';
|
||||||
|
|
||||||
import { showCanvasSelectionModal } from '../actions';
|
import { showCanvasSelectionModal } from '../actions';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
|
||||||
|
|
||||||
|
|
||||||
const CanvasSwitchButton = ({ open }) => (
|
const CanvasSwitchButton = ({ open }) => (
|
||||||
<div
|
<div
|
||||||
id="canvasbutton"
|
id="canvasbutton"
|
||||||
className="actionbuttons"
|
className="actionbuttons"
|
||||||
onClick={open}
|
onClick={open}
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
>
|
>
|
||||||
<FaGlobe />
|
<FaGlobe />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
function mapStateToProps(state: State) {
|
|
||||||
const { canvasId } = state.canvas;
|
|
||||||
return { canvasId };
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
open() {
|
open() {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
validateName, validateEMail, validatePassword, parseAPIresponse,
|
validateEMail, validatePassword, parseAPIresponse,
|
||||||
} from '../utils/validation';
|
} from '../utils/validation';
|
||||||
|
|
||||||
function validate(email, password) {
|
function validate(email, password) {
|
||||||
|
@ -19,7 +19,7 @@ function validate(email, password) {
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submit_mailchange(email, password) {
|
async function submitMailchange(email, password) {
|
||||||
const body = JSON.stringify({
|
const body = JSON.stringify({
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
|
@ -63,7 +63,7 @@ class ChangeMail extends React.Component {
|
||||||
if (errors.length > 0) return;
|
if (errors.length > 0) return;
|
||||||
this.setState({ submitting: true });
|
this.setState({ submitting: true });
|
||||||
|
|
||||||
const { errors: resperrors } = await submit_mailchange(email, password);
|
const { errors: resperrors } = await submitMailchange(email, password);
|
||||||
if (resperrors) {
|
if (resperrors) {
|
||||||
this.setState({
|
this.setState({
|
||||||
errors: resperrors,
|
errors: resperrors,
|
||||||
|
@ -77,15 +77,24 @@ class ChangeMail extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.success) {
|
const { success } = this.state;
|
||||||
|
const { done } = this.props;
|
||||||
|
if (success) {
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<p className="modalmessage">Changed Mail successfully. We sent you a verification mail, please verify your new mail adress.</p>
|
<p
|
||||||
<button type="button" onClick={this.props.done}>Close</button>
|
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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const { errors } = this.state;
|
const {
|
||||||
|
errors, password, email, submitting,
|
||||||
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
|
@ -93,21 +102,23 @@ class ChangeMail extends React.Component {
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
value={this.state.password}
|
value={password}
|
||||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
value={this.state.email}
|
value={email}
|
||||||
onChange={(evt) => this.setState({ email: evt.target.value })}
|
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="New Mail"
|
placeholder="New Mail"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<button type="submit">{(this.state.submitting) ? '...' : 'Save'}</button>
|
<button type="submit">
|
||||||
<button type="button" onClick={this.props.done}>Cancel</button>
|
{(submitting) ? '...' : 'Save'}
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={done}>Cancel</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,7 +16,7 @@ function validate(name) {
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submit_namechange(name) {
|
async function submitNamechange(name) {
|
||||||
const body = JSON.stringify({
|
const body = JSON.stringify({
|
||||||
name,
|
name,
|
||||||
});
|
});
|
||||||
|
@ -57,7 +57,7 @@ class ChangeName extends React.Component {
|
||||||
if (errors.length > 0) return;
|
if (errors.length > 0) return;
|
||||||
this.setState({ submitting: true });
|
this.setState({ submitting: true });
|
||||||
|
|
||||||
const { errors: resperrors } = await submit_namechange(name);
|
const { errors: resperrors } = await submitNamechange(name);
|
||||||
if (resperrors) {
|
if (resperrors) {
|
||||||
this.setState({
|
this.setState({
|
||||||
errors: resperrors,
|
errors: resperrors,
|
||||||
|
@ -65,12 +65,14 @@ class ChangeName extends React.Component {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.props.set_name(name);
|
const { setName, done } = this.props;
|
||||||
this.props.done();
|
setName(name);
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { errors } = this.state;
|
const { errors, name, submitting } = this.state;
|
||||||
|
const { done } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
|
@ -78,14 +80,16 @@ class ChangeName extends React.Component {
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
value={this.state.name}
|
value={name}
|
||||||
onChange={(evt) => this.setState({ name: evt.target.value })}
|
onChange={(evt) => this.setState({ name: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="New Username"
|
placeholder="New Username"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<button type="submit">{(this.state.submitting) ? '...' : 'Save'}</button>
|
<button type="submit">
|
||||||
<button type="button" onClick={this.props.done}>Cancel</button>
|
{(submitting) ? '...' : 'Save'}
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={done}>Cancel</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,27 +6,27 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { validatePassword, parseAPIresponse } from '../utils/validation';
|
import { validatePassword, parseAPIresponse } from '../utils/validation';
|
||||||
|
|
||||||
function validate(mailreg, password, new_password, confirm_password) {
|
function validate(mailreg, password, newPassword, confirmPassword) {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
if (mailreg) {
|
if (mailreg) {
|
||||||
const oldpasserror = validatePassword(password);
|
const oldpasserror = validatePassword(password);
|
||||||
if (oldpasserror) errors.push(oldpasserror);
|
if (oldpasserror) errors.push(oldpasserror);
|
||||||
}
|
}
|
||||||
if (new_password != confirm_password) {
|
if (newPassword !== confirmPassword) {
|
||||||
errors.push('Passwords do not match.');
|
errors.push('Passwords do not match.');
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
const passerror = validatePassword(new_password);
|
const passerror = validatePassword(newPassword);
|
||||||
if (passerror) errors.push(passerror);
|
if (passerror) errors.push(passerror);
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submit_passwordchange(new_password, password) {
|
async function submitPasswordChange(newPassword, password) {
|
||||||
const body = JSON.stringify({
|
const body = JSON.stringify({
|
||||||
password,
|
password,
|
||||||
new_password,
|
newPassword,
|
||||||
});
|
});
|
||||||
const response = await fetch('./api/auth/change_passwd', {
|
const response = await fetch('./api/auth/change_passwd', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -46,8 +46,8 @@ class ChangePassword extends React.Component {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
password: '',
|
password: '',
|
||||||
new_password: '',
|
newPassword: '',
|
||||||
confirm_password: '',
|
confirmPassword: '',
|
||||||
success: false,
|
success: false,
|
||||||
submitting: false,
|
submitting: false,
|
||||||
|
|
||||||
|
@ -61,17 +61,26 @@ class ChangePassword extends React.Component {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
password, new_password, confirm_password, submitting,
|
password, newPassword, confirmPassword, submitting,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
if (submitting) return;
|
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 });
|
this.setState({ errors });
|
||||||
if (errors.length > 0) return;
|
if (errors.length > 0) return;
|
||||||
this.setState({ submitting: true });
|
this.setState({ submitting: true });
|
||||||
|
|
||||||
const { errors: resperrors } = await submit_passwordchange(new_password, password);
|
const { errors: resperrors } = await submitPasswordChange(
|
||||||
|
newPassword,
|
||||||
|
password,
|
||||||
|
);
|
||||||
if (resperrors) {
|
if (resperrors) {
|
||||||
this.setState({
|
this.setState({
|
||||||
errors: resperrors,
|
errors: resperrors,
|
||||||
|
@ -85,25 +94,34 @@ class ChangePassword extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
if (this.state.success) {
|
const { success } = this.state;
|
||||||
|
if (success) {
|
||||||
|
const { done } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<p className="modalmessage">Changed Password successfully.</p>
|
<p className="modalmessage">Changed Password successfully.</p>
|
||||||
<button type="button" onClick={this.props.done}>Close</button>
|
<button type="button" onClick={done}>Close</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const { errors } = this.state;
|
const {
|
||||||
|
errors,
|
||||||
|
password,
|
||||||
|
newPassword,
|
||||||
|
confirmPassword,
|
||||||
|
submitting,
|
||||||
|
} = this.state;
|
||||||
|
const { cancel, mailreg } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="inarea">
|
<div className="inarea">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map((error) => (
|
{errors.map((error) => (
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
{(this.props.mailreg)
|
{(mailreg)
|
||||||
&& (
|
&& (
|
||||||
<input
|
<input
|
||||||
value={this.state.password}
|
value={password}
|
||||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Old Password"
|
placeholder="Old Password"
|
||||||
|
@ -111,21 +129,25 @@ class ChangePassword extends React.Component {
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
value={this.state.new_password}
|
value={newPassword}
|
||||||
onChange={(evt) => this.setState({ new_password: evt.target.value })}
|
onChange={(evt) => this.setState({ newPassword: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="New Password"
|
placeholder="New Password"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<input
|
<input
|
||||||
value={this.state.confirm_password}
|
value={confirmPassword}
|
||||||
onChange={(evt) => this.setState({ confirm_password: evt.target.value })}
|
onChange={(evt) => this.setState({
|
||||||
|
confirmPassword: evt.target.value,
|
||||||
|
})}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Confirm New Password"
|
placeholder="Confirm New Password"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<button type="submit">{(this.state.submitting) ? '...' : 'Save'}</button>
|
<button type="submit">
|
||||||
<button type="button" onClick={this.props.cancel}>Cancel</button>
|
{(submitting) ? '...' : 'Save'}
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={cancel}>Cancel</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,23 +9,10 @@ import Modal from './Modal';
|
||||||
import Chat from './Chat';
|
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 = () => (
|
const ChatModal = () => (
|
||||||
<Modal title="Chat">
|
<Modal title="Chat">
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
<p style={textStyle}>Chat with other people here</p>
|
<p className="modaltext">Chat with other people here</p>
|
||||||
</p>
|
</p>
|
||||||
<div className="inarea" style={{ height: '65%' }}>
|
<div className="inarea" style={{ height: '65%' }}>
|
||||||
<Chat />
|
<Chat />
|
||||||
|
|
|
@ -12,28 +12,6 @@ import type { State } from '../reducers';
|
||||||
import printGIMPPalette from '../core/exportGPL';
|
import printGIMPPalette from '../core/exportGPL';
|
||||||
import { copyCanvasToClipboard } from '../utils/clipboard';
|
import { copyCanvasToClipboard } from '../utils/clipboard';
|
||||||
|
|
||||||
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() {
|
function downloadOutput() {
|
||||||
const output = document.getElementById('imgoutput');
|
const output = document.getElementById('imgoutput');
|
||||||
|
@ -284,7 +262,7 @@ function Converter({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
<p style={textStyle}>Choose Canvas:
|
<p className="modalcotext">Choose Canvas:
|
||||||
<select
|
<select
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const sel = e.target;
|
const sel = e.target;
|
||||||
|
@ -307,8 +285,8 @@ function Converter({
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
<h3 style={titleStyle}>Palette Download</h3>
|
<h3 className="modaltitle">Palette Download</h3>
|
||||||
<p style={textStyle}>
|
<p className="modalcotext">
|
||||||
Palette for <a href="https://www.gimp.org">GIMP</a>:
|
Palette for <a href="https://www.gimp.org">GIMP</a>:
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -329,8 +307,8 @@ function Converter({
|
||||||
<p>Credit for the Palette of the Moon goes to
|
<p>Credit for the Palette of the Moon goes to
|
||||||
<a href="https://twitter.com/starhousedev">starhouse</a>.</p>
|
<a href="https://twitter.com/starhousedev">starhouse</a>.</p>
|
||||||
</p>
|
</p>
|
||||||
<h3 style={titleStyle}>Image Converter</h3>
|
<h3 className="modaltitle">Image Converter</h3>
|
||||||
<p style={textStyle}>Convert an image to canvas colors</p>
|
<p className="modalcotext">Convert an image to canvas colors</p>
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
id="imgfile"
|
id="imgfile"
|
||||||
|
@ -341,7 +319,7 @@ function Converter({
|
||||||
readFile(file, selectFile, setScaleData);
|
readFile(file, selectFile, setScaleData);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<p style={textStyle}>Choose Strategy:
|
<p className="modalcotext">Choose Strategy:
|
||||||
<select
|
<select
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const sel = e.target;
|
const sel = e.target;
|
||||||
|
@ -368,7 +346,7 @@ function Converter({
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
<p style={textStyle}>Choose Color Mode:
|
<p className="modalcotext">Choose Color Mode:
|
||||||
<select
|
<select
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const sel = e.target;
|
const sel = e.target;
|
||||||
|
@ -395,7 +373,7 @@ function Converter({
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</p>
|
</p>
|
||||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={gridEnabled}
|
checked={gridEnabled}
|
||||||
|
@ -418,7 +396,7 @@ function Converter({
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={gridLight}
|
checked={gridLight}
|
||||||
|
@ -431,7 +409,7 @@ function Converter({
|
||||||
/>
|
/>
|
||||||
Light Grid
|
Light Grid
|
||||||
</p>
|
</p>
|
||||||
<span style={textStyle}>Offset X:
|
<span className="modalcotext">Offset X:
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
|
@ -445,9 +423,9 @@ function Converter({
|
||||||
offsetX: e.target.value,
|
offsetX: e.target.value,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>%
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span style={textStyle}>Offset Y:
|
<span className="modalcotext">Offset Y:
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
|
@ -461,12 +439,12 @@ function Converter({
|
||||||
offsetY: e.target.value,
|
offsetY: e.target.value,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>%
|
/>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
: null}
|
: null}
|
||||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={scalingEnabled}
|
checked={scalingEnabled}
|
||||||
|
@ -489,7 +467,7 @@ function Converter({
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span style={textStyle}>Width:
|
<span className="modalcotext">Width:
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
|
@ -504,6 +482,7 @@ function Converter({
|
||||||
if (selectedScaleKeepRatio && selectedFile) {
|
if (selectedScaleKeepRatio && selectedFile) {
|
||||||
const ratio = selectedFile.width / selectedFile.height;
|
const ratio = selectedFile.width / selectedFile.height;
|
||||||
const newHeight = Math.round(newWidth / ratio);
|
const newHeight = Math.round(newWidth / ratio);
|
||||||
|
if (newHeight <= 0) return;
|
||||||
setScaleData({
|
setScaleData({
|
||||||
...scaleData,
|
...scaleData,
|
||||||
width: newWidth,
|
width: newWidth,
|
||||||
|
@ -516,9 +495,9 @@ function Converter({
|
||||||
width: newWidth,
|
width: newWidth,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>%
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span style={textStyle}>Height:
|
<span className="modalcotext">Height:
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
|
@ -533,6 +512,7 @@ function Converter({
|
||||||
if (selectedScaleKeepRatio && selectedFile) {
|
if (selectedScaleKeepRatio && selectedFile) {
|
||||||
const ratio = selectedFile.width / selectedFile.height;
|
const ratio = selectedFile.width / selectedFile.height;
|
||||||
const nuWidth = Math.round(ratio * nuHeight);
|
const nuWidth = Math.round(ratio * nuHeight);
|
||||||
|
if (nuWidth <= 0) return;
|
||||||
setScaleData({
|
setScaleData({
|
||||||
...scaleData,
|
...scaleData,
|
||||||
width: nuWidth,
|
width: nuWidth,
|
||||||
|
@ -545,9 +525,9 @@ function Converter({
|
||||||
height: nuHeight,
|
height: nuHeight,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>%
|
/>
|
||||||
</span>
|
</span>
|
||||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={selectedScaleKeepRatio}
|
checked={selectedScaleKeepRatio}
|
||||||
|
@ -557,7 +537,7 @@ function Converter({
|
||||||
/>
|
/>
|
||||||
Keep Ratio
|
Keep Ratio
|
||||||
</p>
|
</p>
|
||||||
<p style={{ ...textStyle, fontHeight: 16 }}>
|
<p style={{ fontHeight: 16 }} className="modalcotext">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={scalingAA}
|
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"
|
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"
|
id="path4"
|
||||||
inkscape:connector-curvature="0"
|
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" />
|
sodipodi:nodetypes="ccccccccccccccccccccccccc" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
@ -15,7 +15,7 @@ function validate(password) {
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submit_delete_account(password) {
|
async function submitDeleteAccount(password) {
|
||||||
const body = JSON.stringify({
|
const body = JSON.stringify({
|
||||||
password,
|
password,
|
||||||
});
|
});
|
||||||
|
@ -56,7 +56,7 @@ class DeleteAccount extends React.Component {
|
||||||
if (errors.length > 0) return;
|
if (errors.length > 0) return;
|
||||||
this.setState({ submitting: true });
|
this.setState({ submitting: true });
|
||||||
|
|
||||||
const { errors: resperrors } = await submit_delete_account(password);
|
const { errors: resperrors } = await submitDeleteAccount(password);
|
||||||
if (resperrors) {
|
if (resperrors) {
|
||||||
this.setState({
|
this.setState({
|
||||||
errors: resperrors,
|
errors: resperrors,
|
||||||
|
@ -64,11 +64,13 @@ class DeleteAccount extends React.Component {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.props.set_name(null);
|
const { setName } = this.props;
|
||||||
|
setName(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { errors } = this.state;
|
const { errors, password, submitting } = this.state;
|
||||||
|
const { done } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="inarea" style={{ backgroundColor: '#ff6666' }}>
|
<div className="inarea" style={{ backgroundColor: '#ff6666' }}>
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
|
@ -76,14 +78,16 @@ class DeleteAccount extends React.Component {
|
||||||
<p key={error} className="errormessage">Error: {error}</p>
|
<p key={error} className="errormessage">Error: {error}</p>
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
value={this.state.password}
|
value={password}
|
||||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<button type="submit">{(this.state.submitting) ? '...' : 'Yes, Delete My Account!'}</button>
|
<button type="submit">
|
||||||
<button type="button" onClick={this.props.done}>Cancel</button>
|
{(submitting) ? '...' : 'Yes, Delete My Account!'}
|
||||||
|
</button>
|
||||||
|
<button type="button" onClick={done}>Cancel</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* espand menu / show other menu buttons
|
* espand menu / show other menu buttons
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
@ -9,7 +11,13 @@ import { MdExpandMore, MdExpandLess } from 'react-icons/md';
|
||||||
import { toggleOpenMenu } from '../actions';
|
import { toggleOpenMenu } from '../actions';
|
||||||
|
|
||||||
const ExpandMenuButton = ({ menuOpen, expand }) => (
|
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 /> }
|
{(menuOpen) ? <MdExpandLess /> : <MdExpandMore /> }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,22 +11,10 @@ import Modal from './Modal';
|
||||||
import { showUserAreaModal } from '../actions';
|
import { showUserAreaModal } from '../actions';
|
||||||
import NewPasswordForm from './NewPasswordForm';
|
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 }) => (
|
const ForgotPasswordModal = ({ login }) => (
|
||||||
<Modal title="Restore my Password">
|
<Modal title="Restore my Password">
|
||||||
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
||||||
<p style={textStyle}>
|
<p className="modaltext">
|
||||||
Enter your mail adress and we will send you a new password:
|
Enter your mail adress and we will send you a new password:
|
||||||
</p><br />
|
</p><br />
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
|
|
|
@ -8,29 +8,40 @@ import React from 'react';
|
||||||
import ReactDOM from 'react-dom/server';
|
import ReactDOM from 'react-dom/server';
|
||||||
|
|
||||||
import Html from './Html';
|
import Html from './Html';
|
||||||
|
/* this will be set by webpack */
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import assets from './assets.json';
|
import assets from './assets.json';
|
||||||
import { ASSET_SERVER } from '../core/config';
|
import { ASSET_SERVER } from '../core/config';
|
||||||
|
|
||||||
import globeCss from './globe.tcss';
|
import globeCss from '../styles/globe.css';
|
||||||
|
|
||||||
const Globe = () => (
|
const Globe = () => (
|
||||||
<div>
|
<div>
|
||||||
<style dangerouslySetInnerHTML={{ __html: globeCss }} />
|
|
||||||
<div id="webgl" />
|
<div id="webgl" />
|
||||||
<div id="coorbox">(0, 0)</div>
|
<div id="coorbox">(0, 0)</div>
|
||||||
<div id="info">Double click on globe to go back.</div>
|
<div id="info">Double click on globe to go back.</div>
|
||||||
<div id="loading">Loading...</div>
|
<div id="loading">Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
const styles = [{
|
||||||
|
id: 'globe',
|
||||||
|
cssText: globeCss,
|
||||||
|
}];
|
||||||
|
|
||||||
const data = {
|
const title = 'PixelPlanet.fun 3DGlobe';
|
||||||
title: 'PixelPlanet.fun 3DGlobe',
|
const description = '3D globe of our canvas';
|
||||||
description: '3D globe of our canvas',
|
const scripts = [
|
||||||
scripts: [
|
ASSET_SERVER + assets.globe.js,
|
||||||
ASSET_SERVER + assets.globe.js,
|
];
|
||||||
],
|
const body = <Globe />;
|
||||||
body: <Globe />,
|
const globeHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(
|
||||||
};
|
<Html
|
||||||
const globeHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
title={title}
|
||||||
|
description={description}
|
||||||
|
scripts={scripts}
|
||||||
|
body={body}
|
||||||
|
styles={styles}
|
||||||
|
/>,
|
||||||
|
)}`;
|
||||||
|
|
||||||
export default globeHtml;
|
export default globeHtml;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import type { State } from '../reducers';
|
||||||
*/
|
*/
|
||||||
function globe(canvasId, canvasIdent, canvasSize, view) {
|
function globe(canvasId, canvasIdent, canvasSize, view) {
|
||||||
const [x, y] = view.map(Math.round);
|
const [x, y] = view.map(Math.round);
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
window.location.href = `globe#${canvasIdent},${canvasId},${canvasSize},${x},${y}`;
|
window.location.href = `globe#${canvasIdent},${canvasId},${canvasSize},${x},${y}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,12 +23,17 @@ function globe(canvasId, canvasIdent, canvasSize, view) {
|
||||||
const GlobeButton = ({
|
const GlobeButton = ({
|
||||||
canvasId, canvasIdent, canvasSize, view,
|
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 />
|
<Md3DRotation />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO optimize
|
|
||||||
function mapStateToProps(state: State) {
|
function mapStateToProps(state: State) {
|
||||||
const {
|
const {
|
||||||
canvasId, canvasIdent, canvasSize, view,
|
canvasId, canvasIdent, canvasSize, view,
|
||||||
|
|
|
@ -11,16 +11,16 @@ import { toggleGrid } from '../actions';
|
||||||
|
|
||||||
|
|
||||||
const GridButton = ({ onToggleGrid }) => (
|
const GridButton = ({ onToggleGrid }) => (
|
||||||
<div className="actionbuttons" onClick={onToggleGrid}>
|
<div
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
className="actionbuttons"
|
||||||
|
onClick={onToggleGrid}
|
||||||
|
>
|
||||||
<FaTh />
|
<FaTh />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO simplify...
|
|
||||||
function mapStateToProps(state: State) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
function mapDispatchToProps(dispatch) {
|
||||||
return {
|
return {
|
||||||
open() {
|
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 }) => (
|
const HelpButton = ({ open }) => (
|
||||||
<div id="helpbutton" className="actionbuttons" onClick={open}>
|
<div
|
||||||
|
id="helpbutton"
|
||||||
|
className="actionbuttons"
|
||||||
|
onClick={open}
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
<FaQuestion />
|
<FaQuestion />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,75 +13,49 @@ import React from 'react';
|
||||||
import Modal from './Modal';
|
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 = () => (
|
const HelpModal = () => (
|
||||||
<Modal title="Welcome to PixelPlanet.fun">
|
<Modal title="Welcome to PixelPlanet.fun">
|
||||||
<p style={{ textAlign: 'center', paddingLeft: '5%', paddingRight: '5%' }}>
|
<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
|
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).
|
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
|
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.
|
pixels and 7s on already set pixels.
|
||||||
Higher zoomlevels take some time to update, the 3D globe gets updated at least once per day.
|
Higher zoomlevels take some time to update, the 3D globe gets updated at least once per day.
|
||||||
Have fun!</p>
|
Have fun!</p>
|
||||||
<p>Discord: <a href="./discord" target="_blank">pixelplanet.fun/discord</a></p>
|
<p>Discord: <a href="./discord" target="_blank" rel="noopener noreferrer">pixelplanet.fun/discord</a></p>
|
||||||
<p>Source on <a href="https://github.com/pixelplanetdev/pixelplanet" target="_blank">github</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">r/PixelPlanetFun</a></p>
|
<p>Reddit: <a href="https://www.reddit.com/r/PixelPlanetFun/" target="_blank" rel="noopener noreferrer">r/PixelPlanetFun</a></p>
|
||||||
<p style={titleStyle}>Map Data</p>
|
<p className="modaltitle">Map Data</p>
|
||||||
<p style={textStyle}>The bare map data that we use, together with converted OpenStreetMap tiles for orientation,
|
<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>
|
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 className="modaltitle">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>
|
<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 style={titleStyle}>2D Controls</h3>
|
<h3 className="modaltitle">2D Controls</h3>
|
||||||
<p style={textStyle}>Click a color in palette to select</p>
|
<p className="modaltext">Click a color in palette to select</p>
|
||||||
<p style={textStyle}>Press <kbd>G</kbd> to toggle grid</p>
|
<p className="modaltext">Press <kbd>G</kbd> to toggle grid</p>
|
||||||
<p style={textStyle}>Press <kbd>X</kbd> to toggle showing of pixel activity</p>
|
<p className="modaltext">Press <kbd>X</kbd> to toggle showing of pixel activity</p>
|
||||||
<p style={textStyle}>Press <kbd>R</kbd> to copy coordinates</p>
|
<p className="modaltext">Press <kbd>R</kbd> to copy coordinates</p>
|
||||||
<p style={textStyle}>Press <kbd>Q</kbd> or <kbd>E</kbd> to zoom</p>
|
<p className="modaltext">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 className="modaltext">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 className="modaltext">Press <kbd>↑</kbd>,<kbd>←</kbd>,<kbd>↓</kbd>, <kbd>→</kbd> to move</p>
|
||||||
<p style={textStyle}>Drag mouse to move</p>
|
<p className="modaltext">Drag mouse to move</p>
|
||||||
<p style={textStyle}>Scroll mouse wheel to zoom</p>
|
<p className="modaltext">Scroll mouse wheel to zoom</p>
|
||||||
<p style={textStyle}>Click middle mouse button to current hovering color</p>
|
<p className="modaltext">Click middle mouse button to current hovering color</p>
|
||||||
<p style={textStyle}>Pinch to zoom (on touch devices)</p>
|
<p className="modaltext">Pinch to zoom (on touch devices)</p>
|
||||||
<p style={textStyle}>Pan to move (on touch devices)</p>
|
<p className="modaltext">Pan to move (on touch devices)</p>
|
||||||
<p style={textStyle}>Click or tap to place a pixel</p>
|
<p className="modaltext">Click or tap to place a pixel</p>
|
||||||
<h3 style={titleStyle}>3D Controls</h3>
|
<h3 className="modaltitle">3D Controls</h3>
|
||||||
<p style={textStyle}>Press <kbd>W</kbd>,<kbd>A</kbd>,<kbd>S</kbd>, <kbd>D</kbd> to move</p>
|
<p className="modaltext">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 className="modaltext">Press <kbd>↑</kbd>,<kbd>←</kbd>,<kbd>↓</kbd>, <kbd>→</kbd> to move</p>
|
||||||
<p style={textStyle}>Scroll mouse wheel to zoom</p>
|
<p className="modaltext">Scroll mouse wheel to zoom</p>
|
||||||
<p style={textStyle}>Left click and drag mouse to rotate</p>
|
<p className="modaltext">Left click and drag mouse to rotate</p>
|
||||||
<p style={textStyle}>Middle click and drag mouse to zoom</p>
|
<p className="modaltext">Middle click and drag mouse to zoom</p>
|
||||||
<p style={textStyle}>Right click and drag mouse to pan</p>
|
<p className="modaltext">Right click and drag mouse to pan</p>
|
||||||
<p style={textStyle}>Left Click or tap to place a pixel</p>
|
<p className="modaltext">Left Click or tap to place a pixel</p>
|
||||||
<p style={textStyle}>Right Click of double tap to remove 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">crazygames.com</a></p>
|
<p>Partners: <a href="https://www.crazygames.com/c/io" target="_blank" rel="noopener noreferrer">crazygames.com</a></p>
|
||||||
<p style={textStyle}>
|
<p className="modaltext">
|
||||||
<small>This site is protected by reCAPTCHA and the Google
|
<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/privacy">Privacy Policy</a> and
|
||||||
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
|
<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.
|
* LICENSE.txt file in the root directory of this source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { analytics, RECAPTCHA_SITEKEY } from '../core/config';
|
import { analytics, RECAPTCHA_SITEKEY } from '../core/config';
|
||||||
|
|
||||||
class Html extends React.Component {
|
const Html = ({
|
||||||
static defaultProps = {
|
title,
|
||||||
styles: [],
|
description,
|
||||||
scripts: [],
|
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;
|
export default Html;
|
||||||
|
|
|
@ -11,7 +11,13 @@ import { showUserAreaModal } from '../actions';
|
||||||
|
|
||||||
|
|
||||||
const LogInButton = ({ open }) => (
|
const LogInButton = ({ open }) => (
|
||||||
<div id="loginbutton" className="actionbuttons" onClick={open}>
|
<div
|
||||||
|
id="loginbutton"
|
||||||
|
className="actionbuttons"
|
||||||
|
onClick={open}
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
<MdPerson />
|
<MdPerson />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,22 +9,29 @@ import React from 'react';
|
||||||
import ReactDOM from 'react-dom/server';
|
import ReactDOM from 'react-dom/server';
|
||||||
|
|
||||||
import Html from './Html';
|
import Html from './Html';
|
||||||
|
/* this one is set by webpack */
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import assets from './assets.json';
|
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';
|
import { ASSET_SERVER, BACKUP_URL } from '../core/config';
|
||||||
|
|
||||||
const data = {
|
// eslint-disable-next-line max-len
|
||||||
title: 'PixelPlanet.fun',
|
let code = `window.assetserver="${ASSET_SERVER}";window.availableStyles=JSON.parse('${JSON.stringify(styleassets)}');`;
|
||||||
description: 'Place color pixels on an map styled canvas '
|
if (BACKUP_URL) {
|
||||||
+ 'with other players online',
|
code += `window.backupurl="${BACKUP_URL}";`;
|
||||||
// styles: [
|
}
|
||||||
// { id: 'css', cssText: baseCss },
|
const scripts = [
|
||||||
// ],
|
ASSET_SERVER + assets.vendor.js,
|
||||||
scripts: [
|
ASSET_SERVER + assets.client.js,
|
||||||
ASSET_SERVER + assets.vendor.js,
|
];
|
||||||
ASSET_SERVER + assets.client.js,
|
const css = [
|
||||||
],
|
{
|
||||||
useRecaptcha: true,
|
id: 'globcss',
|
||||||
};
|
uri: styleassets.default,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* generates string with html of main page
|
* generates string with html of main page
|
||||||
|
@ -35,12 +42,18 @@ const data = {
|
||||||
*/
|
*/
|
||||||
function generateMainPage(countryCoords: Cell): string {
|
function generateMainPage(countryCoords: Cell): string {
|
||||||
const [x, y] = countryCoords;
|
const [x, y] = countryCoords;
|
||||||
let code = `window.coordx=${x};window.coordy=${y};window.assetserver="${ASSET_SERVER}";`;
|
// eslint-disable-next-line
|
||||||
if (BACKUP_URL) {
|
const html = ReactDOM.renderToStaticMarkup(
|
||||||
code += `window.backupurl="${BACKUP_URL}";`;
|
<Html
|
||||||
}
|
title="PixelPlanet.fun"
|
||||||
const htmldata = { ...data, code };
|
// eslint-disable-next-line max-len
|
||||||
const html = ReactDOM.renderToStaticMarkup(<Html {...htmldata} />);
|
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}`;
|
return `<!doctype html>${html}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,13 @@ import ToggleButton from 'react-toggle-button';
|
||||||
import { MdCheck, MdClose } from 'react-icons/md';
|
import { MdCheck, MdClose } from 'react-icons/md';
|
||||||
|
|
||||||
|
|
||||||
const MdToggleButton = ({ value, onToggle, ...props }) => (
|
const MdToggleButton = ({ value, onToggle }) => (
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
inactiveLabel={<MdClose />}
|
inactiveLabel={<MdClose />}
|
||||||
activeLabel={<MdCheck />}
|
activeLabel={<MdCheck />}
|
||||||
thumbAnimateRange={[-10, 36]}
|
thumbAnimateRange={[-10, 36]}
|
||||||
value={value}
|
value={value}
|
||||||
onToggle={onToggle}
|
onToggle={onToggle}
|
||||||
{...props}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,14 @@ import Creeper from './Creeper.svg';
|
||||||
|
|
||||||
import { showMinecraftModal } from '../actions';
|
import { showMinecraftModal } from '../actions';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
|
||||||
|
|
||||||
|
|
||||||
const MinecraftButton = ({ open }) => (
|
const MinecraftButton = ({ open }) => (
|
||||||
<div id="minecraftbutton" className="actionbuttons" onClick={open}>
|
<div
|
||||||
|
id="minecraftbutton"
|
||||||
|
className="actionbuttons"
|
||||||
|
onClick={open}
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
<Creeper />
|
<Creeper />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,13 +9,13 @@ import { MdNearMe } from 'react-icons/md';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../reducers';
|
||||||
|
|
||||||
async function submit_minecraft_tp(view) {
|
async function submitMinecraftTp(view) {
|
||||||
const [x, y] = view.map(Math.round);
|
const [x, y] = view.map(Math.round);
|
||||||
const body = JSON.stringify({
|
const body = JSON.stringify({
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
});
|
});
|
||||||
const response = await fetch('./api/mctp', {
|
await fetch('./api/mctp', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-type': 'application/json',
|
'Content-type': 'application/json',
|
||||||
|
@ -27,7 +27,13 @@ async function submit_minecraft_tp(view) {
|
||||||
|
|
||||||
|
|
||||||
const MinecraftTPButton = ({ 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 />
|
<MdNearMe />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -54,179 +54,171 @@ function cancelMovement() {
|
||||||
renderer.controls.moveDown = false;
|
renderer.controls.moveDown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mobile3DControls extends React.Component {
|
const Mobile3DControls = () => (
|
||||||
constructor() {
|
<div>
|
||||||
super();
|
<div
|
||||||
}
|
className="actionbuttons"
|
||||||
|
role="button"
|
||||||
render() {
|
tabIndex={0}
|
||||||
return (
|
style={{
|
||||||
<div>
|
...btnStyle,
|
||||||
<div
|
// left: 46,
|
||||||
className="actionbuttons"
|
left: 57,
|
||||||
role="button"
|
// bottom: 128,
|
||||||
tabIndex={0}
|
bottom: 139,
|
||||||
style={{
|
}}
|
||||||
...btnStyle,
|
onMouseDown={() => {
|
||||||
// left: 46,
|
move('FORWARD', true);
|
||||||
left: 57,
|
}}
|
||||||
// bottom: 128,
|
onMouseUp={() => {
|
||||||
bottom: 139,
|
move('FORWARD', false);
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => {
|
onTouchStart={() => {
|
||||||
move('FORWARD', true);
|
move('FORWARD', true);
|
||||||
}}
|
}}
|
||||||
onMouseUp={() => {
|
onTouchEnd={() => {
|
||||||
move('FORWARD', false);
|
move('FORWARD', false);
|
||||||
}}
|
}}
|
||||||
onTouchStart={() => {
|
onTouchCancel={cancelMovement}
|
||||||
move('FORWARD', true);
|
onMouseLeave={cancelMovement}
|
||||||
}}
|
>
|
||||||
onTouchEnd={() => {
|
↑
|
||||||
move('FORWARD', false);
|
</div>
|
||||||
}}
|
<div
|
||||||
onTouchCancel={cancelMovement}
|
className="actionbuttons"
|
||||||
onMouseLeave={cancelMovement}
|
role="button"
|
||||||
>
|
tabIndex={0}
|
||||||
↑
|
style={{
|
||||||
</div>
|
...btnStyle,
|
||||||
<div
|
// left: 46,
|
||||||
className="actionbuttons"
|
left: 57,
|
||||||
role="button"
|
bottom: 98,
|
||||||
tabIndex={0}
|
}}
|
||||||
style={{
|
onMouseDown={() => {
|
||||||
...btnStyle,
|
move('BACKWARD', true);
|
||||||
// left: 46,
|
}}
|
||||||
left: 57,
|
onMouseUp={() => {
|
||||||
bottom: 98,
|
move('BACKWARD', false);
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => {
|
onTouchStart={() => {
|
||||||
move('BACKWARD', true);
|
move('BACKWARD', true);
|
||||||
}}
|
}}
|
||||||
onMouseUp={() => {
|
onTouchEnd={() => {
|
||||||
move('BACKWARD', false);
|
move('BACKWARD', false);
|
||||||
}}
|
}}
|
||||||
onTouchStart={() => {
|
onTouchCancel={cancelMovement}
|
||||||
move('BACKWARD', true);
|
onMouseLeave={cancelMovement}
|
||||||
}}
|
>
|
||||||
onTouchEnd={() => {
|
↓
|
||||||
move('BACKWARD', false);
|
</div>
|
||||||
}}
|
<div
|
||||||
onTouchCancel={cancelMovement}
|
className="actionbuttons"
|
||||||
onMouseLeave={cancelMovement}
|
role="button"
|
||||||
>
|
tabIndex={0}
|
||||||
↓
|
style={{
|
||||||
</div>
|
...btnStyle,
|
||||||
<div
|
left: 16,
|
||||||
className="actionbuttons"
|
bottom: 98,
|
||||||
role="button"
|
}}
|
||||||
tabIndex={0}
|
onMouseDown={() => {
|
||||||
style={{
|
move('LEFT', true);
|
||||||
...btnStyle,
|
}}
|
||||||
left: 16,
|
onMouseUp={() => {
|
||||||
bottom: 98,
|
move('LEFT', false);
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => {
|
onTouchStart={() => {
|
||||||
move('LEFT', true);
|
move('LEFT', true);
|
||||||
}}
|
}}
|
||||||
onMouseUp={() => {
|
onTouchEnd={() => {
|
||||||
move('LEFT', false);
|
move('LEFT', false);
|
||||||
}}
|
}}
|
||||||
onTouchStart={() => {
|
onTouchCancel={cancelMovement}
|
||||||
move('LEFT', true);
|
onMouseLeave={cancelMovement}
|
||||||
}}
|
>
|
||||||
onTouchEnd={() => {
|
←
|
||||||
move('LEFT', false);
|
</div>
|
||||||
}}
|
<div
|
||||||
onTouchCancel={cancelMovement}
|
className="actionbuttons"
|
||||||
onMouseLeave={cancelMovement}
|
role="button"
|
||||||
>
|
tabIndex={0}
|
||||||
←
|
style={{
|
||||||
</div>
|
...btnStyle,
|
||||||
<div
|
// left: 76,
|
||||||
className="actionbuttons"
|
left: 98,
|
||||||
role="button"
|
bottom: 98,
|
||||||
tabIndex={0}
|
}}
|
||||||
style={{
|
onMouseDown={() => {
|
||||||
...btnStyle,
|
move('RIGHT', true);
|
||||||
// left: 76,
|
}}
|
||||||
left: 98,
|
onMouseUp={() => {
|
||||||
bottom: 98,
|
move('RIGHT', false);
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => {
|
onTouchStart={() => {
|
||||||
move('RIGHT', true);
|
move('RIGHT', true);
|
||||||
}}
|
}}
|
||||||
onMouseUp={() => {
|
onTouchEnd={() => {
|
||||||
move('RIGHT', false);
|
move('RIGHT', false);
|
||||||
}}
|
}}
|
||||||
onTouchStart={() => {
|
onTouchCancel={cancelMovement}
|
||||||
move('RIGHT', true);
|
onMouseLeave={cancelMovement}
|
||||||
}}
|
>
|
||||||
onTouchEnd={() => {
|
→
|
||||||
move('RIGHT', false);
|
</div>
|
||||||
}}
|
<div
|
||||||
onTouchCancel={cancelMovement}
|
className="actionbuttons"
|
||||||
onMouseLeave={cancelMovement}
|
role="button"
|
||||||
>
|
tabIndex={0}
|
||||||
→
|
style={{
|
||||||
</div>
|
...btnStyle,
|
||||||
<div
|
// left: 76,
|
||||||
className="actionbuttons"
|
left: 16,
|
||||||
role="button"
|
bottom: 139,
|
||||||
tabIndex={0}
|
}}
|
||||||
style={{
|
onMouseDown={() => {
|
||||||
...btnStyle,
|
move('UP', true);
|
||||||
// left: 76,
|
}}
|
||||||
left: 16,
|
onMouseUp={() => {
|
||||||
bottom: 139,
|
move('UP', false);
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => {
|
onTouchStart={() => {
|
||||||
move('UP', true);
|
move('UP', true);
|
||||||
}}
|
}}
|
||||||
onMouseUp={() => {
|
onTouchEnd={() => {
|
||||||
move('UP', false);
|
move('UP', false);
|
||||||
}}
|
}}
|
||||||
onTouchStart={() => {
|
onTouchCancel={cancelMovement}
|
||||||
move('UP', true);
|
onMouseLeave={cancelMovement}
|
||||||
}}
|
>
|
||||||
onTouchEnd={() => {
|
↖
|
||||||
move('UP', false);
|
</div>
|
||||||
}}
|
<div
|
||||||
onTouchCancel={cancelMovement}
|
className="actionbuttons"
|
||||||
onMouseLeave={cancelMovement}
|
role="button"
|
||||||
>
|
tabIndex={0}
|
||||||
↖
|
style={{
|
||||||
</div>
|
...btnStyle,
|
||||||
<div
|
// left: 76,
|
||||||
className="actionbuttons"
|
left: 98,
|
||||||
role="button"
|
bottom: 139,
|
||||||
tabIndex={0}
|
}}
|
||||||
style={{
|
onMouseDown={() => {
|
||||||
...btnStyle,
|
move('DOWN', true);
|
||||||
// left: 76,
|
}}
|
||||||
left: 98,
|
onMouseUp={() => {
|
||||||
bottom: 139,
|
move('DOWN', false);
|
||||||
}}
|
}}
|
||||||
onMouseDown={() => {
|
onTouchStart={() => {
|
||||||
move('DOWN', true);
|
move('DOWN', true);
|
||||||
}}
|
}}
|
||||||
onMouseUp={() => {
|
onTouchEnd={() => {
|
||||||
move('DOWN', false);
|
move('DOWN', false);
|
||||||
}}
|
}}
|
||||||
onTouchStart={() => {
|
onTouchCancel={cancelMovement}
|
||||||
move('DOWN', true);
|
onMouseLeave={cancelMovement}
|
||||||
}}
|
>
|
||||||
onTouchEnd={() => {
|
↘
|
||||||
move('DOWN', false);
|
</div>
|
||||||
}}
|
</div>
|
||||||
onTouchCancel={cancelMovement}
|
);
|
||||||
onMouseLeave={cancelMovement}
|
|
||||||
>
|
|
||||||
↘
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Mobile3DControls;
|
export default Mobile3DControls;
|
||||||
|
|
|
@ -13,26 +13,6 @@ import {
|
||||||
} from '../actions';
|
} 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 }) {
|
function MyModal({ close, title, children }) {
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -45,8 +25,8 @@ function MyModal({ close, title, children }) {
|
||||||
>
|
>
|
||||||
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
|
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
|
||||||
<div
|
<div
|
||||||
style={closeStyles}
|
|
||||||
onClick={close}
|
onClick={close}
|
||||||
|
className="ModalClose"
|
||||||
role="button"
|
role="button"
|
||||||
label="close"
|
label="close"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
|
|
|
@ -30,13 +30,13 @@ const MODAL_COMPONENTS = {
|
||||||
/* other modals */
|
/* other modals */
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModalRoot = ({ modalType, modalProps }) => {
|
const ModalRoot = ({ modalType }) => {
|
||||||
if (!modalType) {
|
if (!modalType) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpecificModal = MODAL_COMPONENTS[modalType];
|
const SpecificModal = MODAL_COMPONENTS[modalType];
|
||||||
return <SpecificModal {...modalProps} />;
|
return <SpecificModal />;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|
|
@ -73,17 +73,19 @@ class NewPasswordForm extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { errors } = this.state;
|
const { success } = this.state;
|
||||||
if (this.state.success) {
|
const { back } = this.props;
|
||||||
|
if (success) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p className="modalmessage">
|
<p className="modalmessage">
|
||||||
Sent you a mail with instructions to reset your password.
|
Sent you a mail with instructions to reset your password.
|
||||||
</p>
|
</p>
|
||||||
<button type="button" onClick={this.props.back}>Back</button>
|
<button type="button" onClick={back}>Back</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const { errors, email, submitting } = this.state;
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map((error) => (
|
{errors.map((error) => (
|
||||||
|
@ -91,16 +93,16 @@ class NewPasswordForm extends React.Component {
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.email}
|
value={email}
|
||||||
onChange={(evt) => this.setState({ email: evt.target.value })}
|
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<button type="submit">
|
<button type="submit">
|
||||||
{(this.state.submitting) ? '...' : 'Submit'}
|
{(submitting) ? '...' : 'Submit'}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onClick={this.props.back}>Cancel</button>
|
<button type="button" onClick={back}>Cancel</button>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,49 +8,46 @@ import React from 'react';
|
||||||
import TotalRankings from './TotalRankings';
|
import TotalRankings from './TotalRankings';
|
||||||
import DailyRankings from './DailyRankings';
|
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 {
|
class Rankings extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
order_daily: false,
|
orderDaily: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { orderDaily } = this.state;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
<span
|
<span
|
||||||
className={(!this.state.order_daily) ? 'modallinkselected' : 'modallink'}
|
role="button"
|
||||||
onClick={() => { this.setState({ order_daily: false }); }}
|
tabIndex={-1}
|
||||||
|
className={
|
||||||
|
(!orderDaily) ? 'modallinkselected' : 'modallink'
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
this.setState({ orderDaily: false });
|
||||||
|
}}
|
||||||
>Total</span> |
|
>Total</span> |
|
||||||
<span
|
<span
|
||||||
className={(this.state.order_daily) ? 'modallinkselected' : 'modallink'}
|
role="button"
|
||||||
onClick={() => { this.setState({ order_daily: true }); }}
|
tabIndex={-1}
|
||||||
|
className={
|
||||||
|
(orderDaily) ? 'modallinkselected' : 'modallink'
|
||||||
|
}
|
||||||
|
onClick={() => { this.setState({ orderDaily: true }); }}
|
||||||
>Daily</span>
|
>Daily</span>
|
||||||
</p>
|
</p>
|
||||||
{(this.state.order_daily) ? <DailyRankings /> : <TotalRankings />}
|
{(orderDaily) ? <DailyRankings /> : <TotalRankings />}
|
||||||
<p style={textStyle}>Ranking updates every 5 min. Daily rankings get reset at midnight UTC.</p>
|
<p className="modaltext">
|
||||||
|
Ranking updates every 5 min. Daily rankings get reset at midnight UTC.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state: State) {
|
|
||||||
const { totalRanking } = state.user;
|
|
||||||
return { totalRanking };
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Rankings;
|
export default Rankings;
|
||||||
|
|
|
@ -12,8 +12,6 @@ import { requestPlacePixel } from '../actions';
|
||||||
|
|
||||||
|
|
||||||
function onCaptcha(token: string) {
|
function onCaptcha(token: string) {
|
||||||
console.log('token', token);
|
|
||||||
|
|
||||||
const { canvasId, coordinates, color } = window.pixel;
|
const { canvasId, coordinates, color } = window.pixel;
|
||||||
|
|
||||||
store.dispatch(requestPlacePixel(canvasId, coordinates, color, token));
|
store.dispatch(requestPlacePixel(canvasId, coordinates, color, token));
|
||||||
|
|
|
@ -8,32 +8,21 @@ import { connect } from 'react-redux';
|
||||||
|
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
|
|
||||||
import { showUserAreaModal, receiveMe } from '../actions';
|
import { showUserAreaModal } from '../actions';
|
||||||
|
|
||||||
// import { send_registration } from '../ui/register';
|
// import { send_registration } from '../ui/register';
|
||||||
import SignUpForm from './SignUpForm';
|
import SignUpForm from './SignUpForm';
|
||||||
|
|
||||||
|
|
||||||
const textStyle = {
|
const RegisterModal = ({ login }) => (
|
||||||
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 }) => (
|
|
||||||
<Modal title="Register New Account">
|
<Modal title="Register New Account">
|
||||||
<p style={textStyle}>Register new account here</p><br />
|
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p className="modaltext">Register new account here</p><br />
|
||||||
<SignUpForm userarea={login} me={doMe} />
|
<p style={{ textAlign: 'center' }}>
|
||||||
<button type="button" onClick={login}>Cancel</button>
|
<SignUpForm back={login} />
|
||||||
<p>Also join our Discord:
|
<p>Also join our Discord:
|
||||||
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
|
<a href="./discord" target="_blank">pixelplanet.fun/discord</a>
|
||||||
|
</p>
|
||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -44,9 +33,6 @@ function mapDispatchToProps(dispatch) {
|
||||||
login() {
|
login() {
|
||||||
dispatch(showUserAreaModal());
|
dispatch(showUserAreaModal());
|
||||||
},
|
},
|
||||||
doMe(me) {
|
|
||||||
dispatch(receiveMe(me));
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,15 @@ import { FaCog } from 'react-icons/fa';
|
||||||
|
|
||||||
import { showSettingsModal } from '../actions';
|
import { showSettingsModal } from '../actions';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
|
||||||
|
|
||||||
|
|
||||||
const SettingsButton = ({ open }) => (
|
const SettingsButton = ({ open }) => (
|
||||||
<div id="settingsbutton" className="actionbuttons" onClick={open}>
|
<div
|
||||||
|
id="settingsbutton"
|
||||||
|
className="actionbuttons"
|
||||||
|
onClick={open}
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
|
>
|
||||||
<FaCog />
|
<FaCog />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
togglePotatoMode,
|
togglePotatoMode,
|
||||||
toggleLightGrid,
|
toggleLightGrid,
|
||||||
toggleHistoricalView,
|
toggleHistoricalView,
|
||||||
|
selectStyle,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../reducers';
|
||||||
|
@ -40,16 +41,6 @@ const itemStyles = {
|
||||||
|
|
||||||
const titleStyles = {
|
const titleStyles = {
|
||||||
flex: '1 1 auto',
|
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 = {
|
const rowStyles = {
|
||||||
|
@ -57,35 +48,50 @@ const rowStyles = {
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
};
|
};
|
||||||
|
|
||||||
const descriptionStyle = {
|
const SettingsItemSelect = ({
|
||||||
boxSizing: 'border-box',
|
title, description, values, selected, onSelect,
|
||||||
flex: '1 1 auto',
|
}) => (
|
||||||
color: 'hsla(218, 5%, 47%, .6)',
|
<div style={itemStyles}>
|
||||||
fontSize: 14,
|
<div style={rowStyles}>
|
||||||
lineHeight: '20px',
|
<h3 style={titleStyles} className="modaltitle">{title}</h3>
|
||||||
fontWeight: 500,
|
<select
|
||||||
marginTop: 4,
|
onChange={(e) => {
|
||||||
};
|
const sel = e.target;
|
||||||
|
onSelect(sel.options[sel.selectedIndex].value);
|
||||||
const dividerStyles = {
|
}}
|
||||||
boxSizing: 'border-box',
|
>
|
||||||
marginTop: 20,
|
{
|
||||||
height: 1,
|
values.map((value) => (
|
||||||
width: '100%',
|
<option
|
||||||
backgroundColor: 'hsla(216, 4%, 74%, .3)',
|
selected={value === selected}
|
||||||
};
|
value={value}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{description && <div className="modaldesc">{description} </div>}
|
||||||
|
<div className="modaldivider" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
const SettingsItem = ({
|
const SettingsItem = ({
|
||||||
title, description, keyBind, value, onToggle,
|
title, description, keyBind, value, onToggle,
|
||||||
}) => (
|
}) => (
|
||||||
<div style={itemStyles}>
|
<div style={itemStyles}>
|
||||||
<div style={rowStyles}>
|
<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} />
|
<MdToggleButtonHover value={value} onToggle={onToggle} />
|
||||||
</div>
|
</div>
|
||||||
{description && <div style={descriptionStyle}>{description} </div>}
|
{description && <div className="modaldesc">{description} </div>}
|
||||||
<div style={dividerStyles} />
|
<div className="modaldivider" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -99,6 +105,7 @@ function SettingsModal({
|
||||||
onMute,
|
onMute,
|
||||||
autoZoomIn,
|
autoZoomIn,
|
||||||
compactPalette,
|
compactPalette,
|
||||||
|
selectedStyle,
|
||||||
onToggleGrid,
|
onToggleGrid,
|
||||||
onTogglePixelNotify,
|
onTogglePixelNotify,
|
||||||
onToggleAutoZoomIn,
|
onToggleAutoZoomIn,
|
||||||
|
@ -107,6 +114,7 @@ function SettingsModal({
|
||||||
onTogglePotatoMode,
|
onTogglePotatoMode,
|
||||||
onToggleLightGrid,
|
onToggleLightGrid,
|
||||||
onToggleHistoricalView,
|
onToggleHistoricalView,
|
||||||
|
onSelectStyle,
|
||||||
chatNotify,
|
chatNotify,
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
|
@ -175,6 +183,15 @@ function SettingsModal({
|
||||||
onToggle={onToggleHistoricalView}
|
onToggle={onToggleHistoricalView}
|
||||||
/>
|
/>
|
||||||
) : null }
|
) : null }
|
||||||
|
{(typeof window.availableStyles !== 'undefined') && (
|
||||||
|
<SettingsItemSelect
|
||||||
|
title="Styles"
|
||||||
|
description="How pixelplanet should look like."
|
||||||
|
values={Object.keys(window.availableStyles)}
|
||||||
|
selected={selectedStyle}
|
||||||
|
onSelect={onSelectStyle}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -189,6 +206,7 @@ function mapStateToProps(state: State) {
|
||||||
compactPalette,
|
compactPalette,
|
||||||
isPotato,
|
isPotato,
|
||||||
isLightGrid,
|
isLightGrid,
|
||||||
|
style: selectedStyle,
|
||||||
} = state.gui;
|
} = state.gui;
|
||||||
const isMuted = mute;
|
const isMuted = mute;
|
||||||
const {
|
const {
|
||||||
|
@ -206,6 +224,7 @@ function mapStateToProps(state: State) {
|
||||||
isPotato,
|
isPotato,
|
||||||
isLightGrid,
|
isLightGrid,
|
||||||
isHistoricalView,
|
isHistoricalView,
|
||||||
|
selectedStyle,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +257,9 @@ function mapDispatchToProps(dispatch) {
|
||||||
onToggleHistoricalView() {
|
onToggleHistoricalView() {
|
||||||
dispatch(toggleHistoricalView());
|
dispatch(toggleHistoricalView());
|
||||||
},
|
},
|
||||||
|
onSelectStyle(style) {
|
||||||
|
dispatch(selectStyle(style));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
validateEMail, validateName, validatePassword, parseAPIresponse,
|
validateEMail, validateName, validatePassword, parseAPIresponse,
|
||||||
} from '../utils/validation';
|
} from '../utils/validation';
|
||||||
|
|
||||||
|
import { showUserAreaModal, receiveMe } from '../actions';
|
||||||
|
|
||||||
|
|
||||||
function validate(name, email, password, confirmPassword) {
|
function validate(name, email, password, confirmPassword) {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const mailerror = validateEMail(email);
|
const mailerror = validateEMail(email);
|
||||||
|
@ -90,12 +94,23 @@ class SignUpForm extends React.Component {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.props.me(me);
|
const { doMe, userarea } = this.props;
|
||||||
this.props.userarea();
|
doMe(me);
|
||||||
|
userarea();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { errors } = this.state;
|
const {
|
||||||
|
errors,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
confirmPassword,
|
||||||
|
submitting,
|
||||||
|
} = this.state;
|
||||||
|
const {
|
||||||
|
back,
|
||||||
|
} = this.props;
|
||||||
return (
|
return (
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
{errors.map((error) => (
|
{errors.map((error) => (
|
||||||
|
@ -103,28 +118,28 @@ class SignUpForm extends React.Component {
|
||||||
))}
|
))}
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.name}
|
value={name}
|
||||||
onChange={(evt) => this.setState({ name: evt.target.value })}
|
onChange={(evt) => this.setState({ name: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Name"
|
placeholder="Name"
|
||||||
/><br />
|
/><br />
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.email}
|
value={email}
|
||||||
onChange={(evt) => this.setState({ email: evt.target.value })}
|
onChange={(evt) => this.setState({ email: evt.target.value })}
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
/><br />
|
/><br />
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.password}
|
value={password}
|
||||||
onChange={(evt) => this.setState({ password: evt.target.value })}
|
onChange={(evt) => this.setState({ password: evt.target.value })}
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
/><br />
|
/><br />
|
||||||
<input
|
<input
|
||||||
style={inputStyles}
|
style={inputStyles}
|
||||||
value={this.state.confirmPassword}
|
value={confirmPassword}
|
||||||
onChange={(evt) => this.setState({
|
onChange={(evt) => this.setState({
|
||||||
confirmPassword: evt.target.value,
|
confirmPassword: evt.target.value,
|
||||||
})}
|
})}
|
||||||
|
@ -132,11 +147,29 @@ class SignUpForm extends React.Component {
|
||||||
placeholder="Confirm Password"
|
placeholder="Confirm Password"
|
||||||
/><br />
|
/><br />
|
||||||
<button type="submit">
|
<button type="submit">
|
||||||
{(this.state.submitting) ? '...' : 'Submit'}
|
{(submitting) ? '...' : 'Submit'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={back}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</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 React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
class Tab extends Component {
|
class Tab extends Component {
|
||||||
static propTypes = {
|
|
||||||
activeTab: PropTypes.string.isRequired,
|
|
||||||
label: PropTypes.string.isRequired,
|
|
||||||
onClick: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
onClick = () => {
|
onClick = () => {
|
||||||
const { label, onClick } = this.props;
|
const { label, onClick } = this.props;
|
||||||
onClick(label);
|
onClick(label);
|
||||||
|
@ -30,6 +23,7 @@ class Tab extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
|
role="presentation"
|
||||||
className={className}
|
className={className}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import Tab from './Tab';
|
import Tab from './Tab';
|
||||||
|
|
||||||
class Tabs extends Component {
|
class Tabs extends Component {
|
||||||
static propTypes = {
|
|
||||||
children: PropTypes.instanceOf(Array).isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
const { children } = this.props;
|
||||||
this.state = {
|
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';
|
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 }) => (
|
const Stat = ({ text, value, rank }) => (
|
||||||
<p>
|
<p>
|
||||||
<span className="stattext">{(rank) ? `${text}: #` : `${text}: `}</span>
|
<span className="stattext">{(rank) ? `${text}: #` : `${text}: `}</span>
|
||||||
|
|
||||||
<span className="statvalue">{numberToString(value)}</span>
|
<span className="statvalue">{numberToString(value)}</span>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
@ -40,95 +29,131 @@ class UserArea extends React.Component {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
// that should be an ENUM tbh
|
// that should be an ENUM tbh
|
||||||
change_name_extended: false,
|
changeNameExtended: false,
|
||||||
change_mail_extended: false,
|
changeMailExtended: false,
|
||||||
change_passwd_extended: false,
|
changePasswdExtended: false,
|
||||||
delete_account_extended: false,
|
deleteAccountExtended: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const {
|
||||||
|
stats, name, logout, mailreg, setMailreg, setName,
|
||||||
|
} = this.props;
|
||||||
|
const {
|
||||||
|
changeNameExtended,
|
||||||
|
changeMailExtended,
|
||||||
|
changePasswdExtended,
|
||||||
|
deleteAccountExtended,
|
||||||
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
<UserMessages />
|
<UserMessages />
|
||||||
<Stat text="Todays Placed Pixels" value={this.props.stats.dailyTotalPixels} />
|
<Stat
|
||||||
<Stat text="Daily Rank" value={this.props.stats.dailyRanking} rank />
|
text="Todays Placed Pixels"
|
||||||
<Stat text="Placed Pixels" value={this.props.stats.totalPixels} />
|
value={stats.dailyTotalPixels}
|
||||||
<Stat text="Total Rank" value={this.props.stats.ranking} rank />
|
/>
|
||||||
<p style={textStyle}>
|
<Stat
|
||||||
<p>Your name is: {this.props.name}</p>(
|
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
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={this.props.logout}
|
onClick={logout}
|
||||||
> Log out</span> |
|
> Log out</span> |
|
||||||
<span
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={(evt) => this.setState({
|
onClick={() => this.setState({
|
||||||
change_name_extended: true,
|
changeNameExtended: true,
|
||||||
change_mail_extended: false,
|
changeMailExtended: false,
|
||||||
change_passwd_extended: false,
|
changePasswdExtended: false,
|
||||||
delete_account_extended: false,
|
deleteAccountExtended: false,
|
||||||
})}
|
})}
|
||||||
> Change Username</span> |
|
> Change Username</span> |
|
||||||
{(this.props.mailreg)
|
{(mailreg)
|
||||||
&& (
|
&& (
|
||||||
<span>
|
<span>
|
||||||
<span
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={(evt) => this.setState({
|
onClick={() => this.setState({
|
||||||
change_name_extended: false,
|
changeNameExtended: false,
|
||||||
change_mail_extended: true,
|
changeMailExtended: true,
|
||||||
change_passwd_extended: false,
|
changePasswdExtended: false,
|
||||||
delete_account_extended: false,
|
deleteAccountExtended: false,
|
||||||
})}
|
})}
|
||||||
> Change Mail</span> |
|
> Change Mail</span> |
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={(evt) => this.setState({
|
onClick={() => this.setState({
|
||||||
change_name_extended: false,
|
changeNameExtended: false,
|
||||||
change_mail_extended: false,
|
changeMailExtended: false,
|
||||||
change_passwd_extended: true,
|
changePasswdExtended: true,
|
||||||
delete_account_extended: false,
|
deleteAccountExtended: false,
|
||||||
})}
|
})}
|
||||||
> Change Password</span> |
|
> Change Password</span> |
|
||||||
<span
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={-1}
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={(evt) => this.setState({
|
onClick={() => this.setState({
|
||||||
change_name_extended: false,
|
changeNameExtended: false,
|
||||||
change_mail_extended: false,
|
changeMailExtended: false,
|
||||||
change_passwd_extended: false,
|
changePasswdExtended: false,
|
||||||
delete_account_extended: true,
|
deleteAccountExtended: true,
|
||||||
})}
|
})}
|
||||||
> Delete Account</span> )
|
> Delete Account</span> )
|
||||||
</p>
|
</p>
|
||||||
{(this.state.change_passwd_extended)
|
{(changePasswdExtended)
|
||||||
&& (
|
&& (
|
||||||
<ChangePassword
|
<ChangePassword
|
||||||
mailreg={this.props.mailreg}
|
mailreg={mailreg}
|
||||||
done={() => { this.props.set_mailreg(true); this.setState({ change_passwd_extended: false }); }}
|
done={() => {
|
||||||
cancel={() => { this.setState({ change_passwd_extended: false }); }}
|
setMailreg(true);
|
||||||
|
this.setState({ changePasswdExtended: false });
|
||||||
|
}}
|
||||||
|
cancel={() => { this.setState({ changePasswdExtended: false }); }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{(this.state.change_name_extended)
|
{(changeNameExtended)
|
||||||
&& (
|
&& (
|
||||||
<ChangeName
|
<ChangeName
|
||||||
set_name={this.props.set_name}
|
setName={setName}
|
||||||
done={() => { this.setState({ change_name_extended: false }); }}
|
done={() => { this.setState({ changeNameExtended: false }); }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{(this.state.change_mail_extended)
|
{(changeMailExtended)
|
||||||
&& (
|
&& (
|
||||||
<ChangeMail
|
<ChangeMail
|
||||||
done={() => { this.setState({ change_mail_extended: false }); }}
|
done={() => { this.setState({ changeMailExtended: false }); }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{(this.state.delete_account_extended)
|
{(deleteAccountExtended)
|
||||||
&& (
|
&& (
|
||||||
<DeleteAccount
|
<DeleteAccount
|
||||||
set_name={this.props.set_name}
|
setName={setName}
|
||||||
done={() => { this.setState({ delete_account_extended: false }); }}
|
done={() => { this.setState({ deleteAccountExtended: false }); }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -26,26 +26,15 @@ const logoStyle = {
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
const textStyle = {
|
const LogInArea = ({ register, forgotPassword, me }) => (
|
||||||
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 }) => (
|
|
||||||
<p style={{ textAlign: 'center' }}>
|
<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>
|
<h2>Login with Mail:</h2>
|
||||||
<LogInForm me={me} />
|
<LogInForm me={me} />
|
||||||
<p
|
<p
|
||||||
className="modallink"
|
className="modallink"
|
||||||
onClick={forgot_password}
|
onClick={forgotPassword}
|
||||||
|
role="presentation"
|
||||||
>
|
>
|
||||||
I forgot my Password.</p>
|
I forgot my Password.</p>
|
||||||
<h2>or login with:</h2>
|
<h2>or login with:</h2>
|
||||||
|
@ -95,7 +84,7 @@ const LogInArea = ({ register, forgot_password, me }) => (
|
||||||
);
|
);
|
||||||
|
|
||||||
const UserAreaModal = ({
|
const UserAreaModal = ({
|
||||||
name, register, forgot_password, doMe, logout, setUserName, setUserMailreg,
|
name, register, forgotPassword, doMe, logout, setUserName, setUserMailreg,
|
||||||
}) => (
|
}) => (
|
||||||
<Modal title="User Area">
|
<Modal title="User Area">
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
|
@ -103,7 +92,7 @@ const UserAreaModal = ({
|
||||||
? (
|
? (
|
||||||
<LogInArea
|
<LogInArea
|
||||||
register={register}
|
register={register}
|
||||||
forgot_password={forgot_password}
|
forgotPassword={forgotPassword}
|
||||||
me={doMe}
|
me={doMe}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -112,8 +101,8 @@ const UserAreaModal = ({
|
||||||
<div label="Profile">
|
<div label="Profile">
|
||||||
<UserArea
|
<UserArea
|
||||||
logout={logout}
|
logout={logout}
|
||||||
set_name={setUserName}
|
setName={setUserName}
|
||||||
set_mailreg={setUserMailreg}
|
setMailreg={setUserMailreg}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div label="Ranking">
|
<div label="Ranking">
|
||||||
|
@ -138,7 +127,7 @@ function mapDispatchToProps(dispatch) {
|
||||||
register() {
|
register() {
|
||||||
dispatch(showRegisterModal());
|
dispatch(showRegisterModal());
|
||||||
},
|
},
|
||||||
forgot_password() {
|
forgotPassword() {
|
||||||
dispatch(showForgotPasswordModal());
|
dispatch(showForgotPasswordModal());
|
||||||
},
|
},
|
||||||
doMe(me) {
|
doMe(me) {
|
||||||
|
|
|
@ -13,20 +13,21 @@ class UserMessages extends React.Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
resent_verify: false,
|
resentVerify: false,
|
||||||
sent_link: false,
|
sentLink: false,
|
||||||
verify_answer: null,
|
verifyAnswer: null,
|
||||||
link_answer: null,
|
linkAnswer: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.submit_resend_verify = this.submit_resend_verify.bind(this);
|
this.submitResendVerify = this.submitResendVerify.bind(this);
|
||||||
this.submit_mc_link = this.submit_mc_link.bind(this);
|
this.submitMcLink = this.submitMcLink.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit_resend_verify() {
|
async submitResendVerify() {
|
||||||
if (this.state.resent_verify) return;
|
const { resentVerify } = this.state;
|
||||||
|
if (resentVerify) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
resent_verify: true,
|
resentVerify: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await fetch('./api/auth/resend_verify', {
|
const response = await fetch('./api/auth/resend_verify', {
|
||||||
|
@ -34,16 +35,19 @@ class UserMessages extends React.Component {
|
||||||
});
|
});
|
||||||
|
|
||||||
const { errors } = await parseAPIresponse(response);
|
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({
|
this.setState({
|
||||||
verify_answer,
|
verifyAnswer,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit_mc_link(accepted) {
|
async submitMcLink(accepted) {
|
||||||
if (this.state.sent_link) return;
|
const { sentLink } = this.state;
|
||||||
|
if (sentLink) return;
|
||||||
this.setState({
|
this.setState({
|
||||||
sent_link: true,
|
sentLink: true,
|
||||||
});
|
});
|
||||||
const body = JSON.stringify({ accepted });
|
const body = JSON.stringify({ accepted });
|
||||||
const rep = await fetch('./api/auth/mclink', {
|
const rep = await fetch('./api/auth/mclink', {
|
||||||
|
@ -56,43 +60,94 @@ class UserMessages extends React.Component {
|
||||||
const { errors } = parseAPIresponse(rep);
|
const { errors } = parseAPIresponse(rep);
|
||||||
if (errors) {
|
if (errors) {
|
||||||
this.setState({
|
this.setState({
|
||||||
link_answer: errors[0],
|
linkAnswer: errors[0],
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const { setMCName, remFromUserMessages } = this.props;
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
this.props.setMCName(null);
|
setMCName(null);
|
||||||
}
|
}
|
||||||
this.props.rem_from_messages('not_mc_verified');
|
remFromUserMessages('not_mc_verified');
|
||||||
this.setState({
|
this.setState({
|
||||||
link_answer: (accepted) ? 'You successfully linked your mc account.' : 'You denied.',
|
linkAnswer: (accepted)
|
||||||
|
? 'You successfully linked your mc account.'
|
||||||
|
: 'You denied.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
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
|
// 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 (
|
return (
|
||||||
<div style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
<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">
|
<p className="usermessages">
|
||||||
Please verify your mail address or your account could get deleted after a few days.
|
Please verify your mail address
|
||||||
{(this.state.verify_answer)
|
or your account could get deleted after a few days.
|
||||||
? <span className="modallink">{this.state.verify_answer}</span>
|
{(verifyAnswer)
|
||||||
: <span className="modallink" onClick={this.submit_resend_verify}>Click here to request a new verification mail.</span>}
|
? (
|
||||||
|
<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>
|
</p>
|
||||||
) : null}
|
) : 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}.
|
<p className="usermessages">
|
||||||
{(this.state.link_answer)
|
You requested to link your mc account {minecraftname}.
|
||||||
? <span className="modallink">{this.state.link_answer}</span>
|
|
||||||
|
{(linkAnswer)
|
||||||
|
? (
|
||||||
|
<span
|
||||||
|
className="modallink"
|
||||||
|
>
|
||||||
|
{linkAnswer}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
: (
|
: (
|
||||||
<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>
|
</span>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
@ -110,7 +165,7 @@ function mapDispatchToProps(dispatch) {
|
||||||
setMCName(minecraftname) {
|
setMCName(minecraftname) {
|
||||||
dispatch(setMinecraftName(minecraftname));
|
dispatch(setMinecraftName(minecraftname));
|
||||||
},
|
},
|
||||||
rem_from_messages(message) {
|
remFromUserMessages(message) {
|
||||||
dispatch(remFromMessages(message));
|
dispatch(remFromMessages(message));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -948,8 +948,8 @@ class VoxelPainterControls extends EventDispatcher {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// clamp to boundaries
|
// clamp to boundaries
|
||||||
const state = scope.store.getState();
|
const reduxState = scope.store.getState();
|
||||||
const { canvasSize } = state.canvas;
|
const { canvasSize } = reduxState.canvas;
|
||||||
const bound = canvasSize / 2;
|
const bound = canvasSize / 2;
|
||||||
scope.target.clamp({
|
scope.target.clamp({
|
||||||
x: -bound,
|
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 RedisCanvas from '../data/models/RedisCanvas';
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
import { getChunkOfPixel } from './utils';
|
import { getChunkOfPixel } from './utils';
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
* @flow
|
* @flow
|
||||||
* */
|
* */
|
||||||
|
|
||||||
|
// Tile creation is allowed to be slow
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
|
@ -14,7 +17,8 @@ import { getMaxTiledZoom } from './utils';
|
||||||
import { TILE_SIZE, TILE_ZOOM_LEVEL } from './constants';
|
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 palette Palette to use
|
||||||
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
* @param subtilesInTile how many subtiles are in a tile (per dimension)
|
||||||
* @param cell subtile to delete [dx, dy]
|
* @param cell subtile to delete [dx, dy]
|
||||||
|
@ -32,8 +36,11 @@ function deleteSubtilefromTile(
|
||||||
let channelOffset = (offset + row * TILE_SIZE * subtilesInTile) * 3;
|
let channelOffset = (offset + row * TILE_SIZE * subtilesInTile) * 3;
|
||||||
const max = channelOffset + TILE_SIZE * 3;
|
const max = channelOffset + TILE_SIZE * 3;
|
||||||
while (channelOffset < max) {
|
while (channelOffset < max) {
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
buffer[channelOffset++] = palette.rgb[0];
|
buffer[channelOffset++] = palette.rgb[0];
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
buffer[channelOffset++] = palette.rgb[1];
|
buffer[channelOffset++] = palette.rgb[1];
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
buffer[channelOffset++] = palette.rgb[2];
|
buffer[channelOffset++] = palette.rgb[2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +59,7 @@ function addRGBSubtiletoTile(
|
||||||
buffer: Uint8Array,
|
buffer: Uint8Array,
|
||||||
) {
|
) {
|
||||||
const [dx, dy] = cell;
|
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 pos: number = 0;
|
||||||
for (let row = 0; row < TILE_SIZE; row += 1) {
|
for (let row = 0; row < TILE_SIZE; row += 1) {
|
||||||
let channelOffset = (chunkOffset + row * TILE_SIZE * subtilesInTile) * 3;
|
let channelOffset = (chunkOffset + row * TILE_SIZE * subtilesInTile) * 3;
|
||||||
|
@ -80,7 +87,7 @@ function addIndexedSubtiletoTile(
|
||||||
buffer: Uint8Array,
|
buffer: Uint8Array,
|
||||||
) {
|
) {
|
||||||
const [dx, dy] = cell;
|
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 pos: number = 0;
|
||||||
let clr: number;
|
let clr: number;
|
||||||
for (let row = 0; row < TILE_SIZE; row += 1) {
|
for (let row = 0; row < TILE_SIZE; row += 1) {
|
||||||
|
@ -194,6 +201,7 @@ export async function createZoomedTile(
|
||||||
const na = [];
|
const na = [];
|
||||||
for (let dy = 0; dy < TILE_ZOOM_LEVEL; dy += 1) {
|
for (let dy = 0; dy < TILE_ZOOM_LEVEL; dy += 1) {
|
||||||
for (let dx = 0; dx < TILE_ZOOM_LEVEL; dx += 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`;
|
const chunkfile = `${canvasTileFolder}/${z + 1}/${x * TILE_ZOOM_LEVEL + dx}/${y * TILE_ZOOM_LEVEL + dy}.png`;
|
||||||
if (!fs.existsSync(chunkfile)) {
|
if (!fs.existsSync(chunkfile)) {
|
||||||
na.push([dx, dy]);
|
na.push([dx, dy]);
|
||||||
|
@ -244,8 +252,11 @@ export async function createEmptyTile(
|
||||||
let i = 0;
|
let i = 0;
|
||||||
const max = TILE_SIZE * TILE_SIZE * 3;
|
const max = TILE_SIZE * TILE_SIZE * 3;
|
||||||
while (i < max) {
|
while (i < max) {
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
tileRGBBuffer[i++] = palette.rgb[0];
|
tileRGBBuffer[i++] = palette.rgb[0];
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
tileRGBBuffer[i++] = palette.rgb[1];
|
tileRGBBuffer[i++] = palette.rgb[1];
|
||||||
|
// eslint-disable-next-line prefer-destructuring
|
||||||
tileRGBBuffer[i++] = palette.rgb[2];
|
tileRGBBuffer[i++] = palette.rgb[2];
|
||||||
}
|
}
|
||||||
const filename = `${canvasTileFolder}/emptytile.png`;
|
const filename = `${canvasTileFolder}/emptytile.png`;
|
||||||
|
@ -416,6 +427,7 @@ export async function initializeTiles(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.info(
|
logger.info(
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
`Tiling: Created ${cnts} / ${cnt} tiles for zoom ${zoom} for canvas${canvasId}`,
|
`Tiling: Created ${cnts} / ${cnt} tiles for zoom ${zoom} for canvas${canvasId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -429,6 +441,7 @@ export async function initializeTiles(
|
||||||
);
|
);
|
||||||
//--
|
//--
|
||||||
logger.info(
|
logger.info(
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
`Tiling: Elapsed Time: ${Math.round((Date.now() - startTime) / 1000)} for canvas${canvasId}`,
|
`Tiling: Elapsed Time: ${Math.round((Date.now() - startTime) / 1000)} for canvas${canvasId}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,11 @@ const logger = proxyLogger;
|
||||||
* @param ip IP to check
|
* @param ip IP to check
|
||||||
* @return true if proxy, false if not
|
* @return true if proxy, false if not
|
||||||
*/
|
*/
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
async function getIPIntel(ip: string): Promise<boolean> {
|
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`;
|
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`;
|
const url = `http://check.getipintel.net/check.php?ip=${ip}&contact=${email}&flags=m`;
|
||||||
logger.info(`PROXYCHECK fetching getipintel ${url}`);
|
logger.info(`PROXYCHECK fetching getipintel ${url}`);
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
@ -27,6 +30,7 @@ async function getIPIntel(ip: string): Promise<boolean> {
|
||||||
Accept: '*/*',
|
Accept: '*/*',
|
||||||
'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
|
'Accept-Language': 'de,en-US;q=0.7,en;q=0.3',
|
||||||
Referer: 'http://check.getipintel.net/',
|
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',
|
'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);
|
logger.info('PROXYCHECK fetching proxycheck %s', url);
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
headers: {
|
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',
|
'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();
|
const data = await response.json();
|
||||||
logger.info('PROXYCHECK proxycheck is proxy?', data);
|
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> {
|
async function getShroomey(ip: string): Promise<boolean> {
|
||||||
logger.info('PROXYCHECK fetching shroomey %s', ip);
|
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}`, {
|
const response = await fetch(`http://www.shroomery.org/ythan/proxycheck.php?ip=${ip}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: '*/*',
|
Accept: '*/*',
|
||||||
'Accept-Language': 'es-ES,es;q=0.8,en;q=0.6',
|
'Accept-Language': 'es-ES,es;q=0.8,en;q=0.6',
|
||||||
Referer: 'http://www.shroomery.org/',
|
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',
|
'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';
|
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
|
* check MYSQL Blacklist table
|
||||||
* @param ip IP to check
|
* @param ip IP to check
|
||||||
|
@ -150,7 +142,14 @@ async function dummy(): Promise<boolean> {
|
||||||
async function withoutCache(f, ip) {
|
async function withoutCache(f, ip) {
|
||||||
if (!ip) return true;
|
if (!ip) return true;
|
||||||
const ipKey = getIPv6Subnet(ip);
|
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);
|
const cache = await redis.getAsync(key);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
const str = cache.toString('utf8');
|
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';
|
return str === 'y';
|
||||||
}
|
}
|
||||||
logger.debug('PROXYCHECK fetch isproxy not from cache %s', key);
|
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
|
// else make asynchronous ipcheck and assume no proxy in the meantime
|
||||||
// use lock to just check three at a time
|
// use lock to just check three at a time
|
||||||
// do not check ip that currently gets checked
|
// do not check ip that currently gets checked
|
||||||
if (checking.indexOf(ipKey) == -1 && lock > 0) {
|
if (checking.indexOf(ipKey) === -1 && lock > 0) {
|
||||||
lock -= 1;
|
lock -= 1;
|
||||||
checking.push(ipKey);
|
checking.push(ipKey);
|
||||||
withoutCache(f, ip)
|
withoutCache(f, ip)
|
||||||
|
@ -199,16 +203,16 @@ async function withCache(f, ip) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cheapDetector(ip: string): Promise<boolean> {
|
export function cheapDetector(ip: string): Promise<boolean> {
|
||||||
return (await withCache(getProxyCheck, ip));
|
return withCache(getProxyCheck, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function strongDetector(ip: string): Promise<boolean> {
|
export function strongDetector(ip: string): Promise<boolean> {
|
||||||
return (await withCache(getShroomey, ip));
|
return withCache(getShroomey, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function blacklistDetector(ip: string): Promise<boolean> {
|
export function blacklistDetector(ip: string): Promise<boolean> {
|
||||||
return (await withCache(dummy, ip));
|
return withCache(dummy, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// export default cheapDetector;
|
// export default cheapDetector;
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Minecraft {
|
||||||
this.online = {};
|
this.online = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
async report_login(minecraftid, minecraftname) {
|
async reportLogin(minecraftid, minecraftname) {
|
||||||
const user = new User();
|
const user = new User();
|
||||||
user.minecraftname = minecraftname;
|
user.minecraftname = minecraftname;
|
||||||
const reguser = await RegUser.findOne({ where: { minecraftid } });
|
const reguser = await RegUser.findOne({ where: { minecraftid } });
|
||||||
|
@ -35,26 +35,27 @@ class Minecraft {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
report_logout(minecraftid) {
|
reportLogout(minecraftid) {
|
||||||
delete this.online[minecraftid];
|
delete this.online[minecraftid];
|
||||||
}
|
}
|
||||||
|
|
||||||
report_userlist(list) {
|
reportUserlist(list) {
|
||||||
this.online = {};
|
this.online = {};
|
||||||
list.forEach((user) => {
|
list.forEach((user) => {
|
||||||
const [minecraftid, minecraftname] = 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 {
|
try {
|
||||||
const finduser = await RegUser.findOne({ where: { minecraftid } });
|
const finduser = await RegUser.findOne({ where: { minecraftid } });
|
||||||
if (finduser) {
|
if (finduser) {
|
||||||
if (finduser.name == name) {
|
if (finduser.name === name) {
|
||||||
if (finduser.mcVerified) {
|
if (finduser.mcVerified) {
|
||||||
return 'You are already verified';
|
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 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}.`;
|
return `You already linked to other account ${finduser.name}.`;
|
||||||
|
@ -62,6 +63,7 @@ class Minecraft {
|
||||||
const reguser = await RegUser.findOne({ where: { name } });
|
const reguser = await RegUser.findOne({ where: { name } });
|
||||||
if (reguser) {
|
if (reguser) {
|
||||||
if (reguser.minecraftid) {
|
if (reguser.minecraftid) {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
return `This pixelplanet account is already linked to ${reguser.minecraftname}`;
|
return `This pixelplanet account is already linked to ${reguser.minecraftname}`;
|
||||||
}
|
}
|
||||||
reguser.update({ minecraftname, minecraftid });
|
reguser.update({ minecraftname, minecraftid });
|
||||||
|
@ -95,8 +97,11 @@ class Minecraft {
|
||||||
|
|
||||||
minecraftname2User(minecraftname: string): User {
|
minecraftname2User(minecraftname: string): User {
|
||||||
const searchstring = minecraftname;
|
const searchstring = minecraftname;
|
||||||
for (const [minecraftid, user] of Object.entries(this.online)) {
|
const onlineIds = Object.keys(this.online);
|
||||||
if (user.minecraftname == searchstring) { return user; }
|
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();
|
const user = new User();
|
||||||
|
|
|
@ -62,7 +62,7 @@ async function exportVox(
|
||||||
return zc - 1;
|
return zc - 1;
|
||||||
}
|
}
|
||||||
const zcMax = zc + VOX_OBJECT_CSIZE / 2 + 1;
|
const zcMax = zc + VOX_OBJECT_CSIZE / 2 + 1;
|
||||||
return (zcMin <= posMax) ? zcMax : zc;
|
return (zcMax <= posMax) ? zcMax : zc;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Size Chunk
|
// Size Chunk
|
||||||
|
@ -79,7 +79,7 @@ async function exportVox(
|
||||||
// 4 bytes numVoxels
|
// 4 bytes numVoxels
|
||||||
// 4 bytes (x, y, z, clr) for every voxel
|
// 4 bytes (x, y, z, clr) for every voxel
|
||||||
let numVoxels = 0;
|
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) {
|
for (let i = xcMin; i <= xcMax; i += 1) {
|
||||||
const key = `${i}:${j}`;
|
const key = `${i}:${j}`;
|
||||||
const { buffer } = chunks.get(key);
|
const { buffer } = chunks.get(key);
|
||||||
|
|
|
@ -18,6 +18,7 @@ export type GUIState = {
|
||||||
paletteOpen: boolean,
|
paletteOpen: boolean,
|
||||||
menuOpen: boolean,
|
menuOpen: boolean,
|
||||||
chatChannel: number,
|
chatChannel: number,
|
||||||
|
style: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialState: GUIState = {
|
const initialState: GUIState = {
|
||||||
|
@ -33,6 +34,7 @@ const initialState: GUIState = {
|
||||||
paletteOpen: true,
|
paletteOpen: true,
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
chatChannel: 0,
|
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': {
|
case 'SET_CHAT_CHANNEL': {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|
|
@ -8,13 +8,11 @@ import type { Action } from '../actions/types';
|
||||||
|
|
||||||
export type ModalState = {
|
export type ModalState = {
|
||||||
modalType: ?string,
|
modalType: ?string,
|
||||||
modalProps: object,
|
|
||||||
chatOpen: boolean,
|
chatOpen: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialState: ModalState = {
|
const initialState: ModalState = {
|
||||||
modalType: null,
|
modalType: null,
|
||||||
modalProps: {},
|
|
||||||
chatOpen: false,
|
chatOpen: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,12 +25,11 @@ export default function modal(
|
||||||
// clear hover when placing a pixel
|
// clear hover when placing a pixel
|
||||||
// fixes a bug with iPad
|
// fixes a bug with iPad
|
||||||
case 'SHOW_MODAL': {
|
case 'SHOW_MODAL': {
|
||||||
const { modalType, modalProps } = action;
|
const { modalType } = action;
|
||||||
const chatOpen = (modalType === 'CHAT') ? false : state.chatOpen;
|
const chatOpen = (modalType === 'CHAT') ? false : state.chatOpen;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
modalType,
|
modalType,
|
||||||
modalProps,
|
|
||||||
chatOpen,
|
chatOpen,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -42,7 +39,6 @@ export default function modal(
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
modalType: null,
|
modalType: null,
|
||||||
modalProps: {},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
case 'TOGGLE_CHAT_BOX': {
|
case 'TOGGLE_CHAT_BOX': {
|
||||||
|
|
|
@ -19,7 +19,7 @@ function validate(newPassword) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async (req: Request, res: Response) => {
|
export default async (req: Request, res: Response) => {
|
||||||
const { new_password: newPassword, password } = req.body;
|
const { newPassword, password } = req.body;
|
||||||
const errors = validate(newPassword);
|
const errors = validate(newPassword);
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
res.status(400);
|
res.status(400);
|
||||||
|
|
|
@ -45,23 +45,35 @@ router.use(bodyParser.urlencoded({ extended: true }));
|
||||||
* Check for POST parameters,
|
* Check for POST parameters,
|
||||||
* if invalid password is given, ignore it and go to next
|
* 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;
|
const { pass, passconf, code } = req.body;
|
||||||
if (!pass || !passconf || !code) {
|
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);
|
res.status(400).send(html);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const email = mailProvider.checkCode(code);
|
const email = mailProvider.checkCode(code);
|
||||||
if (!email) {
|
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);
|
res.status(401).send(html);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pass != passconf) {
|
if (pass !== passconf) {
|
||||||
const html = getPasswordResetHtml(null, null, 'Your passwords do not match :(');
|
const html = getPasswordResetHtml(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'Your passwords do not match :(',
|
||||||
|
);
|
||||||
res.status(400).send(html);
|
res.status(400).send(html);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -69,15 +81,24 @@ router.post('/', async (req: Request, res: Response, next) => {
|
||||||
// set password
|
// set password
|
||||||
const reguser = await RegUser.findOne({ where: { email } });
|
const reguser = await RegUser.findOne({ where: { email } });
|
||||||
if (!reguser) {
|
if (!reguser) {
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
logger.error(`${email} from PasswordReset page does not exist in database`);
|
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);
|
res.status(400).send(html);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await reguser.update({ password: pass });
|
await reguser.update({ password: pass });
|
||||||
|
|
||||||
logger.info(`Changed password of ${email} via passowrd reset form`);
|
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);
|
res.status(200).send(html);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -85,17 +106,26 @@ router.post('/', async (req: Request, res: Response, next) => {
|
||||||
/*
|
/*
|
||||||
* Check GET parameters for action to execute
|
* 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;
|
const { token } = req.query;
|
||||||
if (!token) {
|
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);
|
res.status(400).send(html);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const email = mailProvider.checkCode(token);
|
const email = mailProvider.checkCode(token);
|
||||||
if (!email) {
|
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);
|
res.status(401).send(html);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ class APISocketServer extends WebSocketEvents {
|
||||||
logger.info(`APISocket message ${message}`);
|
logger.info(`APISocket message ${message}`);
|
||||||
if (command === 'login') {
|
if (command === 'login') {
|
||||||
const [minecraftid, minecraftname, ip] = packet;
|
const [minecraftid, minecraftname, ip] = packet;
|
||||||
const user = await this.mc.report_login(minecraftid, minecraftname);
|
const user = await this.mc.reportLogin(minecraftid, minecraftname);
|
||||||
// get userinfo
|
// get userinfo
|
||||||
user.ip = ip;
|
user.ip = ip;
|
||||||
const wait = await user.getWait(0);
|
const wait = await user.getWait(0);
|
||||||
|
@ -234,12 +234,12 @@ class APISocketServer extends WebSocketEvents {
|
||||||
logger.error('Got invalid minecraft userlist on APISocketServer');
|
logger.error('Got invalid minecraft userlist on APISocketServer');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.mc.report_userlist(userlist);
|
this.mc.reportUserlist(userlist);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (command === 'logout') {
|
if (command === 'logout') {
|
||||||
const [minecraftid] = packet;
|
const [minecraftid] = packet;
|
||||||
this.mc.report_logout(minecraftid);
|
this.mc.reportLogout(minecraftid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (command === 'mcchat') {
|
if (command === 'mcchat') {
|
||||||
|
@ -260,7 +260,7 @@ class APISocketServer extends WebSocketEvents {
|
||||||
}
|
}
|
||||||
if (command === 'linkacc') {
|
if (command === 'linkacc') {
|
||||||
const [minecraftid, minecraftname, name] = packet;
|
const [minecraftid, minecraftname, name] = packet;
|
||||||
const ret = await this.mc.linkacc(minecraftid, minecraftname, name);
|
const ret = await Minecraft.linkacc(minecraftid, minecraftname, name);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
webSockets.notifyChangedMe(name);
|
webSockets.notifyChangedMe(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// allow the websocket to be noisy on the console
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
|
|
||||||
import CoolDownPacket from './packets/CoolDownPacket';
|
import CoolDownPacket from './packets/CoolDownPacket';
|
||||||
|
@ -44,9 +47,9 @@ class ProtocolClient extends EventEmitter {
|
||||||
console.log('WebSocket already open, not starting');
|
console.log('WebSocket already open, not starting');
|
||||||
}
|
}
|
||||||
this.timeConnected = Date.now();
|
this.timeConnected = Date.now();
|
||||||
const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||||
const url = `${protocol}//${location.hostname}${
|
const url = `${protocol}//${window.location.hostname}${
|
||||||
location.port ? `:${location.port}` : ''
|
window.location.port ? `:${window.location.port}` : ''
|
||||||
}/ws`;
|
}/ws`;
|
||||||
this.ws = new WebSocket(url);
|
this.ws = new WebSocket(url);
|
||||||
this.ws.binaryType = 'arraybuffer';
|
this.ws.binaryType = 'arraybuffer';
|
||||||
|
|
|
@ -9,6 +9,7 @@ import audio from './audio';
|
||||||
import swal from './sweetAlert';
|
import swal from './sweetAlert';
|
||||||
import protocolClientHook from './protocolClientHook';
|
import protocolClientHook from './protocolClientHook';
|
||||||
import rendererHook from './rendererHook';
|
import rendererHook from './rendererHook';
|
||||||
|
import styleHook from './styleHook';
|
||||||
// import ads from './ads';
|
// import ads from './ads';
|
||||||
// import analytics from './analytics';
|
// import analytics from './analytics';
|
||||||
import array from './array';
|
import array from './array';
|
||||||
|
@ -40,6 +41,7 @@ const store = createStore(
|
||||||
title,
|
title,
|
||||||
protocolClientHook,
|
protocolClientHook,
|
||||||
rendererHook,
|
rendererHook,
|
||||||
|
styleHook,
|
||||||
// ads,
|
// ads,
|
||||||
// analytics,
|
// analytics,
|
||||||
logger,
|
logger,
|
||||||
|
@ -49,7 +51,9 @@ const store = createStore(
|
||||||
|
|
||||||
|
|
||||||
export default function configureStore(onComplete: ?() => void) {
|
export default function configureStore(onComplete: ?() => void) {
|
||||||
persistStore(store, null, onComplete);
|
persistStore(store, null, () => {
|
||||||
|
onComplete(store);
|
||||||
|
});
|
||||||
if (isDebuggingInChrome) {
|
if (isDebuggingInChrome) {
|
||||||
window.store = store;
|
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 swal from 'sweetalert2';
|
||||||
import 'sweetalert2/src/sweetalert2.scss';
|
|
||||||
|
|
||||||
export default () => (next) => (action) => {
|
export default () => (next) => (action) => {
|
||||||
switch (action.type) {
|
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;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.modallink) {
|
.modallink {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #428bca;
|
color: #428bca;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
:global(.modallink:hover){
|
.modallink:hover){
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #226baa;
|
color: #226baa;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.inarea) {
|
.inarea {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: #d5d5d5;
|
border-color: #d5d5d5;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
@ -56,41 +56,41 @@ kbd {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.tab-list) {
|
.tab-list {
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.tab-list-item) {
|
.tab-list-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
padding: 0.5rem 0.75rem;
|
padding: 0.5rem 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.tab-list-active) {
|
.tab-list-active {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: solid #ccc;
|
border: solid #ccc;
|
||||||
border-width: 1px 1px 0 1px;
|
border-width: 1px 1px 0 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(table) {
|
table {
|
||||||
font-family: arial, sans-serif;
|
font-family: arial, sans-serif;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(td, th) {
|
td, th {
|
||||||
border: 1px solid #dddddd;
|
border: 1px solid #dddddd;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(tr:nth-child(even)) {
|
tr:nth-child(even) {
|
||||||
background-color: #dddddd;
|
background-color: #dddddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.chatbox) {
|
.chatbox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(226, 226, 226, 0.92);
|
background-color: rgba(226, 226, 226, 0.92);
|
||||||
width: 350px;
|
width: 350px;
|
||||||
|
@ -101,7 +101,7 @@ kbd {
|
||||||
border-width: thin;
|
border-width: thin;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.actionbuttons), :global(.coorbox), :global(.onlinebox), :global(.cooldownbox), :global(.palettebox) {
|
.actionbuttons, .coorbox, .onlinebox, .cooldownbox, .palettebox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: rgba(226, 226, 226, 0.80);
|
background-color: rgba(226, 226, 226, 0.80);
|
||||||
color: black;
|
color: black;
|
||||||
|
@ -114,114 +114,202 @@ kbd {
|
||||||
border: solid black;
|
border: solid black;
|
||||||
border-width: thin;
|
border-width: thin;
|
||||||
}
|
}
|
||||||
:global(.coorbox) {
|
.coorbox {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
bottom: 16px;
|
bottom: 16px;
|
||||||
}
|
}
|
||||||
:global(.onlinebox) {
|
.onlinebox {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
bottom: 57px;
|
bottom: 57px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#menubutton) {
|
#menubutton {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#menu > div) {
|
#menu > div {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
background-color: rgb(213, 238, 255);
|
background-color: rgb(213, 238, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#helpbutton) {
|
#helpbutton {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 221px;
|
top: 221px;
|
||||||
}
|
}
|
||||||
:global(#minecraftbutton) {
|
#minecraftbutton {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 180px;
|
top: 180px;
|
||||||
}
|
}
|
||||||
:global(#settingsbutton) {
|
#settingsbutton {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 57px;
|
top: 57px;
|
||||||
}
|
}
|
||||||
:global(#loginbutton) {
|
#loginbutton {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 98px;
|
top: 98px;
|
||||||
}
|
}
|
||||||
:global(#downloadbutton) {
|
#downloadbutton {
|
||||||
left: 16px;
|
left: 16px;
|
||||||
top: 139px;
|
top: 139px;
|
||||||
}
|
}
|
||||||
:global(#globebutton) {
|
#globebutton {
|
||||||
left: 98px;
|
left: 98px;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
}
|
}
|
||||||
:global(#voxelbutton) {
|
#voxelbutton {
|
||||||
left: 180px;
|
left: 180px;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
}
|
}
|
||||||
:global(#canvasbutton) {
|
#canvasbutton {
|
||||||
left: 57px;
|
left: 57px;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
}
|
}
|
||||||
:global(#minecrafttpbutton) {
|
#minecrafttpbutton {
|
||||||
top: 16px;
|
top: 16px;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
}
|
}
|
||||||
:global(#palselbutton) {
|
#palselbutton {
|
||||||
bottom: 16px;
|
bottom: 16px;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
}
|
}
|
||||||
:global(#chatbutton) {
|
#chatbutton {
|
||||||
bottom: 16px;
|
bottom: 16px;
|
||||||
right: 57px;
|
right: 57px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#historyselect) {
|
#historyselect {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 16px;
|
top: 16px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
width: 140px;
|
width: 140px;
|
||||||
background-color: rgba(226, 226, 226, 0.80);
|
background-color: rgba(226, 226, 226, 0.80);
|
||||||
color: black;
|
color: black;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: solid black;
|
border: solid black;
|
||||||
border-width: thin;
|
border-width: thin;
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
:global(.hsar) {
|
|
||||||
|
.hsar {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.Modal) {
|
.Modal {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
right: auto;
|
right: auto;
|
||||||
bottom: auto;
|
bottom: auto;
|
||||||
border: 1px solid rgb(204, 204, 204);
|
border: 1px solid rgb(204, 204, 204);
|
||||||
background: rgb(255, 255, 255) none repeat scroll 0% 0%;
|
background: rgb(255, 255, 255) none repeat scroll 0% 0%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
outline: currentcolor none medium;
|
outline: currentcolor none medium;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
height: 80%;
|
height: 80%;
|
||||||
max-height: 900px;
|
max-height: 900px;
|
||||||
width: 70%;
|
width: 70%;
|
||||||
transition: all 0.5s ease 0s;
|
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) {
|
@media (max-width: 604px) {
|
||||||
:global(.Modal) {
|
.Modal {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
@ -235,7 +323,7 @@ kbd {
|
||||||
padding: 5%;
|
padding: 5%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
:global(.Overlay) {
|
.Overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
@ -245,54 +333,51 @@ kbd {
|
||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.chatbox div .chatarea ) {
|
.chatbox div .chatarea {
|
||||||
height: 174px;
|
height: 174px;
|
||||||
}
|
}
|
||||||
:global(.chatarea) {
|
.chatarea {
|
||||||
padding: 3px 3px 0px 3px;
|
padding: 3px 3px 0px 3px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
height: 95%;
|
height: 95%;
|
||||||
}
|
}
|
||||||
:global(.Modal div chatarea) {
|
.chatinput {
|
||||||
max-height: 600px;
|
|
||||||
}
|
|
||||||
:global(.chatinput) {
|
|
||||||
height: 22px;
|
height: 22px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
:global(.chatname) {
|
.chatname {
|
||||||
color: #4B0000;
|
color: #4B0000;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
user-select: all;
|
user-select: all;
|
||||||
}
|
}
|
||||||
:global(.chatmsg) {
|
.chatmsg {
|
||||||
color: #030303;
|
color: #030303;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.usermessages) {
|
.usermessages {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
:global(.stattext) {
|
.stattext {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
:global(.statvalue) {
|
.statvalue {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #2d0045;
|
color: #2d0045;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.pressed) {
|
.pressed {
|
||||||
box-shadow:0 0 3px 2px rgba(0,0,0,.6);
|
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);
|
background-color: rgba(226, 226, 226, 0.80);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 57px;
|
top: 57px;
|
||||||
|
@ -313,18 +398,18 @@ kbd {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.notifyboxvis) {
|
.notifyboxvis {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: visibility 0s, opacity 0.5s linear;
|
transition: visibility 0s, opacity 0.5s linear;
|
||||||
}
|
}
|
||||||
:global(.notifyboxhid) {
|
.notifyboxhid {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: visibility 0.5s, opacity 0.5s linear;
|
transition: visibility 0.5s, opacity 0.5s linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.cooldownbox) {
|
.cooldownbox {
|
||||||
top: 16px;
|
top: 16px;
|
||||||
width: 48px;
|
width: 48px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
@ -334,18 +419,18 @@ kbd {
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.actionbuttons) {
|
.actionbuttons {
|
||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
width: 36px;
|
width: 36px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.actionbuttons:hover) {
|
.actionbuttons:hover, .coorbox:hover, #menu > div:hover {
|
||||||
background-color: #d2d2d2cc;
|
background-color: #d2d2d2cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.palettebox) {
|
.palettebox {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
bottom: 59px;
|
bottom: 59px;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
|
@ -355,8 +440,8 @@ kbd {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#colors) :global(.selected),
|
#colors .selected,
|
||||||
:global(#colors) span:hover {
|
#colors span:hover {
|
||||||
z-index: 2 !important;
|
z-index: 2 !important;
|
||||||
outline: rgb(234, 234, 234) solid 1px;
|
outline: rgb(234, 234, 234) solid 1px;
|
||||||
box-shadow: rgba(0, 0, 0, 0.80) 0px 0px 5px 2px;
|
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 */
|
transform: scale(1.10,1.10); /* Standard syntax */
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#outstreamContainer) {
|
#outstreamContainer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: none;
|
display: none;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -378,6 +463,6 @@ kbd {
|
||||||
z-index: 9000;
|
z-index: 9000;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.grecaptcha-badge) {
|
.grecaptcha-badge {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
|
@ -6,13 +6,13 @@ body {
|
||||||
font-family: Montserrat,sans-serif;
|
font-family: Montserrat,sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.tm) {
|
.tm {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10px;
|
top: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(.webgl-error) {
|
.webgl-error {
|
||||||
font: 15px/30px monospace;
|
font: 15px/30px monospace;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
@ -20,12 +20,12 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
:global(.webgl-error) a {
|
.webgl-error a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
:global(#coorbox) {
|
#coorbox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: hsla(0,0%,89%,.8);
|
background-color: hsla(0,0%,89%,.8);
|
||||||
color: #000;
|
color: #000;
|
||||||
|
@ -42,7 +42,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
:global(#info) {
|
#info {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: hsla(0,0%,89%,.8);
|
background-color: hsla(0,0%,89%,.8);
|
||||||
|
@ -59,7 +59,7 @@ body {
|
||||||
top: 16px
|
top: 16px
|
||||||
}
|
}
|
||||||
|
|
||||||
:global(#loading) {
|
#loading {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
position: absolute;
|
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,
|
canvasSize,
|
||||||
) {
|
) {
|
||||||
pixelNotify.updateScale(viewscale);
|
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;
|
tiledScale = 4 ** tiledScale;
|
||||||
const tiledZoom = canvasMaxTiledZoom + Math.log2(tiledScale) / 2;
|
const tiledZoom = canvasMaxTiledZoom + Math.log2(tiledScale) / 2;
|
||||||
const relScale = viewscale / tiledScale;
|
const relScale = viewscale / tiledScale;
|
||||||
|
@ -174,7 +176,11 @@ class Renderer {
|
||||||
updateView(view, canvasSize) {
|
updateView(view, canvasSize) {
|
||||||
const [x, y] = view;
|
const [x, y] = view;
|
||||||
let [cx, cy] = this.centerChunk;
|
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) {
|
if (cx !== curcx || cy !== curcy) {
|
||||||
cx = curcx;
|
cx = curcx;
|
||||||
cy = curcy;
|
cy = curcy;
|
||||||
|
@ -233,8 +239,12 @@ class Renderer {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const { width, height } = this.viewport;
|
const { width, height } = this.viewport;
|
||||||
const CHUNK_RENDER_RADIUS_X = Math.ceil(width / TILE_SIZE / 2 / this.relScale);
|
const CHUNK_RENDER_RADIUS_X = Math.ceil(
|
||||||
const CHUNK_RENDER_RADIUS_Y = Math.ceil(height / TILE_SIZE / 2 / this.relScale);
|
width / TILE_SIZE / 2 / this.relScale,
|
||||||
|
);
|
||||||
|
const CHUNK_RENDER_RADIUS_Y = Math.ceil(
|
||||||
|
height / TILE_SIZE / 2 / this.relScale,
|
||||||
|
);
|
||||||
const [xc, yc] = this.centerChunk;
|
const [xc, yc] = this.centerChunk;
|
||||||
if (Math.abs(cx - xc)
|
if (Math.abs(cx - xc)
|
||||||
<= CHUNK_RENDER_RADIUS_X && Math.abs(cy - yc)
|
<= CHUNK_RENDER_RADIUS_X && Math.abs(cy - yc)
|
||||||
|
@ -450,15 +460,21 @@ class Renderer {
|
||||||
viewportCtx.scale(viewscale, viewscale);
|
viewportCtx.scale(viewscale, viewscale);
|
||||||
viewportCtx.drawImage(
|
viewportCtx.drawImage(
|
||||||
this.canvas,
|
this.canvas,
|
||||||
width / 2 / viewscale - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
width / 2 / viewscale - CANVAS_WIDTH / 2 + (
|
||||||
height / 2 / viewscale - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
(cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
||||||
|
height / 2 / viewscale - CANVAS_HEIGHT / 2 + (
|
||||||
|
(cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
||||||
);
|
);
|
||||||
viewportCtx.restore();
|
viewportCtx.restore();
|
||||||
} else {
|
} else {
|
||||||
viewportCtx.drawImage(
|
viewportCtx.drawImage(
|
||||||
this.canvas,
|
this.canvas,
|
||||||
Math.floor(width / 2 - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - x) * viewscale),
|
Math.floor(width / 2 - CANVAS_WIDTH / 2
|
||||||
Math.floor(height / 2 - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE / this.tiledScale - canvasCenter - y) * viewscale),
|
+ ((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.scale(viewscale, viewscale);
|
||||||
viewportCtx.drawImage(
|
viewportCtx.drawImage(
|
||||||
this.canvas,
|
this.canvas,
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
width / 2 / viewscale - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x),
|
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),
|
height / 2 / viewscale - CANVAS_HEIGHT / 2 + ((cy + 0.5) * TILE_SIZE - canvasCenter - y),
|
||||||
);
|
);
|
||||||
viewportCtx.restore();
|
viewportCtx.restore();
|
||||||
} else {
|
} else {
|
||||||
viewportCtx.drawImage(
|
viewportCtx.drawImage(
|
||||||
this.canvas,
|
this.canvas,
|
||||||
|
// eslint-disable-next-line max-len
|
||||||
Math.floor(width / 2 - CANVAS_WIDTH / 2 + ((cx + 0.5) * TILE_SIZE - canvasCenter - x) * viewscale),
|
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),
|
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 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;
|
export default store;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import run from './run';
|
import run from './run';
|
||||||
import clean from './clean';
|
import clean from './clean';
|
||||||
import copy from './copy';
|
import copy from './copy';
|
||||||
|
import minifyCss from './minifyCss';
|
||||||
import bundle from './bundle';
|
import bundle from './bundle';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +21,7 @@ import bundle from './bundle';
|
||||||
async function build() {
|
async function build() {
|
||||||
await run(clean);
|
await run(clean);
|
||||||
await run(copy);
|
await run(copy);
|
||||||
|
await run(minifyCss);
|
||||||
await run(bundle);
|
await run(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ function bundle() {
|
||||||
fileContent = fileContent.replace(regex, 'core-js/features/set-immediate');
|
fileContent = fileContent.replace(regex, 'core-js/features/set-immediate');
|
||||||
fs.writeFileSync(file, fileContent);
|
fs.writeFileSync(file, fileContent);
|
||||||
});
|
});
|
||||||
|
console.log('Pathing image-q done');
|
||||||
} catch {
|
} catch {
|
||||||
console.log('Error while patching image-q');
|
console.log('Error while patching image-q');
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ import pkg from '../package.json';
|
||||||
*/
|
*/
|
||||||
async function copy() {
|
async function copy() {
|
||||||
await makeDir('build');
|
await makeDir('build');
|
||||||
await makeDir('build/log');
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
makeDir('build/log'),
|
||||||
copyFile('LICENSE', 'build/LICENSE'),
|
copyFile('LICENSE', 'build/LICENSE'),
|
||||||
copyDir('public', 'build/public'),
|
copyDir('public', 'build/public'),
|
||||||
copyFile('src/canvases.json', 'build/canvases.json'),
|
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.yml', 'build/ecosystem.example.yml'),
|
||||||
copyFile('tools/example-ecosystem-backup.yml', 'build/ecosystem-backup.example.yml'),
|
copyFile('tools/example-ecosystem-backup.yml', 'build/ecosystem-backup.example.yml'),
|
||||||
]);
|
]);
|
||||||
|
await makeDir('build/public/assets');
|
||||||
}
|
}
|
||||||
|
|
||||||
export default copy;
|
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: {
|
module: {
|
||||||
rules: [
|
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$/,
|
test: /\.svg$/,
|
||||||
use: [
|
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/,
|
test: /\.scss/,
|
||||||
use: [
|
use: [
|
||||||
|
@ -165,20 +96,6 @@ const config = {
|
||||||
'sass-loader',
|
'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$/,
|
test: /\.md$/,
|
||||||
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
|
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
|
||||||
|
@ -242,6 +159,81 @@ const clientConfig = {
|
||||||
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].js',
|
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: [
|
plugins: [
|
||||||
// Define free variables
|
// Define free variables
|
||||||
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
||||||
|
@ -315,26 +307,85 @@ const webConfig = {
|
||||||
...config.module,
|
...config.module,
|
||||||
|
|
||||||
// Override babel-preset-env configuration for Node.js
|
// Override babel-preset-env configuration for Node.js
|
||||||
rules: config.module.rules.map((rule) => (rule.loader !== 'babel-loader' ? rule : {
|
rules: [
|
||||||
...rule,
|
...config.module.rules,
|
||||||
query: {
|
{
|
||||||
...rule.query,
|
test: /\.(js|jsx|ts|tsx)$/,
|
||||||
presets: rule.query.presets.map((preset) => (preset[0] !== '@babel/preset-env' ? preset : ['@babel/preset-env', {
|
loader: 'babel-loader',
|
||||||
targets: {
|
include: [
|
||||||
node: pkg.engines.node.replace(/^\D+/g, ''),
|
path.resolve(__dirname, '../src'),
|
||||||
},
|
],
|
||||||
modules: false,
|
query: {
|
||||||
useBuiltIns: false,
|
// https://github.com/babel/babel-loader#options
|
||||||
debug: false,
|
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
|
// needed because webpack tries to pack socket.io
|
||||||
externals: [
|
externals: [
|
||||||
/\/proxies\.json$/,
|
/\/proxies\.json$/,
|
||||||
/\/canvases\.json$/,
|
/\/canvases\.json$/,
|
||||||
|
/^\.\/styleassets\.json$/,
|
||||||
/^\.\/assets\.json$/,
|
/^\.\/assets\.json$/,
|
||||||
(context, request, callback) => {
|
(context, request, callback) => {
|
||||||
const isExternal = request.match(/^[@a-z][a-z/.\-0-9]*$/i)
|
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]
|
x = unpack_from('B', message, 1)[0]
|
||||||
y = unpack_from('B', message, 2)[0]
|
y = unpack_from('B', message, 2)[0]
|
||||||
a = unpack_from('!h', message, 4)[0]
|
a = unpack_from('!h', message, 4)[0]
|
||||||
if x != 10000 and y != 10000:
|
|
||||||
return
|
|
||||||
color = int(unpack_from('!B', message, 6)[0])
|
color = int(unpack_from('!B', message, 6)[0])
|
||||||
if color == 0:
|
if color == 0:
|
||||||
color = 19
|
color = 19
|
||||||
|
@ -29,6 +27,8 @@ def on_message(ws, message):
|
||||||
number = (65520 & a) >> 4
|
number = (65520 & a) >> 4
|
||||||
x = int(x * 256 + a % 256 - 256 * 256 / 2)
|
x = int(x * 256 + a % 256 - 256 * 256 / 2)
|
||||||
y = int(y * 256 + a // 256 + 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)))
|
print('Pixel Received: @%s,%s - color %s' % (str(x), str(y), str(color)))
|
||||||
|
|
||||||
def on_error(ws, error):
|
def on_error(ws, error):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user