diff --git a/src/actions/index.js b/src/actions/index.js index 99a60c4..194e639 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -169,6 +169,14 @@ export function setMobile(mobile: boolean): Action { }; } +export function windowResize(width: number, height: number): Action { + return { + type: 'WINDOW_RESIZE', + width, + height, + }; +} + export function selectColor(color: ColorIndex): Action { return { type: 'SELECT_COLOR', diff --git a/src/actions/types.js b/src/actions/types.js index 69b0431..f6c3561 100644 --- a/src/actions/types.js +++ b/src/actions/types.js @@ -35,6 +35,7 @@ export type Action = | { type: 'SET_WAIT', wait: ?number } | { type: 'RECEIVE_COOLDOWN', wait: number } | { type: 'SET_MOBILE', mobile: boolean } + | { type: 'WINDOW_RESIZE', width: number, height: number } | { type: 'COOLDOWN_END' } | { type: 'COOLDOWN_SET', coolDown: number } | { type: 'COOLDOWN_DELTA', delta: number } diff --git a/src/client.js b/src/client.js index 29dab42..d68e0f1 100644 --- a/src/client.js +++ b/src/client.js @@ -17,6 +17,7 @@ import { addChatChannel, removeChatChannel, setMobile, + windowResize, } from './actions'; import { receivePixelUpdate, @@ -93,6 +94,14 @@ function init() { } document.addEventListener('touchstart', checkMobile, { once: true }); + // listen for resize + // + function onWindowResize() { + store.dispatch(windowResize(window.innerWidth, window.innerHeight)); + } + window.addEventListener('resize', onWindowResize); + onWindowResize(); + store.dispatch(initTimer()); store.dispatch(fetchMe()); diff --git a/src/components/ChannelContextMenu.jsx b/src/components/ChannelContextMenu.jsx index fddb5a9..71b680a 100644 --- a/src/components/ChannelContextMenu.jsx +++ b/src/components/ChannelContextMenu.jsx @@ -36,14 +36,11 @@ const ChannelContextMenu = ({ close(); } }; - const handleWindowResize = () => close(); document.addEventListener('mousedown', handleClickOutside); document.addEventListener('touchstart', handleClickOutside); - window.addEventListener('resize', handleWindowResize); return () => { document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('touchstart', handleClickOutside); - window.removeEventListener('resize', handleWindowResize); }; }, [wrapperRef]); diff --git a/src/components/UserContextMenu.jsx b/src/components/UserContextMenu.jsx index ab4aba5..0146a28 100644 --- a/src/components/UserContextMenu.jsx +++ b/src/components/UserContextMenu.jsx @@ -37,14 +37,11 @@ const UserContextMenu = ({ close(); } }; - const handleWindowResize = () => close(); document.addEventListener('mousedown', handleClickOutside); document.addEventListener('touchstart', handleClickOutside); - window.addEventListener('resize', handleWindowResize); return () => { document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('touchstart', handleClickOutside); - window.removeEventListener('resize', handleWindowResize); }; }, [wrapperRef]); diff --git a/src/components/Window.jsx b/src/components/Window.jsx index 6208a2b..74a31f7 100644 --- a/src/components/Window.jsx +++ b/src/components/Window.jsx @@ -42,7 +42,6 @@ const Window = ({ id }) => { document.removeEventListener('mousemove', move); }; document.addEventListener('mouseup', stopMove, { once: true }); - document.addEventListener('mouseleave', stopMove, { once: true }); }, []); const startResize = useCallback((event) => { @@ -65,7 +64,6 @@ const Window = ({ id }) => { document.removeEventListener('mousemove', resize); }; document.addEventListener('mouseup', stopResize, { once: true }); - document.addEventListener('mouseleave', stopResize, { once: true }); }, []); if (!win) { diff --git a/src/reducers/contextMenu.js b/src/reducers/contextMenu.js index e62e48d..e56f26d 100644 --- a/src/reducers/contextMenu.js +++ b/src/reducers/contextMenu.js @@ -44,6 +44,7 @@ export default function contextMenu( }; } + case 'WINDOW_RESIZE': case 'HIDE_CONTEXT_MENU': { return { ...state, diff --git a/src/reducers/windows.js b/src/reducers/windows.js index e106ca9..fbb5529 100644 --- a/src/reducers/windows.js +++ b/src/reducers/windows.js @@ -6,6 +6,8 @@ import type { Action } from '../actions/types'; +import { clamp } from '../core/utils'; + function generateWindowId(state) { let windowId = Math.floor(Math.random() * 99999) + 1; while (state.args[windowId]) { @@ -254,12 +256,16 @@ export default function windows( xDiff, yDiff, } = action; + const { + innerWidth: width, + innerHeight: height, + } = window; const newWindows = state.windows.map((win) => { if (win.windowId !== windowId) return win; return { ...win, - xPos: win.xPos + xDiff, - yPos: win.yPos + yDiff, + xPos: clamp(win.xPos + xDiff, -win.width + 70, width - 30), + yPos: clamp(win.yPos + yDiff, 0, height - 30), }; }); return { @@ -278,8 +284,8 @@ export default function windows( if (win.windowId !== windowId) return win; return { ...win, - width: win.width + xDiff, - height: win.height + yDiff, + width: Math.max(win.width + xDiff, 70, 70 - win.xPos), + height: Math.max(win.height + yDiff, 50), }; }); return { @@ -288,6 +294,39 @@ export default function windows( }; } + case 'WINDOW_RESIZE': { + const { + width, + height, + } = action; + const xMax = width - 30; + const yMax = height - 30; + let modified = false; + + const newWindows = []; + for (let i = 0; i < state.windows.length; i += 1) { + const win = state.windows[i]; + let { xPos, yPos } = win; + if (xPos > xMax || yPos > yMax) { + modified = true; + newWindows.push({ + ...win, + xPos: Math.min(xMax, xPos), + yPos: Math.min(yMax, yPos), + }); + } else { + newWindows.push(win); + } + } + + if (!modified) return state; + + return { + ...state, + windows: newWindows, + }; + } + case 'CLOSE_ALL_WINDOWS': { return initialState; } diff --git a/src/styles/default.css b/src/styles/default.css index 4c97ab4..3743409 100644 --- a/src/styles/default.css +++ b/src/styles/default.css @@ -140,6 +140,7 @@ tr:nth-child(even) { border: solid black; border-width: thin; overflow: hidden; + z-index: 3; } .win-topbar {