diff --git a/package-lock.json b/package-lock.json index 98bbaa0..f25eee4 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 4dbea75..e357aa7 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 0eb8333..42cf06a 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 52b20a7..5b75cd4 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 0000000..c18ee30 --- /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) && ( +
+
+

{alertTitle}

+

+ {alertMessage} +

+

+ +

+
+
+ ) + ); +}; + +export default React.memo(Alert); diff --git a/src/components/Captcha.jsx b/src/components/Captcha.jsx index 220a461..78f97f8 100644 --- a/src/components/Captcha.jsx +++ b/src/components/Captcha.jsx @@ -7,6 +7,5 @@ import { t } from 'ttag'; const Captcha = ({ }) => ( -
-
+ div /> ); diff --git a/src/components/ChatBox.jsx b/src/components/ChatBox.jsx index b9adaf8..0fa3c12 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 2320d68..91b3783 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 0000000..30e7eda --- /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 0ad4c09..c62e651 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 fc87936..3c307d5 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 6303411..401c2de 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 72bbd8d..0000000 --- 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 6cab70e..97318f5 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; }