Skip to content

Commit f9b0a1a

Browse files
authored
Merge pull request #10 from oslabs-beta/sean
Refactored Mouse-Tracker
2 parents 91fd4e7 + dfca8f9 commit f9b0a1a

File tree

6 files changed

+150
-41
lines changed

6 files changed

+150
-41
lines changed

app/src/components/left/RoomsContainer.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import List from '@mui/material/List';
55
import ListItem from '@mui/material/ListItem';
66
import ListItemText from '@mui/material/ListItemText';
77
import Button from '@mui/material/Button';
8-
import React from 'react';
8+
import React, { useState } from 'react';
99
import { RootState } from '../../redux/store';
1010
import TextField from '@mui/material/TextField';
1111
import {
@@ -32,7 +32,22 @@ import {
3232
disconnectSocket
3333
} from '../../helperFunctions/socket';
3434

35-
//Websocket
35+
// // for websockets
36+
// // Part - join room and room code functionality
37+
let socket;
38+
39+
//function to create HTML elements and update the position of the cursorr.
40+
// function getCursor(id) {
41+
// let elementId = 'cursor-' + id;
42+
// let element = document.getElementById(elementId);
43+
// if (element == null) {
44+
// element = document.createElement('div');
45+
// element.id = elementId;
46+
// element.className = 'cursor';
47+
// document.appendChild(element);
48+
// }
49+
// return element;
50+
// }
3651

3752
const RoomsContainer = () => {
3853
const dispatch = useDispatch();
@@ -81,6 +96,7 @@ const RoomsContainer = () => {
8196
socket.on('updateUserList', (newUserList) => {
8297
console.log('user list received from server');
8398
dispatch(setUserList(newUserList));
99+
console.log('userList:', userList);
84100
});
85101

86102
socket.on('child data from server', (childData: object) => {

app/src/components/main/Canvas.tsx

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,65 @@ import {
77
snapShotAction
88
} from '../../redux/reducers/slice/appStateSlice';
99
import { useDispatch, useSelector } from 'react-redux';
10+
import { debounce, throttle } from 'lodash';
1011

1112
import Arrow from './Arrow';
1213
import { ItemTypes } from '../../constants/ItemTypes';
1314
import { RootState } from '../../redux/store';
1415
import { combineStyles } from '../../helperFunctions/combineStyles';
1516
import renderChildren from '../../helperFunctions/renderChildren';
16-
import { emitEvent } from '../../helperFunctions/socket';
17+
import { emitEvent, getSocket } from '../../helperFunctions/socket';
1718

1819
function Canvas(props: {}): JSX.Element {
1920
const state = useSelector((store: RootState) => store.appState);
2021
const contextParam = useSelector((store: RootState) => store.contextSlice);
21-
2222
const roomCode = useSelector((store: RootState) => store.roomSlice.roomCode);
23-
// console.log('roomCode:', roomCode);
24-
// console.log('canavs is rendered');
23+
const userName = useSelector((store: RootState) => store.roomSlice.userName);
24+
const userList = useSelector((store: RootState) => store.roomSlice.userList);
25+
26+
//-------mouse tracking-------
27+
console.log('canvas is rendered');
28+
29+
//remote cursor data
30+
const [remoteCursor, setRemoteCursor] = useState({
31+
x: 0,
32+
y: 0,
33+
remoteUserName: '',
34+
isVisible: false
35+
});
36+
37+
const debounceSetPosition = debounce((newX, newY) => {
38+
//emit socket event every 500ms when cursor moves
39+
if (userList.length > 1)
40+
emitEvent('cursorData', roomCode, { x: newX, y: newY, userName });
41+
}, 100);
42+
43+
const handleMouseMove = (e) => {
44+
debounceSetPosition(e.clientX, e.clientY);
45+
};
46+
47+
const socket = getSocket();
48+
if (socket) {
49+
// console.log('setting up socket listener');
50+
socket.on('remote cursor data from server', (remoteData) => {
51+
setRemoteCursor((prevState) => {
52+
// check if the received data is different from the current state
53+
if (prevState.x !== remoteData.x || prevState.y !== remoteData.y) {
54+
return {
55+
...prevState,
56+
x: remoteData.x,
57+
y: remoteData.y,
58+
remoteUserName: remoteData.userName,
59+
isVisible: true
60+
};
61+
}
62+
// if data is the same, return the previous state to prevent re-render
63+
return prevState;
64+
});
65+
});
66+
}
67+
68+
//--------------------------------
2569

2670
// find the current component based on the canvasFocus component ID in the state
2771
const currentComponent: Component = state.components.find(
@@ -184,8 +228,29 @@ function Canvas(props: {}): JSX.Element {
184228
data-testid="drop"
185229
style={canvasStyle}
186230
onClick={onClickHandler}
231+
onMouseMove={handleMouseMove}
187232
>
188233
{renderChildren(currentComponent.children)}
234+
235+
{remoteCursor.isVisible && (
236+
<div
237+
className="remote-cursor"
238+
style={{
239+
position: 'absolute',
240+
left: remoteCursor.x + 'px',
241+
top: remoteCursor.y - 68 + 'px',
242+
//style
243+
width: '10px',
244+
height: '10px',
245+
borderRadius: '50%',
246+
backgroundColor: 'blue',
247+
color: 'red'
248+
}}
249+
>
250+
{' '}
251+
{remoteCursor.remoteUserName}
252+
</div>
253+
)}
189254
</div>
190255
);
191256
}

app/src/index.tsx

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,42 +39,42 @@ if (isDev) {
3939

4040
const PrivateRoute = ({ component: Component, ...rest }) => {
4141
const [isLoggedIn, setIsLoggedIn] = useState(null);
42-
43-
useEffect(() => {
44-
45-
const projects = fetch(`${serverURL}/loggedIn`, {
46-
method: 'GET',
47-
headers: {
48-
'content-type': 'application/json'
49-
},
50-
// need credentials for userid pull from cookie
51-
credentials: 'include'
52-
})
53-
.then((res) => res.json())
54-
.then((data) => {
55-
56-
setIsLoggedIn(data);
5742

43+
useEffect(() => {
44+
const projects = fetch(`${serverURL}/loggedIn`, {
45+
method: 'GET',
46+
headers: {
47+
'content-type': 'application/json'
48+
},
49+
// need credentials for userid pull from cookie
50+
credentials: 'include'
5851
})
59-
.catch((err) => console.log(`Error getting project ${err}`));
52+
.then((res) => res.json())
53+
.then((data) => {
54+
setIsLoggedIn(data);
55+
})
56+
.catch((err) => console.log(`Error getting project ${err}`));
6057
}, []);
6158

62-
return (
63-
<Route
64-
{...rest}
65-
render={(props) => {
66-
if (isLoggedIn === true || window.localStorage.getItem('ssid') === 'guest') {
67-
// User is logged in, render the protected component
68-
return <Component {...props} />;
69-
} else if(isLoggedIn !== null) {
70-
// User is not logged in, redirect to the login page
71-
// Ignores the initial render which would have isLoggedIn as null
72-
return <Redirect to="/login" />;
73-
}
74-
}}
75-
/>
76-
)};
77-
59+
return (
60+
<Route
61+
{...rest}
62+
render={(props) => {
63+
if (
64+
isLoggedIn === true ||
65+
window.localStorage.getItem('ssid') === 'guest'
66+
) {
67+
// User is logged in, render the protected component
68+
return <Component {...props} />;
69+
} else if (isLoggedIn !== null) {
70+
// User is not logged in, redirect to the login page
71+
// Ignores the initial render which would have isLoggedIn as null
72+
return <Redirect to="/login" />;
73+
}
74+
}}
75+
/>
76+
);
77+
};
7878

7979
ReactDOM.render(
8080
<ApolloProvider client={client}>

app/src/interfaces/Interfaces.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,25 @@ export interface Arrow {
169169
) => HTMLDivElement;
170170
}
171171

172-
export interface ColumnTab { //table state props
172+
export interface ColumnTab {
173+
//table state props
173174
field: string;
174175
headerName: string;
175176
width: string | number;
176177
editable: boolean;
177-
align?:string;
178+
align?: string;
178179
valueGetter?: (param: any) => string | undefined;
179180
renderCell?: (params: any) => React.ReactNode;
180181
flex?: string | number;
181182
sortable?: boolean;
182183
disableColumnMenu?: boolean;
183184
}
185+
186+
// Exports for Mouse tracking
187+
188+
export interface MouseProps {}
189+
export interface MouseState {
190+
//canvas mouseTracking props.
191+
clientX: number;
192+
clientY: number;
193+
}

server/server.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,20 @@ io.on('connection', (client) => {
147147
}
148148
});
149149

150+
//updating mouse movement after joining.
151+
152+
client.on('mouse connection', (data) => {
153+
io.emit('mouseCursor', { line: data.line, id: client.id });
154+
});
155+
156+
//connecting and emitting the mousetracker
157+
// client.on('connection', (socket) => {
158+
// socket.emit('news', { hello: 'world' });
159+
// socket.on('other event', (data) => {
160+
// console.log(data);
161+
// });
162+
// });
163+
150164
//disconnecting functionality
151165
client.on('disconnecting', () => {
152166
// the client.rooms Set contains at least the socket ID
@@ -190,6 +204,10 @@ io.on('connection', (client) => {
190204
.emit('item position data from server', itemPositionData);
191205
}
192206
);
207+
208+
client.on('cursorData', (roomCode: string, remoteData: object) => {
209+
client.to(roomCode).emit('remote cursor data from server', remoteData);
210+
});
193211
});
194212

195213
//--------------------------------

webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module.exports = {
2929
plugins: [
3030
new Dotenv(),
3131
new webpack.DefinePlugin({
32-
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
32+
'process.env.NODE_ENV': JSON.stringify('development')
3333
})
3434
// new BundleAnalyzerPlugin(),
3535
],

0 commit comments

Comments
 (0)