foundersandcoders / Live-Peers

2 stars 2 forks source link

add room and chat classes #30 #39

Closed jbesraa closed 7 years ago

jbesraa commented 7 years ago

Add chat and room classes. relates to #30

Ok, so Ive been working on this issue for last days.

Here is where Iam currently:

When i think about the whole process, I can see that we should have two classes:

1) chat-room (or channel) class 2) users class

class chatRoom {

  constructor (roomName) {
    this.roomName = roomName;
    this.endpoints = {};
  }

  addEndpoint (endpointID) {
    this.endpoints[endpointID] = {
      permission: 'CHAT'
    }
  }

}

//mock
FACN = new chatRoom('FACN')
}
let users = [];

class newUser {
  constructor(username){
    this.username = username;
    users.push(username)
  }

  isValid() { //should edit
    if(indexOf(comms.roomid.endpoints[username]) == -1)
    {
      successUsername(this.username);
      showActiveUsers();
    }
    else{
      ErrorUsernameTaken();
    }
  }

}

}

couple of things about these classes: 1) i mocked a room, but this room should be created when the mentor create it and then we can know which room it is from the url the mentor gives to the students 1) deleteendpoint function should be added to the chatroom class(useable when user disconnects) 2) user obj added at the newuser class to keep track on who is currently in the room. though, we can do that differently (on the server): io[username]=username (we can move username with a socket from the client side to the server side). im not sure which approach we should follow. 3) isValid function should check if the username is already exist at the specific room. It worked fine with me while i used the socket.username approach(see point 2), i'm not sure about the implementation now. 4) successUsername should:

const successUsername = (username) => {
  comms.roomid.addEndpoint(username);
  username.style.display = 'none';
  register.style.display = 'none';
  chat.style.display = 'block' ;
  message.style.display = 'block';
  send.style.display = 'block';
};

5) showActiveusers should show the current users in the chat room. 6) usernametaken should return a message with error about username is not available

CHAT HANDLERS:

Client side:

let register = document.getElementById('register');
let message = document.getElementsByClassName('message');
let username = document.getElementById('username');
let send = document.getElementById('send');

register.addEventListener('click', () => {
  //registration process(creating new user, making sure the username is not exist in the room, adding the user endpoint to the specific room endpoints list)
})

comms.registerHandler('CHATROOM', 'REGISTER', //..)
comms.registerHandler('CHATROOM', 'MESSAGE', //..)
comms.registerHandler('CHATROOM', 'DISCONNECT', //..)

send.addEventListener('click', () => {
  comms.send('CHATROOM', 'TEXTMESSAGE', this.comms[roomid], message.value);
  displayTextMessage(data);
  value='';
})

A) the CB function at the registerHandler. i didnt really know what i should implement in it. in one hand i would redirect to the router at the backend, but because we are using websockets, im doing that at the router file (see example below). B) im not sure how to start the registration process

Server Side:

const chatHandler = (route, data) => {
  switch (route) {
    case ('CHATROOM.REGISTER') : {
      newuser = new newUser(data)
      newuser.isValid();
      break;
    }

    case ('CHATROOM.MESSAGE') : {
      io.emit('message', data)
      break;
    }

    case ('CHATROOM.DISCONNECT') : {
      //user close window
      break;
    }
  }
};

io.on('connection', (socket) => {
  socket.on('message', (message) => {
    chatHandler('CHATROOM.MESSAGE', message) // point A
  })
  //TODO
  //socket.one('disconnect'..)
})

I) Im not sure if i can chatHandler('CHATROOM.REGISTRATION', data) after io.on('connection, (scoket) =>{ help with that would be appreciated (this issue also refers to point B)


I didnt have time to setup a server and work with it.

at the beginning i build the whole chat with websockets and express server and i could implement alot of things, when i switched and started working with the comms file things got a little bit more complicated.

would love to hear what you think and help with it :)

jbesraa commented 7 years ago

useful resources :

https://github.com/dwyl/hapi-socketio-redis-chat-example https://github.com/smilli/nodejs-chat-complete

jbesraa commented 7 years ago

Instead of chatHandler, I created chat class

const appendP = (output, comms, from, message) => {
  output.appendChild(elt('p', from + ' : ' + message));
};

class Chat {
  constructor (comms, input, output, form) {
    this.comms = comms;
    this.input = input;
    this.output = output;
    this.form = form;
    this.app = 'CHATROOM';
    this.sys = 'SYSTEM';

    comms.send(this.app, 'REGISTER', this.sys, 'JOINED');
    comms.registerHandler(this.app, 'REGISTER', appendP.bind(null, output));
    comms.registerHandler(this.app, 'MESSAGE', appendP.bind(null, output));
    comms.registerHandler(this.app, 'DISCONNECT', appendP.bind(null, output));

    this.form.onsubmit = (e) => {
      e.preventDefault();
      if (this.input.value) {
        this.comms.send(this.app, 'MESSAGE', this.sys, this.input.value);
        this.input.value = '';
      }
    };

    this.input.onkeydown = (e) => {
      if (e.which === 13 && this.input.value) {
        this.comms.send(this.app, 'MESSAGE', this.sys, this.input.value);
        this.input.value = '';
      }
    };
  }
}
const elt = (type, msg) => {
  const newElt = document.createElement(type);
  newElt.innerHTML = msg;
  return newElt;
};

room class

// Global room class
class Room {

  constructor (roomname) {
    this.roomname = roomname;
    this.endpoints = {};
  }
  addEndpoint (endpointId) {
    this.endpoints[endpointId] = {
      name: '',
      permissions: 'CHAT',
      commsid: ''
    };
  }
  updateEndpointName (endpointId, Name) {
    this.endpoints[endpointId].name = Name;
  }
  updateEndpointPermissions (endpointId, permissions) {
    this.endpoints[endpointId].permissions = permissions;
  }
  updateEndpointCommsID (endpointId, commsid) {
    this.endpoints[endpointId].commsid = commsid;
  }
  removeEndpoint (endpointId) {
    delete this.endpoints[endpointId];
  }
  getRoomName () {
    return this.roomname;
  }
  getEndpointNameFromCommsID (commsid) {
    for (let props in this.endpoints) {
      if (this.endpoints[props].commsid === commsid) {
        return props;
      }
    }
  }
}
module.exports = Room;

big credit to nick

jsms90 commented 7 years ago

@esraajb Can you change the name of this pull to be descriptive about what you're actually asking to be merged, and update the body to say that it relates to the relevant issue, please?

jbesraa commented 7 years ago

@jsms90 please see last two commits and let me know if i missed something ?