diff --git a/src/components/Palette.jsx b/src/components/Palette.jsx
index ddf5f9d..1e9f2e0 100644
--- a/src/components/Palette.jsx
+++ b/src/components/Palette.jsx
@@ -8,7 +8,7 @@ import { connect } from 'react-redux';
import { selectColor } from '../actions';
import type { State } from '../reducers';
-import useWindowSize from '../utils/reactHookResize';
+import useWindowSize from './hooks/resize';
/*
diff --git a/src/components/Window.jsx b/src/components/Window.jsx
index ac35212..552e677 100644
--- a/src/components/Window.jsx
+++ b/src/components/Window.jsx
@@ -3,7 +3,7 @@
* @flow
*/
-import React, { useCallback, useRef, useEffect } from 'react';
+import React, { useCallback, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import {
@@ -14,117 +14,45 @@ import {
cloneWindow,
focusWindow,
} from '../actions';
+import useDrag from './hooks/drag';
import COMPONENTS from './windows';
const selectWindowById = (state, windowId) => state.windows.windows.find((win) => win.windowId === windowId);
const Window = ({ id }) => {
const titleBarRef = useRef(null);
+ const resizeRef = useRef(null);
const win = useSelector((state) => selectWindowById(state, id));
const dispatch = useDispatch();
- const startMove = useCallback((event) => {
- try {
- event.stopPropagation();
- dispatch(focusWindow(id));
- console.log('startMove');
+ const focus = useCallback(() => dispatch(focusWindow(id)), []);
- let {
- clientX: startX,
- clientY: startY,
- } = event.touches ? event.touches[0] : evt;
- const move = (evt) => {
- evt.stopPropagation();
- try {
- const {
- clientX: curX,
- clientY: curY,
- } = evt.touches ? evt.touches[0] : evt;
- console.log(`move by ${curX-startX} - ${curY - startY}`);
- dispatch(moveWindow(id, curX - startX, curY - startY));
- startX = curX;
- startY = curY;
- } catch (e) {
- console.log(e);
- }
- };
- document.addEventListener('mousemove', move);
- document.addEventListener('touchmove', move);
- const stopMove = (evt) => {
- evt.stopPropagation();
- console.log('stopMove');
- document.removeEventListener('mousemove', move);
- document.removeEventListener('touchmove', move);
- document.removeEventListener('mouseup', stopMove);
- document.removeEventListener('touchcancel', stopMove);
- document.removeEventListener('touchend', stopMove);
- };
- document.addEventListener('mouseup', stopMove);
- document.addEventListener('touchcancel', stopMove);
- document.addEventListener('touchend', stopMove);
- } catch (e) {
- console.log(e);
- }
- }, []);
+ useDrag(
+ titleBarRef,
+ focus,
+ useCallback((xDiff, yDiff) => dispatch(moveWindow(id, xDiff, yDiff)), []),
+ );
- const startResize = useCallback((event) => {
- dispatch(focusWindow(id));
-
- 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.removeEventListener('mouseup', stopResize);
- document.removeEventListener('touchcancel', stopResize);
- document.removeEventListener('touchend', stopResize);
- };
- document.addEventListener('mouseup', stopResize);
- document.addEventListener('touchcancel', stopResize);
- document.addEventListener('touchend', stopResize);
- }, []);
-
- useEffect(() => {
- if (titleBarRef && titleBarRef.current) {
- console.log('add listener')
- console.log(titleBarRef.current);
- titleBarRef.current.addEventListener('mousedown', startMove, {passive: false});
- titleBarRef.current.addEventListener('touchstart', startMove, {passive: false});
- }
- return () => {
- titleBarRef.current.removeEventListener('mousedown', startMove);
- titleBarRef.current.removeEventListener('touchstart', startMove);
- };
- }, [titleBarRef, startMove]);
+ useDrag(
+ resizeRef,
+ focus,
+ useCallback((xDiff, yDiff) => dispatch(resizeWindow(id, xDiff, yDiff)), []),
+ );
const clone = (evt) => {
evt.stopPropagation();
- evt.preventDefault();
dispatch(cloneWindow(id));
};
const maximize = (evt) => {
evt.stopPropagation();
- evt.preventDefault();
dispatch(maximizeWindow(id));
};
const close = (evt) => {
evt.stopPropagation();
- evt.preventDefault();
dispatch(closeWindow(id));
};
@@ -146,7 +74,7 @@ const Window = ({ id }) => {
return (
dispatch(focusWindow(id))}
+ onClick={focus}
style={{
left: xPos,
top: yPos,
@@ -156,37 +84,35 @@ const Window = ({ id }) => {
>
+
{title}
↑
X
▨
diff --git a/src/components/hooks/drag.js b/src/components/hooks/drag.js
new file mode 100644
index 0000000..80bad60
--- /dev/null
+++ b/src/components/hooks/drag.js
@@ -0,0 +1,66 @@
+/*
+ * @flex
+ *
+ * mouse draging
+ */
+
+import { useEffect, useCallback } from 'react';
+
+/*
+ * @param elRef element reference from useRef
+ * @param startHandler function called on start of drag
+ * @param diffHandler functio that is called with dragged distance
+ */
+function useDrag(elRef, startHandler, diffHandler) {
+ const startDrag = useCallback((event) => {
+ event.preventDefault();
+ event.stopPropagation();
+ startHandler();
+ console.log('startDrag');
+
+ let {
+ clientX: startX,
+ clientY: startY,
+ } = event.touches ? event.touches[0] : event;
+ const drag = (evt) => {
+ evt.preventDefault();
+ evt.stopPropagation();
+ const {
+ clientX: curX,
+ clientY: curY,
+ } = evt.touches ? evt.touches[0] : evt;
+ console.log(`drag by ${curX - startX} - ${curY - startY}`);
+ diffHandler(curX - startX, curY - startY);
+ startX = curX;
+ startY = curY;
+ };
+ document.addEventListener('mousemove', drag);
+ document.addEventListener('touchmove', drag);
+ const stopDrag = (evt) => {
+ evt.preventDefault();
+ evt.stopPropagation();
+ console.log('stopDrag');
+ document.removeEventListener('mousemove', drag);
+ document.removeEventListener('touchmove', drag);
+ document.removeEventListener('mouseup', stopDrag);
+ document.removeEventListener('touchcancel', stopDrag);
+ document.removeEventListener('touchend', stopDrag);
+ };
+ document.addEventListener('mouseup', stopDrag);
+ document.addEventListener('touchcancel', stopDrag);
+ document.addEventListener('touchend', stopDrag);
+ }, [startHandler]);
+
+ useEffect(() => {
+ if (elRef && elRef.current) {
+ elRef.current.addEventListener('mousedown', startDrag, { passive: false });
+ elRef.current.addEventListener('touchstart', startDrag, { passive: false });
+ }
+ return () => {
+ elRef.current.removeEventListener('mousedown', startDrag);
+ elRef.current.removeEventListener('touchstart', startDrag);
+ };
+ }, [elRef, diffHandler]);
+}
+
+export default useDrag;
diff --git a/src/utils/reactHookResize.js b/src/components/hooks/resize.js
similarity index 100%
rename from src/utils/reactHookResize.js
rename to src/components/hooks/resize.js
diff --git a/src/reducers/windows.js b/src/reducers/windows.js
index 522ac49..3bd2dc0 100644
--- a/src/reducers/windows.js
+++ b/src/reducers/windows.js
@@ -8,8 +8,8 @@ import type { Action } from '../actions/types';
import { clamp } from '../core/utils';
-const SCREEN_MARGIN_SE = 30;
-const SCREEN_MARGIN_W = 70;
+const SCREEN_MARGIN_S = 30;
+const SCREEN_MARGIN_EW = 70;
const MIN_WIDTH = 70;
const MIN_HEIGHT = 50;
@@ -191,8 +191,8 @@ export default function windows(
{
...win,
windowId: newWindowId,
- xPos: Math.min(win.xPos + 15, width - SCREEN_MARGIN_SE),
- yPos: Math.min(win.yPos + 15, height - SCREEN_MARGIN_SE),
+ xPos: Math.min(win.xPos + 15, width - SCREEN_MARGIN_EW),
+ yPos: Math.min(win.yPos + 15, height - SCREEN_MARGIN_S),
},
],
args: {
@@ -300,10 +300,10 @@ export default function windows(
...win,
xPos: clamp(
win.xPos + xDiff,
- -win.width + SCREEN_MARGIN_W,
- width - SCREEN_MARGIN_SE,
+ -win.width + SCREEN_MARGIN_EW,
+ width - SCREEN_MARGIN_S,
),
- yPos: clamp(win.yPos + yDiff, 0, height - SCREEN_MARGIN_SE),
+ yPos: clamp(win.yPos + yDiff, 0, height - SCREEN_MARGIN_S),
};
});
return {
@@ -322,14 +322,15 @@ export default function windows(
if (win.windowId !== windowId) return win;
return {
...win,
- width: Math.max(
+ width: clamp(
win.width + xDiff,
- MIN_WIDTH,
- SCREEN_MARGIN_W - win.xPos,
+ Math.max(MIN_WIDTH, SCREEN_MARGIN_EW - win.xPos),
+ window.innerWidth,
),
- height: Math.max(
+ height: clamp(
win.height + yDiff,
MIN_HEIGHT,
+ window.innerHeight,
),
};
});
@@ -344,20 +345,28 @@ export default function windows(
width,
height,
} = action;
- const xMax = width - SCREEN_MARGIN_SE;
- const yMax = height - SCREEN_MARGIN_SE;
+ const xMax = width - SCREEN_MARGIN_EW;
+ const yMax = height - SCREEN_MARGIN_S;
let modified = false;
const newWindows = [];
for (let i = 0; i < state.windows.length; i += 1) {
const win = state.windows[i];
- const { xPos, yPos } = win;
- if (xPos > xMax || yPos > yMax) {
+ const {
+ xPos,
+ yPos,
+ width: winWidth,
+ height: winHeight,
+ } = win;
+ if (xPos > xMax || yPos > yMax
+ || width > winWidth || height > winHeight) {
modified = true;
newWindows.push({
...win,
xPos: Math.min(xMax, xPos),
yPos: Math.min(yMax, yPos),
+ width: Math.min(winWidth, width - SCREEN_MARGIN_S),
+ height: Math.min(winHeight, height - SCREEN_MARGIN_S),
});
} else {
newWindows.push(win);