move drag detection into hook
This commit is contained in:
parent
f593d8c7e2
commit
1c486f3105
|
@ -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';
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 (
|
||||
<div
|
||||
className={`window ${windowType}`}
|
||||
onClick={() => dispatch(focusWindow(id))}
|
||||
onClick={focus}
|
||||
style={{
|
||||
left: xPos,
|
||||
top: yPos,
|
||||
|
@ -156,37 +84,35 @@ const Window = ({ id }) => {
|
|||
>
|
||||
<div
|
||||
className="win-topbar"
|
||||
ref={titleBarRef}
|
||||
>
|
||||
<span
|
||||
className="win-topbtn"
|
||||
onMouseDown={clone}
|
||||
onClick={clone}
|
||||
>
|
||||
+
|
||||
</span>
|
||||
<span
|
||||
className="win-title"
|
||||
ref={titleBarRef}
|
||||
>
|
||||
{title}
|
||||
</span>
|
||||
<span
|
||||
className="win-topbtn"
|
||||
onMouseDown={maximize}
|
||||
onClick={maximize}
|
||||
>
|
||||
↑
|
||||
</span>
|
||||
<span
|
||||
className="win-topbtn"
|
||||
onMouseDown={close}
|
||||
onClick={close}
|
||||
>
|
||||
X
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
onMouseDown={startResize}
|
||||
onTouchStart={startResize}
|
||||
className="win-resize"
|
||||
touchAction="none"
|
||||
ref={resizeRef}
|
||||
>
|
||||
▨
|
||||
</div>
|
||||
|
|
66
src/components/hooks/drag.js
Normal file
66
src/components/hooks/drag.js
Normal file
|
@ -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;
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user