move windows to subfolder
This commit is contained in:
parent
7d550d5a20
commit
6d1ad02b26
|
@ -1,5 +1,7 @@
|
||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Action,
|
Action,
|
||||||
ThunkAction,
|
ThunkAction,
|
||||||
|
@ -557,42 +559,62 @@ export function initTimer(): ThunkAction {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showModal(modalType: string): Action {
|
export function showModal(modalType: string, title: string): Action {
|
||||||
return {
|
return openWindow(
|
||||||
type: 'SHOW_MODAL',
|
|
||||||
modalType,
|
modalType,
|
||||||
};
|
title,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showSettingsModal(): Action {
|
export function showSettingsModal(): Action {
|
||||||
return showModal('SETTINGS');
|
return showModal(
|
||||||
|
'SETTINGS',
|
||||||
|
t`Settings`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showUserAreaModal(): Action {
|
export function showUserAreaModal(): Action {
|
||||||
return showModal('USERAREA');
|
return showModal(
|
||||||
}
|
'USERAREA',
|
||||||
|
t`User Area`,
|
||||||
export function showMinecraftModal(): Action {
|
);
|
||||||
return showModal('MINECRAFT');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showRegisterModal(): Action {
|
export function showRegisterModal(): Action {
|
||||||
return showModal('REGISTER');
|
return showModal(
|
||||||
|
'REGISTER',
|
||||||
|
t`Register New Account`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showForgotPasswordModal(): Action {
|
export function showForgotPasswordModal(): Action {
|
||||||
return showModal('FORGOT_PASSWORD');
|
return showModal(
|
||||||
|
'FORGOT_PASSWORD',
|
||||||
|
t`Restore my Password`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showHelpModal(): Action {
|
export function showHelpModal(): Action {
|
||||||
return showModal('HELP');
|
return showModal(
|
||||||
|
'HELP',
|
||||||
|
t`Welcome to PixelPlanet.fun`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
export function showArchiveModal(): Action {
|
export function showArchiveModal(): Action {
|
||||||
return showModal('ARCHIVE');
|
return showModal(
|
||||||
|
'ARCHIVE',
|
||||||
|
t`Canvas Archive`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showCanvasSelectionModal(): Action {
|
export function showCanvasSelectionModal(): Action {
|
||||||
return showModal('CANVAS_SELECTION');
|
return showModal(
|
||||||
|
'CANVAS_SELECTION',
|
||||||
|
t`Canvas Selection`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function showContextMenu(
|
export function showContextMenu(
|
||||||
|
@ -610,6 +632,7 @@ export function showContextMenu(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO CHAT MODAL
|
||||||
export function showChatModal(forceModal: boolean = false): Action {
|
export function showChatModal(forceModal: boolean = false): Action {
|
||||||
if (window.innerWidth > 604 && !forceModal) { return toggleChatBox(); }
|
if (window.innerWidth > 604 && !forceModal) { return toggleChatBox(); }
|
||||||
return showModal('CHAT');
|
return showModal('CHAT');
|
||||||
|
@ -704,6 +727,53 @@ export function addToChatInputMessage(windowId: number, msg: string): Action {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fullscreen means to open as modal
|
||||||
|
*/
|
||||||
|
export function openWindow(
|
||||||
|
windowType: string,
|
||||||
|
title: string,
|
||||||
|
fullscreen: boolean,
|
||||||
|
cloneable: boolean,
|
||||||
|
args: Object,
|
||||||
|
): Action {
|
||||||
|
return {
|
||||||
|
type: 'OPEN_WINDOW',
|
||||||
|
windowType,
|
||||||
|
title,
|
||||||
|
fullscreen,
|
||||||
|
cloneable,
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeWindow(windowId): Action {
|
||||||
|
return {
|
||||||
|
type: 'CLOSE_WINDOW',
|
||||||
|
windowId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cloneWindow(windowId): Action {
|
||||||
|
return {
|
||||||
|
type: 'CLONE_WINDOW',
|
||||||
|
windowId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function maximizeWindow(windowId): Action {
|
||||||
|
return {
|
||||||
|
type: 'MAXIMIZE_WINDOW',
|
||||||
|
windowId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function restoreWindow(): Action {
|
||||||
|
return {
|
||||||
|
type: 'RESTORE_WINDOW',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function moveWindow(windowId, xDiff, yDiff): Action {
|
export function moveWindow(windowId, xDiff, yDiff): Action {
|
||||||
return {
|
return {
|
||||||
type: 'MOVE_WINDOW',
|
type: 'MOVE_WINDOW',
|
||||||
|
@ -713,22 +783,20 @@ export function moveWindow(windowId, xDiff, yDiff): Action {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function openChatWindow(): Action {
|
export function resizeWindow(windowId, xDiff, yDiff): Action {
|
||||||
return {
|
return {
|
||||||
type: 'OPEN_WINDOW',
|
type: 'RESIZE_WINDOW',
|
||||||
windowType: 'CHAT',
|
windowId,
|
||||||
title: 'chat',
|
xDiff,
|
||||||
width: 700,
|
yDiff,
|
||||||
height: 300,
|
|
||||||
xPos: 100,
|
|
||||||
yPos: 100,
|
|
||||||
args: {
|
|
||||||
chatChannel: 1,
|
|
||||||
inputMessage: '',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function openChatWindow(): Action {
|
||||||
|
return openWindow('CHAT', t`Chat`, false, true,
|
||||||
|
{ chatChannel: 1, inputMessage: '' });
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* query: Object with either userId: number or userName: string
|
* query: Object with either userId: number or userName: string
|
||||||
*/
|
*/
|
||||||
|
@ -823,12 +891,6 @@ export function setLeaveChannel(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hideModal(): Action {
|
|
||||||
return {
|
|
||||||
type: 'HIDE_MODAL',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hideContextMenu(): Action {
|
export function hideContextMenu(): Action {
|
||||||
return {
|
return {
|
||||||
type: 'HIDE_CONTEXT_MENU',
|
type: 'HIDE_CONTEXT_MENU',
|
||||||
|
|
|
@ -75,7 +75,19 @@ export type Action =
|
||||||
| { type: 'SET_CHAT_INPUT_MSG', windowId: number, msg: string }
|
| { type: 'SET_CHAT_INPUT_MSG', windowId: number, msg: string }
|
||||||
| { type: 'ADD_CHAT_INPUT_MSG', windowId: number, msg: string }
|
| { type: 'ADD_CHAT_INPUT_MSG', windowId: number, msg: string }
|
||||||
| { type: 'SET_CHAT_FETCHING', fetching: boolean }
|
| { type: 'SET_CHAT_FETCHING', fetching: boolean }
|
||||||
|
| { type: 'OPEN_WINDOW',
|
||||||
|
windowType: string,
|
||||||
|
title: string,
|
||||||
|
fullscreen: boolean,
|
||||||
|
cloneable: boolean,
|
||||||
|
args: Object,
|
||||||
|
}
|
||||||
|
| { type: 'CLOSE_WINDOW', windowId: number }
|
||||||
|
| { type: 'CLONE_WINDOW', windowId: number }
|
||||||
|
| { type: 'MAXIMIZE_WINDOW', windowId: number }
|
||||||
|
| { type: 'RESTORE_WINDOW' }
|
||||||
| { type: 'MOVE_WINDOW', windowId: number, xDiff: number, yDiff: number }
|
| { type: 'MOVE_WINDOW', windowId: number, xDiff: number, yDiff: number }
|
||||||
|
| { type: 'RESIZE_WINDOW', windowId: number, xDiff: number, yDiff: number }
|
||||||
| { type: 'BLOCK_USER', userId: number, userName: string }
|
| { type: 'BLOCK_USER', userId: number, userName: string }
|
||||||
| { type: 'UNBLOCK_USER', userId: number, userName: string }
|
| { type: 'UNBLOCK_USER', userId: number, userName: string }
|
||||||
| { type: 'SET_BLOCKING_DM', blockDm: boolean }
|
| { type: 'SET_BLOCKING_DM', blockDm: boolean }
|
||||||
|
@ -117,14 +129,12 @@ 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 }
|
|
||||||
| { type: 'SHOW_CONTEXT_MENU',
|
| { type: 'SHOW_CONTEXT_MENU',
|
||||||
menuType: string,
|
menuType: string,
|
||||||
xPos: number,
|
xPos: number,
|
||||||
yPos: number,
|
yPos: number,
|
||||||
args: Object,
|
args: Object,
|
||||||
}
|
}
|
||||||
| { type: 'HIDE_MODAL' }
|
|
||||||
| { type: 'HIDE_CONTEXT_MENU' }
|
| { type: 'HIDE_CONTEXT_MENU' }
|
||||||
| { type: 'RELOAD_URL' }
|
| { type: 'RELOAD_URL' }
|
||||||
| { type: 'SET_HISTORICAL_TIME', date: string, time: string }
|
| { type: 'SET_HISTORICAL_TIME', date: string, time: string }
|
||||||
|
|
|
@ -19,7 +19,7 @@ import Menu from './Menu';
|
||||||
import UI from './UI';
|
import UI from './UI';
|
||||||
import ExpandMenuButton from './ExpandMenuButton';
|
import ExpandMenuButton from './ExpandMenuButton';
|
||||||
import ModalRoot from './ModalRoot';
|
import ModalRoot from './ModalRoot';
|
||||||
import WindowsRoot from './WindowsRoot';
|
import WindowManager from './WindowManager';
|
||||||
|
|
||||||
const App = () => (
|
const App = () => (
|
||||||
<div>
|
<div>
|
||||||
|
@ -34,7 +34,7 @@ const App = () => (
|
||||||
<ExpandMenuButton />
|
<ExpandMenuButton />
|
||||||
<UI />
|
<UI />
|
||||||
<ModalRoot />
|
<ModalRoot />
|
||||||
<WindowsRoot />
|
<WindowManager />
|
||||||
</IconContext.Provider>
|
</IconContext.Provider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
|
|
||||||
import useWindowSize from '../utils/reactHookResize';
|
|
||||||
import { showChatModal } from '../actions';
|
|
||||||
|
|
||||||
import Chat from './Chat';
|
|
||||||
|
|
||||||
|
|
||||||
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 = () => {
|
|
||||||
if (!chatOpen) setRender(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const { width } = useWindowSize();
|
|
||||||
if (width < 604 && chatOpen) {
|
|
||||||
dispatch(showChatModal(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
(render || chatOpen) && (
|
|
||||||
<div
|
|
||||||
className={(chatOpen && render) ? 'chatbox show' : 'chatbox'}
|
|
||||||
onTransitionEnd={onTransitionEnd}
|
|
||||||
>
|
|
||||||
<Chat showExpand />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(ChatBox);
|
|
|
@ -14,7 +14,6 @@ import { showChatModal, openChatWindow } from '../actions';
|
||||||
|
|
||||||
|
|
||||||
const ChatButton = ({
|
const ChatButton = ({
|
||||||
modalOpen,
|
|
||||||
chatNotify,
|
chatNotify,
|
||||||
channels,
|
channels,
|
||||||
unread,
|
unread,
|
||||||
|
@ -24,6 +23,7 @@ const ChatButton = ({
|
||||||
const [unreadAny, setUnreadAny] = useState(false);
|
const [unreadAny, setUnreadAny] = useState(false);
|
||||||
// TODO what do here?
|
// TODO what do here?
|
||||||
const chatOpen = false;
|
const chatOpen = false;
|
||||||
|
const modalOpen = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* almost the same as in ChannelDropDown
|
* almost the same as in ChannelDropDown
|
||||||
|
@ -88,9 +88,6 @@ function mapDispatchToProps(dispatch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
const {
|
|
||||||
modalOpen,
|
|
||||||
} = state.windows;
|
|
||||||
const {
|
const {
|
||||||
chatNotify,
|
chatNotify,
|
||||||
} = state.audio;
|
} = state.audio;
|
||||||
|
@ -102,8 +99,6 @@ function mapStateToProps(state) {
|
||||||
mute,
|
mute,
|
||||||
} = state.chatRead;
|
} = state.chatRead;
|
||||||
return {
|
return {
|
||||||
modalOpen,
|
|
||||||
chatNotify,
|
|
||||||
channels,
|
channels,
|
||||||
unread,
|
unread,
|
||||||
mute,
|
mute,
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { t } from 'ttag';
|
|
||||||
|
|
||||||
import Chat from './Chat';
|
|
||||||
|
|
||||||
|
|
||||||
const ChatModal = () => (
|
|
||||||
<div style={{
|
|
||||||
position: 'fixed',
|
|
||||||
top: 80,
|
|
||||||
padding: 10,
|
|
||||||
bottom: 10,
|
|
||||||
left: 10,
|
|
||||||
right: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="inarea"
|
|
||||||
style={{
|
|
||||||
height: '95%',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Chat />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
content: ChatModal,
|
|
||||||
title: t`Chat`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -1,32 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @flow
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import Creeper from './Creeper.svg';
|
|
||||||
|
|
||||||
import { showMinecraftModal } from '../actions';
|
|
||||||
|
|
||||||
const MinecraftButton = ({ open }) => (
|
|
||||||
<div
|
|
||||||
id="minecraftbutton"
|
|
||||||
className="actionbuttons"
|
|
||||||
onClick={open}
|
|
||||||
role="button"
|
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
<Creeper />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
function mapDispatchToProps(dispatch) {
|
|
||||||
return {
|
|
||||||
open() {
|
|
||||||
dispatch(showMinecraftModal());
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(MinecraftButton);
|
|
|
@ -5,88 +5,76 @@
|
||||||
* @flow
|
* @flow
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect, useCallback } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { MdClose } from 'react-icons/md';
|
import { MdClose } from 'react-icons/md';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
hideModal,
|
closeWindow,
|
||||||
|
restoreWindow,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
|
import COMPONENTS from './windows';
|
||||||
import HelpModal from './HelpModal';
|
|
||||||
import SettingsModal from './SettingsModal';
|
|
||||||
import UserAreaModal from './UserAreaModal';
|
|
||||||
import RegisterModal from './RegisterModal';
|
|
||||||
import CanvasSelectModal from './CanvasSelectModal';
|
|
||||||
import ArchiveModal from './ArchiveModal';
|
|
||||||
import ChatModal from './ChatModal';
|
|
||||||
import ForgotPasswordModal from './ForgotPasswordModal';
|
|
||||||
|
|
||||||
|
|
||||||
const MODAL_COMPONENTS = {
|
|
||||||
NONE: { content: <div />, title: '' },
|
|
||||||
HELP: HelpModal,
|
|
||||||
SETTINGS: SettingsModal,
|
|
||||||
USERAREA: UserAreaModal,
|
|
||||||
REGISTER: RegisterModal,
|
|
||||||
FORGOT_PASSWORD: ForgotPasswordModal,
|
|
||||||
CHAT: ChatModal,
|
|
||||||
CANVAS_SELECTION: CanvasSelectModal,
|
|
||||||
ARCHIVE: ArchiveModal,
|
|
||||||
/* other modals */
|
|
||||||
};
|
|
||||||
|
|
||||||
const ModalRoot = () => {
|
const ModalRoot = () => {
|
||||||
const [render, setRender] = useState(false);
|
const [render, setRender] = useState(false);
|
||||||
|
|
||||||
const modalType = useSelector((state) => state.windows.modalType);
|
const { windowType, open, title } = useSelector(
|
||||||
const modalOpen = useSelector((state) => state.windows.modalOpen);
|
(state) => state.windows.modal,
|
||||||
|
);
|
||||||
const {
|
|
||||||
title,
|
|
||||||
content: SpecificModal,
|
|
||||||
} = MODAL_COMPONENTS[modalType || 'NONE'];
|
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const close = useCallback(() => {
|
|
||||||
dispatch(hideModal());
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
const onTransitionEnd = () => {
|
const onTransitionEnd = () => {
|
||||||
if (!modalOpen) setRender(false);
|
if (!open) setRender(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
if (modalOpen) setRender(true);
|
if (open) setRender(true);
|
||||||
}, 10);
|
}, 10);
|
||||||
}, [modalOpen]);
|
}, [open]);
|
||||||
|
|
||||||
|
if (!windowType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Content = COMPONENTS[windowType || 'NONE'];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(render || modalOpen)
|
(render || open)
|
||||||
&& [
|
&& [
|
||||||
<div
|
<div
|
||||||
className={(modalOpen && render)
|
className={(open && render)
|
||||||
? 'OverlayModal show'
|
? 'OverlayModal show'
|
||||||
: 'OverlayModal'}
|
: 'OverlayModal'}
|
||||||
onTransitionEnd={onTransitionEnd}
|
onTransitionEnd={onTransitionEnd}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
onClick={close}
|
onClick={() => dispatch(closeWindow(0))}
|
||||||
/>,
|
/>,
|
||||||
<div
|
<div
|
||||||
className={(modalOpen && render) ? 'Modal show' : 'Modal'}
|
className={(open && render) ? 'Modal show' : 'Modal'}
|
||||||
>
|
>
|
||||||
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
|
<h2 style={{ paddingLeft: '5%' }}>{title}</h2>
|
||||||
<div
|
<div
|
||||||
onClick={close}
|
onClick={() => dispatch(closeWindow(0))}
|
||||||
className="ModalClose"
|
className="ModalClose"
|
||||||
role="button"
|
role="button"
|
||||||
label="close"
|
label="close"
|
||||||
title={t`Close`}
|
title={t`Close`}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
><MdClose /></div>
|
><MdClose /></div>
|
||||||
<SpecificModal windowId={0} />
|
<div
|
||||||
|
onClick={() => dispatch(restoreWindow())}
|
||||||
|
className="ModalRestore"
|
||||||
|
role="button"
|
||||||
|
label="restore"
|
||||||
|
title={t`Restore`}
|
||||||
|
tabIndex={-1}
|
||||||
|
>♥</div>
|
||||||
|
<div className="win-content">
|
||||||
|
<Content windowId={0} />
|
||||||
|
</div>
|
||||||
</div>,
|
</div>,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,18 +6,17 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
|
|
||||||
import Chat from './Chat';
|
|
||||||
import {
|
import {
|
||||||
moveWindow,
|
moveWindow,
|
||||||
|
resizeWindow,
|
||||||
|
closeWindow,
|
||||||
|
maximizeWindow,
|
||||||
|
cloneWindow,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
|
import COMPONENTS from './windows';
|
||||||
|
|
||||||
const selectWindowById = (state, windowId) => state.windows.windows.find((win) => win.windowId === windowId);
|
const selectWindowById = (state, windowId) => state.windows.windows.find((win) => win.windowId === windowId);
|
||||||
|
|
||||||
const WINDOW_COMPONENTS = {
|
|
||||||
NONE: <div />,
|
|
||||||
CHAT: Chat,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Window = ({ id }) => {
|
const Window = ({ id }) => {
|
||||||
const win = useSelector((state) => selectWindowById(state, id));
|
const win = useSelector((state) => selectWindowById(state, id));
|
||||||
|
|
||||||
|
@ -46,6 +45,33 @@ const Window = ({ id }) => {
|
||||||
document.addEventListener('mouseleave', stopMove, { once: true });
|
document.addEventListener('mouseleave', stopMove, { once: true });
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const startResize = useCallback((event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
let {
|
||||||
|
clientX: startX,
|
||||||
|
clientY: startY,
|
||||||
|
} = event;
|
||||||
|
const resize = (evt) => {
|
||||||
|
const {
|
||||||
|
clientX: curX,
|
||||||
|
clientY: curY,
|
||||||
|
} = evt;
|
||||||
|
dispatch(resizeWindow(id, curX - startX, curY - startY));
|
||||||
|
startX = curX;
|
||||||
|
startY = curY;
|
||||||
|
};
|
||||||
|
document.addEventListener('mousemove', resize);
|
||||||
|
const stopResize = () => {
|
||||||
|
document.removeEventListener('mousemove', resize);
|
||||||
|
};
|
||||||
|
document.addEventListener('mouseup', stopResize, { once: true });
|
||||||
|
document.addEventListener('mouseleave', stopResize, { once: true });
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!win) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
width, height,
|
width, height,
|
||||||
xPos, yPos,
|
xPos, yPos,
|
||||||
|
@ -53,7 +79,7 @@ const Window = ({ id }) => {
|
||||||
title,
|
title,
|
||||||
} = win;
|
} = win;
|
||||||
|
|
||||||
const Content = WINDOW_COMPONENTS[windowType];
|
const Content = COMPONENTS[windowType];
|
||||||
|
|
||||||
console.log(`render window ${id}`);
|
console.log(`render window ${id}`);
|
||||||
|
|
||||||
|
@ -71,7 +97,8 @@ const Window = ({ id }) => {
|
||||||
className="win-topbar"
|
className="win-topbar"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="win-topbtnn"
|
className="win-topbtn"
|
||||||
|
onClick={() => dispatch(cloneWindow(id))}
|
||||||
>
|
>
|
||||||
+
|
+
|
||||||
</span>
|
</span>
|
||||||
|
@ -79,20 +106,30 @@ const Window = ({ id }) => {
|
||||||
className="win-title"
|
className="win-title"
|
||||||
onMouseDown={startMove}
|
onMouseDown={startMove}
|
||||||
>
|
>
|
||||||
Move Here
|
{title}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="win-topbtnn"
|
className="win-topbtn"
|
||||||
|
onClick={() => dispatch(maximizeWindow(id))}
|
||||||
>
|
>
|
||||||
↑
|
↑
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="win-topbtnn"
|
className="win-topbtn"
|
||||||
|
onClick={() => dispatch(closeWindow(id))}
|
||||||
>
|
>
|
||||||
X
|
X
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<Content windowId={id} />
|
<div className="win-content">
|
||||||
|
<Content windowId={id} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onMouseDown={startResize}
|
||||||
|
className="win-resize"
|
||||||
|
>
|
||||||
|
R
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ const WindowsRoot = () => {
|
||||||
const windowIds = useSelector(selectWindowIds, shallowEqual);
|
const windowIds = useSelector(selectWindowIds, shallowEqual);
|
||||||
|
|
||||||
return windowIds.map((id) => (
|
return windowIds.map((id) => (
|
||||||
<Window id={id} />
|
<Window key={id} id={id} />
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ const imageStyle = {
|
||||||
verticalAlign: 'middle',
|
verticalAlign: 'middle',
|
||||||
};
|
};
|
||||||
|
|
||||||
const ArchiveModal = () => (
|
const Archive = () => (
|
||||||
<p style={{ textAlign: 'center', paddingLeft: '5%', paddingRight: '5%' }}>
|
<p style={{ textAlign: 'center', paddingLeft: '5%', paddingRight: '5%' }}>
|
||||||
<p className="modaltext">
|
<p className="modaltext">
|
||||||
{t`While we tend to not delete canvases, some canvases are started for fun or as a request by users who currently like a meme. \
|
{t`While we tend to not delete canvases, some canvases are started for fun or as a request by users who currently like a meme. \
|
||||||
|
@ -45,9 +45,4 @@ Those canvases can get boring after a while and after weeks of no major change a
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
const data = {
|
export default Archive;
|
||||||
content: ArchiveModal,
|
|
||||||
title: t`Canvas Archive`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -7,13 +7,13 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import CanvasItem from './CanvasItem';
|
import CanvasItem from '../CanvasItem';
|
||||||
import { showArchiveModal } from '../actions';
|
import { showArchiveModal } from '../../actions';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../../reducers';
|
||||||
|
|
||||||
|
|
||||||
const CanvasSelectModal = ({
|
const CanvasSelect = ({
|
||||||
canvases,
|
canvases,
|
||||||
showHiddenCanvases,
|
showHiddenCanvases,
|
||||||
showArchive,
|
showArchive,
|
||||||
|
@ -62,9 +62,4 @@ function mapStateToProps(state: State) {
|
||||||
return { canvases, showHiddenCanvases };
|
return { canvases, showHiddenCanvases };
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
export default connect(mapStateToProps, mapDispatchToProps)(CanvasSelect);
|
||||||
content: connect(mapStateToProps, mapDispatchToProps)(CanvasSelectModal),
|
|
||||||
title: t`Canvas Selection`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -10,9 +10,8 @@ import useStayScrolled from 'react-stay-scrolled';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import ChatMessage from '../ChatMessage';
|
||||||
import ChatMessage from './ChatMessage';
|
import ChannelDropDown from '../ChannelDropDown';
|
||||||
import ChannelDropDown from './ChannelDropDown';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
showUserAreaModal,
|
showUserAreaModal,
|
||||||
|
@ -21,9 +20,9 @@ import {
|
||||||
setChatInputMessage,
|
setChatInputMessage,
|
||||||
fetchChatMessages,
|
fetchChatMessages,
|
||||||
showContextMenu,
|
showContextMenu,
|
||||||
} from '../actions';
|
} from '../../actions';
|
||||||
import ProtocolClient from '../socket/ProtocolClient';
|
import ProtocolClient from '../../socket/ProtocolClient';
|
||||||
import splitChatMessage from '../core/chatMessageFilter';
|
import splitChatMessage from '../../core/chatMessageFilter';
|
||||||
|
|
||||||
function escapeRegExp(string) {
|
function escapeRegExp(string) {
|
||||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||||
|
@ -115,13 +114,7 @@ const Chat = ({
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={targetRef}
|
ref={targetRef}
|
||||||
style={{
|
className="chat-container"
|
||||||
display: 'flex',
|
|
||||||
position: 'relative',
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
flexDirection: 'column',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="chatlink"
|
className="chatlink"
|
|
@ -7,10 +7,10 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import { showUserAreaModal } from '../actions';
|
import { showUserAreaModal } from '../../actions';
|
||||||
import NewPasswordForm from './NewPasswordForm';
|
import NewPasswordForm from '../NewPasswordForm';
|
||||||
|
|
||||||
const ForgotPasswordModal = ({ login }) => (
|
const ForgotPassword = ({ login }) => (
|
||||||
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
||||||
<p className="modaltext">
|
<p className="modaltext">
|
||||||
{t`Enter your mail address and we will send you a new password:`}
|
{t`Enter your mail address and we will send you a new password:`}
|
||||||
|
@ -32,9 +32,4 @@ function mapDispatchToProps(dispatch) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
export default connect(null, mapDispatchToProps)(ForgotPassword);
|
||||||
content: connect(null, mapDispatchToProps)(ForgotPasswordModal),
|
|
||||||
title: t`Restore my Password`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -11,7 +11,7 @@ import { MdTouchApp } from 'react-icons/md';
|
||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
|
|
||||||
|
|
||||||
const HelpModal = () => {
|
const Help = () => {
|
||||||
const bindG = <kbd>{c('keybinds').t`G`}</kbd>;
|
const bindG = <kbd>{c('keybinds').t`G`}</kbd>;
|
||||||
const bindX = <kbd>{c('keybinds').t`X`}</kbd>;
|
const bindX = <kbd>{c('keybinds').t`X`}</kbd>;
|
||||||
const bindH = <kbd>{c('keybinds').t`H`}</kbd>;
|
const bindH = <kbd>{c('keybinds').t`H`}</kbd>;
|
||||||
|
@ -89,9 +89,4 @@ can be downloaded from mega.nz here: `}<a href="https://mega.nz/#!JpkBwAbJ!EnSLl
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const data = {
|
export default Help;
|
||||||
content: HelpModal,
|
|
||||||
title: t`Welcome to PixelPlanet.fun`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -7,13 +7,13 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import { showUserAreaModal } 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 RegisterModal = ({ login }) => (
|
const Register = ({ login }) => (
|
||||||
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
<p style={{ paddingLeft: '5%', paddingRight: '5%' }}>
|
||||||
<p className="modaltext">{t`Register new account here`}</p><br />
|
<p className="modaltext">{t`Register new account here`}</p><br />
|
||||||
<p style={{ textAlign: 'center' }}>
|
<p style={{ textAlign: 'center' }}>
|
||||||
|
@ -33,9 +33,4 @@ function mapDispatchToProps(dispatch) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
export default connect(null, mapDispatchToProps)(Register);
|
||||||
content: connect(null, mapDispatchToProps)(RegisterModal),
|
|
||||||
title: t`Register New Account`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -7,8 +7,8 @@ import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { c, t } from 'ttag';
|
import { c, t } from 'ttag';
|
||||||
|
|
||||||
import LanguageSelect from './LanguageSelect';
|
import LanguageSelect from '../LanguageSelect';
|
||||||
import MdToggleButtonHover from './MdToggleButtonHover';
|
import MdToggleButtonHover from '../MdToggleButtonHover';
|
||||||
import {
|
import {
|
||||||
toggleGrid,
|
toggleGrid,
|
||||||
togglePixelNotify,
|
togglePixelNotify,
|
||||||
|
@ -20,9 +20,9 @@ import {
|
||||||
toggleLightGrid,
|
toggleLightGrid,
|
||||||
toggleHistoricalView,
|
toggleHistoricalView,
|
||||||
selectStyle,
|
selectStyle,
|
||||||
} from '../actions';
|
} from '../../actions';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../../reducers';
|
||||||
|
|
||||||
|
|
||||||
const flexy = {
|
const flexy = {
|
||||||
|
@ -97,7 +97,7 @@ const SettingsItem = ({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
function SettingsModal({
|
function Settings({
|
||||||
isMuted,
|
isMuted,
|
||||||
isGridShown,
|
isGridShown,
|
||||||
isPixelNotifyShown,
|
isPixelNotifyShown,
|
||||||
|
@ -273,9 +273,4 @@ function mapDispatchToProps(dispatch) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
export default connect(mapStateToProps, mapDispatchToProps)(Settings);
|
||||||
content: connect(mapStateToProps, mapDispatchToProps)(SettingsModal),
|
|
||||||
title: t`Settings`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
|
@ -7,21 +7,21 @@ import React, { Suspense } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { t } from 'ttag';
|
import { t } from 'ttag';
|
||||||
|
|
||||||
import type { State } from '../reducers';
|
import type { State } from '../../reducers';
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
showRegisterModal, showForgotPasswordModal, setName, setMailreg,
|
showRegisterModal, showForgotPasswordModal, setName, setMailreg,
|
||||||
} from '../actions';
|
} from '../../actions';
|
||||||
import LogInForm from './LogInForm';
|
import LogInForm from '../LogInForm';
|
||||||
import Tabs from './Tabs';
|
import Tabs from '../Tabs';
|
||||||
import UserArea from './UserArea';
|
import UserAreaContent from '../UserArea';
|
||||||
import Rankings from './Rankings';
|
import Rankings from '../Rankings';
|
||||||
|
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
const Converter = React.lazy(() => import(/* webpackChunkName: "converter" */ './Converter'));
|
const Converter = React.lazy(() => import(/* webpackChunkName: "converter" */ '../Converter'));
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
const Admintools = React.lazy(() => import(/* webpackChunkName: "admintools" */ './Admintools'));
|
const Admintools = React.lazy(() => import(/* webpackChunkName: "admintools" */ '../Admintools'));
|
||||||
|
|
||||||
const logoStyle = {
|
const logoStyle = {
|
||||||
marginRight: 5,
|
marginRight: 5,
|
||||||
|
@ -86,7 +86,7 @@ const LogInArea = ({ register, forgotPassword, me }) => (
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
const UserAreaModal = ({
|
const UserArea = ({
|
||||||
name,
|
name,
|
||||||
register,
|
register,
|
||||||
forgotPassword,
|
forgotPassword,
|
||||||
|
@ -105,7 +105,7 @@ const UserAreaModal = ({
|
||||||
: (
|
: (
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<div label={t`Profile`}>
|
<div label={t`Profile`}>
|
||||||
<UserArea
|
<UserAreaContent
|
||||||
setName={setUserName}
|
setName={setUserName}
|
||||||
setMailreg={setUserMailreg}
|
setMailreg={setUserMailreg}
|
||||||
/>
|
/>
|
||||||
|
@ -155,9 +155,4 @@ function mapStateToProps(state: State) {
|
||||||
return { name, userlvl };
|
return { name, userlvl };
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = {
|
export default connect(mapStateToProps, mapDispatchToProps)(UserArea);
|
||||||
content: connect(mapStateToProps, mapDispatchToProps)(UserAreaModal),
|
|
||||||
title: t`User Area`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default data;
|
|
25
src/components/windows/index.jsx
Normal file
25
src/components/windows/index.jsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Help from './Help';
|
||||||
|
import Settings from './Settings';
|
||||||
|
import UserArea from './UserArea';
|
||||||
|
import Register from './Register';
|
||||||
|
import CanvasSelect from './CanvasSelect';
|
||||||
|
import Archive from './Archive';
|
||||||
|
import Chat from './Chat';
|
||||||
|
import ForgotPassword from './ForgotPassword';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
NONE: <div />,
|
||||||
|
HELP: Help,
|
||||||
|
SETTINGS: Settings,
|
||||||
|
USERAREA: UserArea,
|
||||||
|
REGISTER: Register,
|
||||||
|
FORGOT_PASSWORD: ForgotPassword,
|
||||||
|
CHAT: Chat,
|
||||||
|
CANVAS_SELECTION: CanvasSelect,
|
||||||
|
ARCHIVE: Archive,
|
||||||
|
/* other modals */
|
||||||
|
};
|
|
@ -6,20 +6,33 @@
|
||||||
|
|
||||||
import type { Action } from '../actions/types';
|
import type { Action } from '../actions/types';
|
||||||
|
|
||||||
|
function generateWindowId(state) {
|
||||||
|
let windowId = Math.floor(Math.random() * 99999) + 1;
|
||||||
|
while (state.args[windowId]) {
|
||||||
|
windowId += 1;
|
||||||
|
}
|
||||||
|
return windowId;
|
||||||
|
}
|
||||||
|
|
||||||
export type WindowsState = {
|
export type WindowsState = {
|
||||||
// modal is considerd as "fullscreen window"
|
// modal is considerd as "fullscreen window"
|
||||||
// its windowId is considered 0 and args are under args[0]
|
// its windowId is considered 0 and args are under args[0]
|
||||||
modalOpen: boolean,
|
modal: {
|
||||||
modalType: ?string,
|
windowType: ?string,
|
||||||
|
title: ?string,
|
||||||
|
open: boolean,
|
||||||
|
},
|
||||||
// [
|
// [
|
||||||
// {
|
// {
|
||||||
// windowId: number,
|
// windowId: number,
|
||||||
|
// windowOpen: boolean,
|
||||||
// windowType: string,
|
// windowType: string,
|
||||||
// title: string,
|
// title: string,
|
||||||
// width: number,
|
// width: number,
|
||||||
// height: number,
|
// height: number,
|
||||||
// xPos: percentage,
|
// xPos: percentage,
|
||||||
// yPos: percentage,
|
// yPos: percentage,
|
||||||
|
// cloneable: boolean,
|
||||||
// },
|
// },
|
||||||
// ]
|
// ]
|
||||||
windows: Array,
|
windows: Array,
|
||||||
|
@ -32,8 +45,11 @@ export type WindowsState = {
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: WindowsState = {
|
const initialState: WindowsState = {
|
||||||
modalOpen: false,
|
modal: {
|
||||||
modalType: null,
|
windowType: null,
|
||||||
|
title: null,
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
windows: [],
|
windows: [],
|
||||||
args: {},
|
args: {},
|
||||||
};
|
};
|
||||||
|
@ -47,16 +63,27 @@ export default function windows(
|
||||||
const {
|
const {
|
||||||
windowType,
|
windowType,
|
||||||
title,
|
title,
|
||||||
width,
|
fullscreen,
|
||||||
height,
|
cloneable,
|
||||||
xPos,
|
|
||||||
yPos,
|
|
||||||
args,
|
args,
|
||||||
} = action;
|
} = action;
|
||||||
let windowId = Math.floor(Math.random() * 99999) + 1;
|
if (fullscreen) {
|
||||||
while (state.args[windowId]) {
|
return {
|
||||||
windowId += 1;
|
...state,
|
||||||
|
modal: {
|
||||||
|
windowType,
|
||||||
|
title,
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
...state.args,
|
||||||
|
0: {
|
||||||
|
...args,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
const windowId = generateWindowId(state);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
windows: [
|
windows: [
|
||||||
|
@ -64,12 +91,13 @@ export default function windows(
|
||||||
{
|
{
|
||||||
windowId,
|
windowId,
|
||||||
windowType,
|
windowType,
|
||||||
|
windowOpen: true,
|
||||||
title,
|
title,
|
||||||
width,
|
width: 600,
|
||||||
height,
|
height: 300,
|
||||||
xPos,
|
xPos: 200,
|
||||||
yPos,
|
yPos: 200,
|
||||||
args,
|
cloneable,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
args: {
|
args: {
|
||||||
|
@ -79,10 +107,57 @@ export default function windows(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'REMOVE_WINDOW': {
|
||||||
|
const {
|
||||||
|
windowId,
|
||||||
|
} = action;
|
||||||
|
const args = { ...state.args };
|
||||||
|
delete args[windowId];
|
||||||
|
|
||||||
|
if (windowId === 0) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
modal: {
|
||||||
|
windowType: null,
|
||||||
|
title: null,
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
windows: state.windows.filter((win) => win.windowId !== windowId),
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'CLOSE_WINDOW': {
|
case 'CLOSE_WINDOW': {
|
||||||
const {
|
const {
|
||||||
windowId,
|
windowId,
|
||||||
} = action;
|
} = action;
|
||||||
|
if (windowId === 0) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
modal: {
|
||||||
|
...state.modal,
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
const newWindows = state.windows.map((win) => {
|
||||||
|
if (win.windowId !== windowId) return win;
|
||||||
|
return {
|
||||||
|
...win,
|
||||||
|
windowOpen: false,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
windows: newWindows,
|
||||||
|
};
|
||||||
|
*/
|
||||||
const args = { ...state.args };
|
const args = { ...state.args };
|
||||||
delete args[windowId];
|
delete args[windowId];
|
||||||
return {
|
return {
|
||||||
|
@ -92,6 +167,87 @@ export default function windows(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'CLONE_WINDOW': {
|
||||||
|
const {
|
||||||
|
windowId,
|
||||||
|
} = action;
|
||||||
|
const win = state.windows.find((w) => w.windowId === windowId);
|
||||||
|
const newWindowId = generateWindowId(state);
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
windows: [
|
||||||
|
...state.windows,
|
||||||
|
{
|
||||||
|
...win,
|
||||||
|
windowId: newWindowId,
|
||||||
|
xPos: win.xPos + 15,
|
||||||
|
yPos: win.yPos + 15,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
args: {
|
||||||
|
...state.args,
|
||||||
|
[newWindowId]: {
|
||||||
|
...state.args[windowId],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'MAXIMIZE_WINDOW': {
|
||||||
|
const {
|
||||||
|
windowId,
|
||||||
|
} = action;
|
||||||
|
const args = {
|
||||||
|
...state.args,
|
||||||
|
0: state.args[windowId],
|
||||||
|
};
|
||||||
|
const { windowType, title } = state.windows.find((w) => w.windowId === windowId);
|
||||||
|
delete args[windowId];
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
modal: {
|
||||||
|
windowType,
|
||||||
|
title,
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
windows: state.windows.filter((w) => w.windowId !== windowId),
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'RESTORE_WINDOW': {
|
||||||
|
const windowId = generateWindowId(state);
|
||||||
|
const { windowType, title } = state.modal;
|
||||||
|
const cloneable = true;
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
modal: {
|
||||||
|
...state.modal,
|
||||||
|
open: false,
|
||||||
|
},
|
||||||
|
windows: [
|
||||||
|
...state.windows,
|
||||||
|
{
|
||||||
|
windowType,
|
||||||
|
windowId,
|
||||||
|
windowOpen: true,
|
||||||
|
title,
|
||||||
|
width: 600,
|
||||||
|
height: 300,
|
||||||
|
xPos: 200,
|
||||||
|
yPos: 200,
|
||||||
|
cloneable,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
args: {
|
||||||
|
...state.args,
|
||||||
|
[windowId]: {
|
||||||
|
...state.args[0],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'MOVE_WINDOW': {
|
case 'MOVE_WINDOW': {
|
||||||
const {
|
const {
|
||||||
windowId,
|
windowId,
|
||||||
|
@ -112,6 +268,26 @@ export default function windows(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'RESIZE_WINDOW': {
|
||||||
|
const {
|
||||||
|
windowId,
|
||||||
|
xDiff,
|
||||||
|
yDiff,
|
||||||
|
} = action;
|
||||||
|
const newWindows = state.windows.map((win) => {
|
||||||
|
if (win.windowId !== windowId) return win;
|
||||||
|
return {
|
||||||
|
...win,
|
||||||
|
width: win.width + xDiff,
|
||||||
|
height: win.height + yDiff,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
windows: newWindows,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
case 'CLOSE_ALL_WINDOWS': {
|
case 'CLOSE_ALL_WINDOWS': {
|
||||||
return initialState;
|
return initialState;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,7 @@ tr:nth-child(even) {
|
||||||
|
|
||||||
.win-topbar {
|
.win-topbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
height: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.win-title {
|
.win-title {
|
||||||
|
@ -155,6 +156,29 @@ tr:nth-child(even) {
|
||||||
border: solid black;
|
border: solid black;
|
||||||
border-width: thin;
|
border-width: thin;
|
||||||
background-color: blue;
|
background-color: blue;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.win-resize {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
cursor: se-resize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-container {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.win-content {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 16px);
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contextmenu {
|
.contextmenu {
|
||||||
|
@ -444,7 +468,7 @@ tr:nth-child(even) {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ModalClose {
|
.ModalClose, .ModalRestore {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -459,11 +483,18 @@ tr:nth-child(even) {
|
||||||
background-color: #f6f6f7;
|
background-color: #f6f6f7;
|
||||||
border-color: #dcddde;
|
border-color: #dcddde;
|
||||||
top: 30px;
|
top: 30px;
|
||||||
right: 40px;
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ModalClose:hover {
|
.ModalClose {
|
||||||
|
right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ModalRestore {
|
||||||
|
right: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ModalClose:hover, .ModalRestore:hover {
|
||||||
background-color: #e3e3e4;
|
background-color: #e3e3e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user