Issue #399

Client

App.js

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Main from './Main'

class App extends Component {
  render() {
    return <Main />
  }
}

export default App;

Main.js

// @flow

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';

import Manager from './Manager'

const styles = {
    root: {
      flexGrow: 1,
    },
    grow: {
      flexGrow: 1,
    },
    menuButton: {
      marginLeft: -12,
      marginRight: 20,
    },
};

class Main extends React.Component {
    static propTypes = {
        classes: PropTypes.object.isRequired,
    }

    render() {
        const { classes } = this.props;

        return (
            <div className={classes.root}>
              <AppBar position="static">
                <Toolbar>
                  <IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
                    <MenuIcon />
                  </IconButton>
                  <Typography variant="h6" color="inherit" className={classes.grow}>
                    Collaborate Canvas
                  </Typography>
                  <Button color="inherit" onClick={this.onImagePress} >Image</Button>
                  <Button color="inherit" onClick={this.onClearPress} >Clear</Button>
                  <input ref="fileInput" type="file" id="myFile" multiple accept="image/*" style={{display: 'none'}} onChange={this.handleFiles}></input>
                </Toolbar>
              </AppBar>
              <canvas ref="canvas" with="1000" height="1000"></canvas>
            </div>
        )
    }

    componentDidMount() {
      const canvas = this.refs.canvas
      this.manager = new Manager(canvas)
      this.manager.connect()
    }

    onImagePress = () => {
      const fileInput = this.refs.fileInput
      fileInput.click()
    }

    onClearPress = () => {
      this.manager.clear()
    }

    handleFiles = (e) => {
      e.persist()
      const canvas = this.refs.canvas
      const context = canvas.getContext('2d')

      const file = e.target.files[0]
      var image = new Image()
      image.onload = function() {
          context.drawImage(image, 0, 0, window.innerWidth, window.innerHeight)
      }
      image.src = URL.createObjectURL(file)
    }
}

export default withStyles(styles)(Main);

Server

Use express and socket.io

index.js

// @flow

const express = require('express')
const app = express()
const http = require('http')
const socketIO = require('socket.io')

const server = http.createServer(app)
const io = socketIO.listen(server)
server.listen(3001)
app.use(express.static(__dirname + '/public'))
console.log("Server running on 127.0.0.1:8080")

let lines = []
io.on('connection', (socket) => {
    lines.forEach((line) => {
        const data = { line }
        socket.emit('draw_line', data) 
    })

    socket.on('draw_line', (data) => {
        const { line } = data
        lines.push(line)

        io.emit('draw_line', data)
    })

    socket.on('clear', () => {
        lines = []
        io.emit('clear')
    })

    socket.on('draw_image', (data) => {
        io.emit('draw_image', data)
    })
})