diff --git a/package-lock.json b/package-lock.json
index 98bbaa0b..f25eee47 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9074,11 +9074,6 @@
}
}
},
- "sweetalert2": {
- "version": "10.14.0",
- "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-10.14.0.tgz",
- "integrity": "sha512-EBUh4k9qyRRsttm9X9j7WUhLExetvTJpcbp1VTMJCpuI2UwHLesXMIw9M+UeuqBywv0UjNMR5PKH7Qnv65m8rw=="
- },
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
diff --git a/package.json b/package.json
index 4dbea75e..e357aa7c 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"main": "server.js",
"scripts": {
"build": "babel-node scripts/run prebuild && npm run webpack",
+ "build-en": "babel-node scripts/run prebuild && npm run extract",
"clean": "babel-node scripts/run clean",
"webpack": "webpack --config ./webpack.config.web.babel.js && parallel-webpack --config ./webpack.config.client.babel.js",
"extract": "webpack --env extract --config ./webpack.config.web.babel.js && webpack --env extract --config ./webpack.config.client.babel.js",
@@ -76,7 +77,6 @@
"sequelize": "^6.5.0",
"sharp": "^0.27.1",
"startaudiocontext": "^1.2.1",
- "sweetalert2": "^10.14.0",
"three": "^0.125.2",
"three-trackballcontrols": "^0.9.0",
"ttag": "^1.7.24",
diff --git a/src/actions/index.js b/src/actions/index.js
index 0eb83337..42cf06a7 100644
--- a/src/actions/index.js
+++ b/src/actions/index.js
@@ -29,6 +29,12 @@ export function sweetAlert(
};
}
+export function closeAlert(): Action {
+ return {
+ type: 'CLOSE_ALERT',
+ };
+}
+
export function toggleChatBox(): Action {
return {
type: 'TOGGLE_CHAT_BOX',
diff --git a/src/actions/types.js b/src/actions/types.js
index 52b20a7b..5b75cd43 100644
--- a/src/actions/types.js
+++ b/src/actions/types.js
@@ -14,6 +14,7 @@ export type Action =
icon: string,
confirmButtonText: string,
}
+ | { type: 'CLOSE_ALERT' }
| { type: 'TOGGLE_GRID' }
| { type: 'TOGGLE_PIXEL_NOTIFY' }
| { type: 'TOGGLE_AUTO_ZOOM_IN' }
diff --git a/src/components/Alert.jsx b/src/components/Alert.jsx
new file mode 100644
index 00000000..c18ee30f
--- /dev/null
+++ b/src/components/Alert.jsx
@@ -0,0 +1,70 @@
+/*
+ *
+ * @flow
+ */
+
+import React, { useState, useEffect } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+
+import { closeAlert } from '../actions';
+
+const Alert = () => {
+ const [render, setRender] = useState(false);
+
+ const {
+ alertOpen,
+ alertType,
+ alertTitle,
+ alertMessage,
+ alertBtn,
+ } = useSelector((state) => state.alert);
+
+ const dispatch = useDispatch();
+ const close = () => {
+ dispatch(closeAlert());
+ };
+
+ const onTransitionEnd = () => {
+ if (!alertOpen) setRender(false);
+ };
+
+ useEffect(() => {
+ window.setTimeout(() => {
+ if (alertOpen) setRender(true);
+ }, 10);
+ }, [alertOpen]);
+
+ return (
+ (render || alertOpen) && (
+
-
+ div />
);
diff --git a/src/components/ChatBox.jsx b/src/components/ChatBox.jsx
index b9adaf86..0fa3c12c 100644
--- a/src/components/ChatBox.jsx
+++ b/src/components/ChatBox.jsx
@@ -4,34 +4,34 @@
*/
import React, { useEffect, useState } from 'react';
-import { connect } from 'react-redux';
+import { useSelector, useDispatch } from 'react-redux';
-import type { State } from '../reducers';
import useWindowSize from '../utils/reactHookResize';
import { showChatModal } from '../actions';
import Chat from './Chat';
-function ChatBox({
- chatOpen,
- triggerModal,
-}) {
+const ChatBox = () => {
const [render, setRender] = useState(false);
+ const chatOpen = useSelector((state) => state.modal.chatOpen);
+
+ const dispatch = useDispatch();
+
useEffect(() => {
window.setTimeout(() => {
if (chatOpen) setRender(true);
}, 10);
}, [chatOpen]);
- const onTransitionEnd = () => {
+ const onTransitionEnd =() => {
if (!chatOpen) setRender(false);
};
const { width } = useWindowSize();
if (width < 604 && chatOpen) {
- triggerModal();
+ dispatch(showChatModal(true));
}
return (
@@ -46,17 +46,4 @@ function ChatBox({
);
}
-function mapStateToProps(state: State) {
- const { chatOpen } = state.modal;
- return { chatOpen };
-}
-
-function mapDispatchToProps(dispatch) {
- return {
- triggerModal() {
- dispatch(showChatModal(true));
- },
- };
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(ChatBox);
+export default React.memo(ChatBox);
diff --git a/src/components/UI.jsx b/src/components/UI.jsx
index 2320d686..91b3783e 100644
--- a/src/components/UI.jsx
+++ b/src/components/UI.jsx
@@ -12,6 +12,7 @@ import NotifyBox from './NotifyBox';
import GlobeButton from './GlobeButton';
import PalselButton from './PalselButton';
import Palette from './Palette';
+import Alert from './Alert';
import HistorySelect from './HistorySelect';
import Mobile3DControls from './Mobile3DControls';
import UserContextMenu from './UserContextMenu';
@@ -41,13 +42,14 @@ const UI = ({
}
return (
+
- {(is3D) ? null :
}
- {(is3D && isOnMobile) ?
: null}
+ {(!is3D) &&
}
+ {(is3D && isOnMobile) &&
}
- {(menuOpen && menuType) ? CONTEXT_MENUS[menuType] : null}
+ {(menuOpen && menuType) && CONTEXT_MENUS[menuType]}
);
};
diff --git a/src/reducers/alert.js b/src/reducers/alert.js
new file mode 100644
index 00000000..30e7eda0
--- /dev/null
+++ b/src/reducers/alert.js
@@ -0,0 +1,51 @@
+/* @flow */
+
+import type { Action } from '../actions/types';
+
+export type AlertState = {
+ alertOpen: boolean,
+ alertType: ?string,
+ alertTitle: ?string,
+ alertMessage: ?string,
+ alertBtn: ?string,
+};
+
+const initialState: AlertState = {
+ alertOpen: false,
+ alertType: null,
+ alertTitle: null,
+ alertMessage: null,
+ alertBtn: null,
+};
+
+export default function alert(
+ state: AlertState = initialState,
+ action: Action,
+): AlertState {
+ switch (action.type) {
+ case 'ALERT': {
+ const {
+ title, text, icon, confirmButtonText,
+ } = action;
+
+ return {
+ ...state,
+ alertOpen: true,
+ alertTitle: title,
+ alertMessage: text,
+ alertType: icon,
+ alertBtn: confirmButtonText,
+ };
+ }
+
+ case 'CLOSE_ALERT': {
+ return {
+ ...state,
+ alertOpen: false,
+ };
+ }
+
+ default:
+ return state;
+ }
+}
diff --git a/src/reducers/index.js b/src/reducers/index.js
index 0ad4c09a..c62e651e 100644
--- a/src/reducers/index.js
+++ b/src/reducers/index.js
@@ -8,6 +8,7 @@ import gui from './gui';
import modal from './modal';
import user from './user';
import ranks from './ranks';
+import alert from './alert';
import chat from './chat';
import contextMenu from './contextMenu';
import chatRead from './chatRead';
@@ -18,6 +19,8 @@ import type { CanvasState } from './canvas';
import type { GUIState } from './gui';
import type { ModalState } from './modal';
import type { UserState } from './user';
+import type { RanksState } from './ranks';
+import type { AlertState } from './alert';
import type { ChatState } from './chat';
import type { ContextMenuState } from './contextMenu';
import type { FetchingState } from './fetching';
@@ -28,6 +31,8 @@ export type State = {
gui: GUIState,
modal: ModalState,
user: UserState,
+ ranks: RanksState,
+ alert: AlertState,
chat: ChatState,
contextMenu: ContextMenuState,
chatRead: ChatReadState,
@@ -41,6 +46,7 @@ const config = {
'user',
'ranks',
'canvas',
+ 'alert',
'modal',
'chat',
'contextMenu',
@@ -55,6 +61,7 @@ export default persistCombineReducers(config, {
modal,
user,
ranks,
+ alert,
chat,
contextMenu,
chatRead,
diff --git a/src/reducers/ranks.js b/src/reducers/ranks.js
index fc879368..3c307d52 100644
--- a/src/reducers/ranks.js
+++ b/src/reducers/ranks.js
@@ -2,7 +2,7 @@
import type { Action } from '../actions/types';
-export type UserState = {
+export type RanksState = {
totalPixels: number,
dailyTotalPixels: number,
ranking: number,
@@ -13,7 +13,7 @@ export type UserState = {
totalDailyRanking: Object,
};
-const initialState: UserState = {
+const initialState: RanksState = {
totalPixels: 0,
dailyTotalPixels: 0,
ranking: 1488,
@@ -24,9 +24,9 @@ const initialState: UserState = {
};
export default function ranks(
- state: UserState = initialState,
+ state: RanksState = initialState,
action: Action,
-): UserState {
+): RanksState {
switch (action.type) {
case 'PLACED_PIXELS': {
let { totalPixels, dailyTotalPixels } = state;
diff --git a/src/store/configureStore.js b/src/store/configureStore.js
index 63034112..401c2dee 100644
--- a/src/store/configureStore.js
+++ b/src/store/configureStore.js
@@ -5,7 +5,6 @@ import thunk from 'redux-thunk';
import { persistStore } from 'redux-persist';
import audio from './audio';
-import swal from './sweetAlert';
import protocolClientHook from './protocolClientHook';
import rendererHook from './rendererHook';
// import ads from './ads';
@@ -25,7 +24,6 @@ const store = createStore(
thunk,
promise,
array,
- swal,
audio,
notifications,
title,
diff --git a/src/store/sweetAlert.js b/src/store/sweetAlert.js
deleted file mode 100644
index 72bbd8d5..00000000
--- a/src/store/sweetAlert.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * @flow
- */
-
-import swal from 'sweetalert2';
-
-export default () => (next) => (action) => {
- switch (action.type) {
- case 'ALERT': {
- const {
- title,
- text,
- icon,
- confirmButtonText,
- } = action;
- swal.fire({
- title,
- text,
- icon,
- confirmButtonText,
- });
- break;
- }
-
- default:
- // nothing
- }
-
- return next(action);
-};
diff --git a/src/styles/default.css b/src/styles/default.css
index 6cab70e1..97318f5f 100644
--- a/src/styles/default.css
+++ b/src/styles/default.css
@@ -322,7 +322,7 @@ tr:nth-child(even) {
padding: 0;
}
-.Modal {
+.Modal, .Alert {
position: fixed;
top: 50%;
left: 50%;
@@ -334,14 +334,21 @@ tr:nth-child(even) {
border-radius: 4px;
outline: currentcolor none medium;
transform: translate(-50%, -50%);
+}
+
+.Modal {
height: 80%;
- max-height: 900px;
width: 70%;
- transition: all 0.5s ease 0s;
+ max-height: 900px;
+}
+
+.Alert {
+ padding: 15px;
+ text-align: center;
}
.modaltext, .modalcotext {
- color: hsla(218, 5%, 47%, .6);
+ color: hsla(0, 0%, 0%, 0.6);
font-size: 14px;
font-weight: 500;
line-height: normal;
@@ -370,7 +377,7 @@ tr:nth-child(even) {
.modaldesc {
box-sizing: border-box;
flex: 1 1 auto;
- color: hsla(218, 5%, 47%, .6);
+ color: hsla(0, 0%, 0%, 0.6);
font-size: 14px;
line-height: 20px;
font-weight: 500;
@@ -397,7 +404,7 @@ tr:nth-child(even) {
}
.modalcvtext {
- color: hsla(218, 5%, 47%, .6);
+ color: hsla(0, 0%, 0%, 0.6);
font-size: 14px;
font-weight: 500;
padding: 0;
@@ -446,6 +453,7 @@ tr:nth-child(even) {
padding: 5%;
}
}
+
.Overlay {
position: fixed;
top: 0px;
@@ -454,6 +462,8 @@ tr:nth-child(even) {
bottom: 0px;
background-color: rgba(255, 255, 255, 0.75);
z-index: 4;
+ opacity: 0;
+ transition: opacity 200ms ease-in-out;
}
.chatbox div .chatarea {
@@ -697,12 +707,7 @@ tr:nth-child(even) {
visibility: hidden;
}
-.ReactModal__Overlay {
- opacity: 0;
- transition: opacity 200ms ease-in-out;
-}
-
-.ReactModal__Overlay--after-open{
+.ReactModal__Overlay--after-open, .Overlay.show {
opacity: 1;
}