1 of 159

Announcements

  • No office hours today 🥲 but feel free to stay after lecture!
  • 🥛🍪thought + opinion dump at weblab.is/milkandcookies !
  • Pls give us feedback for yesterday 👉👈🥺 weblab.is/feedback
  • Raffling off $15 amazon gift cards at Mobi sponsor lecture today!

2 of 159

W8 + W9: Chatbook!

***Catbook with Chat***

Michael Kuoch & Andrew Liu

3 of 159

Chatbook: weblab.is/example

4 of 159

The story so far...

Card

Comments

Block

SingleStory

Feed

NewStory

App

Navbar

Profile

Single

Comment

New

Comment

CatHappiness

NotFound

5 of 159

Next couple of days!

ChatList

SingleMessage

SingleUser

Chatbook

Chat

NewMessage

6 of 159

Chatbook Frontend Plan

Refer back to this for a big picture overview

7 of 159

Chatbook: The whole page

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

8 of 159

Chatbook divides into ChatList and Chat

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

9 of 159

ChatList

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

10 of 159

Chat (focus of W8)

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

11 of 159

Props and State...

ChatData refers to {

messages: Array of MessageObjs

recipient: A UserObj

}

MessageObj refers to {

sender: A UserObj

content: A String

}

UserObj refers to {

_id: id (stored as string)

name: A String

}

Who we are chatting with

App

12 of 159

Chatbook Backend Plan

Refer back to this for a big picture overview

13 of 159

Endpoints

server

// Get all of the messages

router.get("/chat", (req, res) => {

});

// Send a message to everyone

router.post("/message", (req, res) => {

});

Teach me how to deal with these requests!!! I don't know what to do!

14 of 159

Endpoints

server

client 1

client 2

post("/api/message", {content: "uwu"})

get("/api/chat", {recipient_id: "25"})

I gotchu

15 of 159

Chatbook Design Recap

16 of 159

Recap (Frontend)

ChatData refers to {

messages: Array of MessageObjs

recipient: A UserObj

}

MessageObj refers to {

sender: A UserObj

content: A String

}

UserObj refers to {

_id: id (stored as string)

name: A String

}

Who we are chatting with

App

17 of 159

Recap (Backend)

server

// Get all of the messages

router.get("/chat", (req, res) => {

});

// Send a message to everyone

router.post("/message", (req, res) => {

});

Teach me how to deal with these requests!!! I don't know what to do!

18 of 159

Let’s make Chatbook!

19 of 159

TODO

exit out of vscode

rm -rf catbook-react

re-clone the repo

(link @ weblab.is/catbook)

19

20 of 159

Let's make Chatbook!!

git fetch

git reset --hard�git checkout w8-step1

npm install

npm start + npm run hotloader

20

21 of 159

Now, the Chat page is empty

git fetch; git reset --hard; git checkout w8-step1

22 of 159

Step 1: Display

git fetch; git reset --hard; git checkout w8-step1

Types & APIs: weblab.to/chatbook-docs

NewMessage

SingleMessage

23 of 159

Step 1 - Let’s Break it Down

App.js

ChatData refers to {

messages: Array of MessageObjs

recipient: A UserObj

}

MessageObj refers to {

sender: A UserObj

content: A String

}

UserObj refers to {

_id: id (stored as string)

name: A String

}

Who we are chatting

1.1

1.2

1.3

1.4

1.5

1.6

24 of 159

Step 1 - Where is everything?

App.js

1.1

1.2

1.3

1.4

1.5

1.6

Step 1.1 & Step 1.2 at bottom of NewMessage in NewPostInput.js

Step 1.3 in SingleMessage.js

Step 1.4 in Chat.js

Step 1.5 in Chatbook.js at bottom

Step 1.6 in Chatbook.js at top

25 of 159

Your Turn

git reset --hard�git checkout w8-step2

25

26 of 159

Step 2: Add the state activeChat to Chatbook

  • Change this to use the state activeChat

git reset --hard; git checkout w8-step2

2.1

File: Chatbook.js

Lines: 48, 67

Types & APIs: weblab.to/chatbook-docs

2.2

27 of 159

Step 2: Add the state activeChat to Chatbook

  • activeChat should be an object with two fields:
  • recipient : who we are currently sending messages to
  • Messages: the messages we’ve sent so far
  • When we start off, we can set our recipient to ALL_CHAT, and we can set messages to be TEST_MESSAGES
  • Hint: initialize state with

const [state, setState] = useState({

<initialState>

});

git reset --hard; git checkout w8-step2

Types & APIs: weblab.to/chatbook-docs

File: Chatbook.js

Lines: 48, 67

28 of 159

Let's get on the same page

git reset --hard�git checkout w8-step3

28

29 of 159

Step 3 - Implement the API endpoints

server

// Get all of the messages

router.get("/chat", (req, res) => {

});

// Send a message to everyone

router.post("/message", (req, res) => {

});

Teach me how to deal with these requests!!! I don't know what to do!

3.3

3.2

What does a message look like though

git reset --hard; git checkout w8-step3

3.1

30 of 159

Step 3: Add Backend for Messages

  • We will add a Message Schema defining the structure of a Message
  • We will add a post request to post a message, and a get request to get all of the existing messages

git reset --hard; git checkout w8-step3

Types & APIs: weblab.to/chatbook-docs

31 of 159

Step 3: Add Backend for Messages

  • We will add a Message Schema defining the structure of a Message
  • We will add a post request to post a message, and a get request to get all of the existing messages

git reset --hard; git checkout w8-step3

Types & APIs: weblab.to/chatbook-docs

32 of 159

Your Turn

git reset --hard�git checkout w8-step4

32

33 of 159

Step 4: Complete sendMessage

git reset --hard; git checkout w8-step4

Types & APIs: weblab.to/chatbook-docs

File: NewPostInput.js

Line: 95

server

client 1

*clicks submit*

(NewMessage)

post the message "Hey I am chatting"

4.1

Ok

34 of 159

Step 4: Complete sendMessage

  • sendMessage should send a post request to the route “/api/message”
  • Post request will take two parameters:
  • recipient: user object for the intended recipient
  • content: the content to be sent on the message
  • If correct, you will see logs on your server whenever you send messages
  • Hint1: the syntax for a post is

post(“<route>”, {param: param_val, param: param_val ..})

  • Hint2: look at your proptypes! Recipient is passed in as a prop
  • Hint3: we pass in the content of our message in the argument value

git reset --hard; git checkout w8-step4

Types & APIs: weblab.to/chatbook-docs

File: NewPostInput.js

Line: 95

35 of 159

Let's get on the same page

git reset --hard�git checkout w8-step5

35

36 of 159

Step 5: Load Messages from Database

git reset --hard; git checkout w8-step5

Types & APIs: weblab.to/chatbook-docs

server

Hey get me all the chat messages to show

Ok

5.1, 5.2

client 1

*loads page*

37 of 159

See the final product

git reset --hard�git checkout w8-complete

37

38 of 159

W9: Sockets

Michael Kuoch & Andrew Liu

Games!!

Live Interaction!!

Chat!!

39 of 159

Announcements

  • Milestone 1 should be graded (you should see it in the portal)
    • If you submitted stuff late / on video it might not be up yet, but we’re working on it
    • If you want credit or competition, you should submit :)
  • OH tomorrow 7-9pm in 32-082
  • Hackathon Friday 7pm-1am in 32-082

40 of 159

Let’s see what Chatbook looks like so far

41 of 159

41

42 of 159

42

Chat solved

43 of 159

Storytime

44 of 159

85% True Story*

*Some details may be exaggerated for dramatic effect

45 of 159

During beta testing

CEO of Catbook

Unfortunately, our customers are mad that you have to refresh the page to see new feed and messages.

They want live interaction and CHAT. Please make something for them!

I gotchu, bro

46 of 159

During Lunch

CEO of Catbook

Bruh.

You still have to refresh the page to see new messages :(

47 of 159

Real Time Chatbook with Socket.io

Finally what you came for!

48 of 159

How we want it to work

Fluffy

Whiskers

Joe

POST /api/message “meow”

server

49 of 159

How we want it to work

Fluffy

Whiskers

Joe

POST hey Fluffy just said meow

server

50 of 159

Doesn’t work!

Fluffy

Whiskers

Joe

X

X

server

i can't initiate conversations :(

51 of 159

Limitation of HTTP

Client sends request to Server

Server responds to Client

Server can’t send data to the client unless a request is made

GET /api/chat

response

52 of 159

How do we fix this?

53 of 159

Polling: Ask the server every (x) seconds

Joe

(GET) any new messages?

nope nothing yet

(GET) any new messages?

nope nothing yet

(GET) any new messages?

Yes! Fluffy said meow

54 of 159

Just teach the server to initiate conversations

55 of 159

We can teach the server to initiate!

A real-time library that uses WebSocket

56 of 159

Lunch Break

Until

1:00

56

57 of 159

Lunch Logistics

Catbook CEO

Open portal.weblab.is

and log in, showing us that you are registered for the class

Eat outside the classroom,

Return at 1:00 :)

1 burrito / bowl only for now

58 of 159

Lunch Logistics

Open portal.weblab.is

and log in, showing us that you are registered for the class

Eat outside the classroom,

Return at 1:00 :)

1 piece only for now

59 of 159

Socket IO

Joe

Hey let’s socket (handshake)

ok bet (upgrade)

Fluffy said meow

(WOW I can initiate conversations now!)

...later

60 of 159

Socket IO

Server

Client

61 of 159

Socket IO

Server

Client

Client

Client

62 of 159

Socket IO

Server

Client

Client

Client

63 of 159

Broadcast using sockets

Fluffy

Whiskers

Joe

POST /api/message “meow”

64 of 159

Broadcast using sockets

Fluffy

Whiskers

Joe

new msg “meow”

(ws)

new msg “meow”

(ws)

new msg “meow”

(ws)

65 of 159

Basic Usage

Broadcast a message from server to everyone connected

socketManager.getIo().emit("event_name", data)

The Title The data

(object, list, string, etc)

We coded this for you!

66 of 159

Basic Usage

Broadcast a message from server to everyone connected

socketManager.getIo().emit("event_name", data)

Listen for messages on client

socket.on("event_name", someFunction)

The Title The data

(object, list, string, etc)

The Title what to do when you get a socket emit of that title

will look like (data) => { do something with data }

We coded this for you!

67 of 159

Professor

Students

On "new_pset",

start working

Emit ("new_pset", pset_obj)

68 of 159

Professor

Students

emit(‘new_pset’, {

due: ‘1/20/23’,

questions: [

‘what is 9 + 10’,

‘does P = NP?’

]

});

on(‘new_pset’, (pset) => {

while (pset.due !== tomorrow) {

procrastinate();

}

solve(pset.questions);

});

69 of 159

Whiskers

Joe

socketManager.getIo().emit(‘message’, messageObj)

socket.on(‘message’, cb)

socket.on(‘message’, cb)

70 of 159

Let’s Socket-ify Chatbook!

71 of 159

Let’s recap Chatbook design

72 of 159

Chatbook Front End Roadmap

ChatList

SingleMessage

SingleUser

Chatbook

Chat

NewMessage

73 of 159

Chatbook Frontend Plan

Refer back to this for a big picture overview

74 of 159

Chatbook: The whole page

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

75 of 159

Chatbook divides into ChatList and Chat

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

76 of 159

Chat

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

77 of 159

ChatList

Chatbook

ChatList

SingleMessage

SingleUser

Chat

NewMessage

78 of 159

Props and State...

ChatData refers to {

messages: Array of MessageObjs

recipient: A UserObj

}

MessageObj refers to {

sender: A UserObj

content: A String

}

UserObj refers to {

_id: id (stored as string)

name: A String

}

Who we are chatting with

App

79 of 159

Chatbook Backend

Refer back to this for a big picture overview

80 of 159

Endpoints

server

// Get all of the messages

router.get("/chat", (req, res) => {

});

// Send a message to everyone

router.post("/message", (req, res) => {

});

81 of 159

Endpoints

server

client 1

client 2

client 3

get("/api/chat")

post("/api/message", {content: "uwu"})

get("/api/chat", {recipient_id: "25"})

I gotchu

(**We’ll add this!**)

82 of 159

Chatbook Design Recap

83 of 159

Summary (Frontend)

ChatData refers to {

messages: Array of MessageObjs

recipient: A UserObj

}

MessageObj refers to {

sender: A UserObj

content: A String

}

UserObj refers to {

_id: id (stored as string)

name: A String

}

Who we are chatting with

App

84 of 159

Summary (Backend)

server

// Get all of the messages

router.get("/chat", (req, res) => {

});

// Send a message to everyone

router.post("/message", (req, res) => {

});

85 of 159

Now We’re Ready to Socket-ify Chatbook!

86 of 159

Go to catbook-react!

git fetch

git reset --hard

git checkout w9-starter

git pull

npm install

Start the hotloader and server

86

87 of 159

Chatbook! (part 2)

Information: weblab.is/socket-guide

Side Slides: weblab.is/socket-docs

87

88 of 159

Chatbook! (part 2)

Main Slides: weblab.is/w9-slides

Side Slides: weblab.is/w9-context

88

89 of 159

Basic Usage

Broadcast a message from server to everyone connected

socketManager.getIo().emit("event_name", data)

The Title The data

(object, list, string, etc)

We coded this for you!

90 of 159

Basic Usage

Broadcast a message from server to everyone connected

socketManager.getIo().emit("event_name", data)

Listen for messages on client

socket.on("event_name", someFunction)

The Title The data

(object, list, string, etc)

The Title what to do when you get a socket emit of that title

will look like (data) => { do something with data }

We coded this for you!

91 of 159

Step 0: Add Sockets to See Messages Instantly!

git reset --hard; git checkout w9-starter

92 of 159

Step 0: Add Sockets to See Messages Instantly!

Backend:

git reset --hard; git checkout w9-starter

...

Files: api.js, line 98

server

*shouts to everyone*

93 of 159

Step 0: Add Sockets to See Messages Instantly!

Backend:

Frontend:

git reset --hard; git checkout w9-starter

...

Files: api.js, line 98; Chatbook.js, line 67

server

*shouts to everyone*

client 1

*when i hears server's shout, do something with the data*

this callback function is defined for you!

94 of 159

Step 0: Add Sockets to See Messages Instantly!

Backend:

Frontend:

git reset --hard; git checkout w9-starter

...

Files: api.js, line 98; Chatbook.js, line 67

server

*shouts to everyone*

client 1

*when i hears server's shout, do something with the data*

these strings must match (it’s the name of the communication)

this callback function is defined for you!

95 of 159

Broadcast using sockets

Fluffy

Whiskers

Joe

POST /api/message “meow”

96 of 159

Broadcast using sockets

Fluffy

Whiskers

Joe

new msg “meow”

(ws)

new msg “meow”

(ws)

new msg “meow”

(ws)

97 of 159

See demo

git reset --hard�git checkout w9-step1

97

98 of 159

But what about sending DMs? 🤔

98

99 of 159

The problem of identity

99

Fluffy

Joe

POST /api/meow “FOOD”

To Whiskers

Whiskers

100 of 159

The problem of identity

100

Fluffy

Joe

Whiskers

new meow “FOOD”

(ws)

101 of 159

The problem of identity

101

Fluffy

Joe

new meow “FOOD”

(ws)

io.emit alone is public to all sockets, so we need more!

Whiskers

POST /api/meow “FOOD”

To Whiskers

102 of 159

io.emit behind the scenes

102

Fluffy

Joe

Whiskers

POST /api/meow “FOOD”

To Whiskers

socketManager.getIo().emit(“meow”, “FOOD”)

(ws)

103 of 159

io.emit behind the scenes

103

Fluffy

Joe

Whiskers

Joe’s socket

Whiskers’

socket

POST /api/meow “FOOD”

To Whiskers

104 of 159

io.emit behind the scenes

104

Fluffy

Joe

Whiskers

socket

socket

IO Object

socketManager.getIo()

POST /api/meow “FOOD”

To Whiskers

105 of 159

io.emit behind the scenes

105

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

socket1.emit(“meow”, “FOOD”)

socket2.emit(“meow”, “FOOD”)

POST /api/meow “FOOD”

To Whiskers

106 of 159

Problem: server doesn’t know Whiskers’ socket

106

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

107 of 159

Socket initialized by the client

107

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

(on initial connection)

https handshake:

we agree to follow some protocols

related to this new connection

108 of 159

Socket initialized by the client

108

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

(on initial connection)

https handshake:

we agree to follow some protocols

related to this new connection

does not include information about the user!

server adds socket to io object blindly

109 of 159

But Whiskers knows its socket!

109

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

(on initial connection)

POST /api/initsocket hi it’s whiskers, my socket is socket1

110 of 159

Tell server which socket the user is

110

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

POST /api/initsocket hi it’s whiskers, my socket is socket1

Server can check with req.user!

(on initial connection)

111 of 159

Tell server which socket the user is

111

Fluffy

Joe

Whiskers

socket2

socket1

IO Object

Server can check with req.user!

socketManager.addUser(whiskers, socket1)

(on initial connection)

112 of 159

Tell server which socket the user is

112

Fluffy

Joe

Whiskers

IO Object

Server can check with req.user!

Whiskers’

socket

Joe’s socket

socketManager.addUser(whiskers, socket1)

(on initial connection)

113 of 159

getSocketFromUserID

113

Fluffy

Joe

Whiskers

Joe’s socket

Whiskers’

socket

IO Object

We can now use socketManager.getSocketFromUserID

to get a user’s socket!

(this function is given to you by staff)

POST /api/meow “FOOD”

To Whiskers

114 of 159

getSocketFromUserID

114

Fluffy

Joe

Whiskers

Joe’s socket

Whiskers’

socket

IO Object

We can now use socketManager.getSocketFromUserID

to get a user’s socket!

(this function is given to you by staff)

socketManager

.getSocketFromUserID(“whiskers_id”)

.emit(“meow”, “FOOD”)

POST /api/meow “FOOD”

To Whiskers

115 of 159

weblab.is/chatbook-docs

weblab.is/socket-guide

115

116 of 159

YAY! We now have everything we need for DMs

Let’s talk about the plan ^___^

weblab.is/example

116

117 of 159

Chatbook Component Tree

117

ChatList

SingleMessage

SingleUser

Chatbook

Chat

NewMessage

118 of 159

Chatbook Component Tree

118

ChatList

SingleMessage

SingleUser

Chatbook

Chat

NewMessage

119 of 159

119

ChatList

SingleUser

Chatbook

120 of 159

120

ChatList

SingleUser

Chatbook

activeChat: ChatData

activeUsers: array of UserObject}

Props: {

setActiveUser: callback function,

userId: String,

users: array of UserObject,

active: UserObject

}

Props: {

setActiveUser: callback function,

user: UserObject,

active: Boolean

}

App

userId: String

Props: {userId: String}

121 of 159

121

UserObject: {

_id: String,

name: String

}

ChatData: {

messages: array of MessageObject,

recipient: UserObject

}

ChatList

SingleUser

Chatbook

activeChat: ChatData

activeUsers: array of UserObject}

Props: {

setActiveUser: callback function,

userId: String,

users: array of UserObject,

active: UserObject

}

Props: {

setActiveUser: callback function,

user: UserObject,

active: Boolean

}

App

userId: String

Props: {userId: String}

122 of 159

Backend API

122

123 of 159

123

client

Socket connection

124 of 159

124

client

Socket connection

POST /api/initsocket

125 of 159

125

client

login

POST /api/initsocket

126 of 159

126

client

login

POST /api/initsocket

emit(“activeUsers”, <list of users>)

client

127 of 159

127

client

GET /api/activeUsers

128 of 159

Now let’s code it up!

128

129 of 159

Catch Up!

git reset --hard�git checkout w9-step1

129

130 of 159

[Live Coding]

130

131 of 159

Step 1: Create the initsocket endpoint

  • Register the client to its socket using socketManager

131

git reset --hard; git checkout w9-step1

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 77

Whiskers

socket1

IO Object

(on initial connection)

POST /api/initsocket hi it’s whiskers, my socket is socket1

132 of 159

Step 2: Build SingleUser Buttons

132

git reset --hard; git checkout w9-step2

Types & APIs: weblab.is/chatbook-docs

File: SingleUser.js

Line: 14

133 of 159

Step 2: Build List of Users (ChatList)

133

git reset --hard; git checkout w9-step2

Types & APIs: weblab.is/chatbook-docs

File: ChatList.js

Line: 16

134 of 159

134

UserObject: {

_id: String,

name: String

}

ChatData: {

messages: array of MessageObject,

recipient: UserObject

}

ChatList

SingleUser

Chatbook

activeChat: ChatData

activeUsers: array of UserObject}

Props: {

setActiveUser: callback function,

userId: String,

users: array of UserObject,

active: UserObject

}

Props: {

setActiveUser: callback function,

user: UserObject,

active: Boolean

}

App

userId: String

Props: {userId: String}

135 of 159

Step 3: Add ChatList component to Chatbook

  • Insert the ChatList component we just built into Chatbook
  • Check ChatList.js for the 4 props that you should pass in
  • Hint1: Components are initialized like so:

<ComponentName prop1name=prop1val prop2name=prop2val ../>

135

git reset --hard; git checkout w9-step3

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 86

136 of 159

Step 3: Add ChatList component to Chatbook

  • Insert the ChatList component we just built into Chatbook
  • Check ChatList.js for the 4 props that you should pass in
  • Hint1: Components are initialized like so:

<ComponentName prop1name=prop1val prop2name=prop2val ../>

  • Hint2: users prop should be the activeUsers state

136

git reset --hard; git checkout w9-step3

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 86

137 of 159

Step 3: Add ChatList component to Chatbook

  • Insert the ChatList component we just built into Chatbook
  • Check ChatList.js for the 4 props that you should pass in
  • Hint1: Components are initialized like so:

<ComponentName prop1name=prop1val prop2name=prop2val ../>

  • Hint2: users prop should be activeUsers held in state
  • Hint3: look inside the state activeChat which should hold the current active user and pass that as the active prop

137

git reset --hard; git checkout w9-step3

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 86

138 of 159

Step 3: Add ChatList component to Chatbook

  • Insert the ChatList component we just built into Chatbook
  • Check ChatList.js for the 4 props that you should pass in
  • Hint1: Components are initialized like so:

<ComponentName prop1name=prop1val prop2name=prop2val ../>

  • Hint2: users prop should be activeUsers held in state
  • Hint3: look inside the state activeChat which should hold the current active user and pass that as the active prop
  • Hint4: userId was passed into this component as a prop

138

git reset --hard; git checkout w9-step3

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 86

139 of 159

Step 4: Implement /api/activeUsers

  • Send back an object with the field activeUsers set to the currently active users
  • Hint1: You can send back a response with res.send(<object>)

139

git reset --hard; git checkout w9-step4

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 103

140 of 159

Step 4: Implement /api/activeUsers

  • Send back an object with the field activeUsers set to the currently active users
  • Hint1: You can send back a response with res.send(<object>)
  • Hint2: Object syntax is {<field-name> : <field-value>}

140

git reset --hard; git checkout w9-step4

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 103

141 of 159

Step 4: Implement /api/activeUsers

  • Send back an object with the field activeUsers set to the currently active users
  • Hint1: You can send back a response with res.send(<object>)
  • Hint2: Object syntax is {<field-name> : <field-value>}
  • Hint3: You can get all the connected users with socketManager.getAllConnectedUsers()

141

git reset --hard; git checkout w9-step4

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 103

142 of 159

[Live Coding]

142

143 of 159

Step 5: Call /activeUsers

  • Use the /activeUsers endpoint to get the active users on the site
  • Set the active users to be displayed on the webpage

143

git reset --hard; git checkout w9-step5

Types & APIs: weblab.is/chatbook-docs

File: ChatBook.js

Line: 69

144 of 159

Step 6: Listen for the activeUsers event

  • Use “socket.on” to catch the activeUsers event.
  • In the callback function, set the state of activeUsers to the new list of active users
  • Hint1: look at socket.on(“message”) in the same file to see how to listen on a socket event!

144

git reset --hard; git checkout w9-step6

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 85

145 of 159

Step 6: Listen for the activeUsers event

  • Use “socket.on” to catch the activeUsers event.
  • In the callback function, set the state of activeUsers to the new list of active users
  • Hint1: look at socket.on(“message”) in the same file to see how to listen on a socket event!
  • Hint2: look at get(“/api/activeUsers”) to see what we should do to update the state to the new list of activeUsers

145

git reset --hard; git checkout w9-step6

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 85

146 of 159

Step 7: Implement setActiveUser

  • We implemented setActiveUser partially a while ago, you just need to change it to set the state instead of console logging! Do the following:
  • First, set the state activeChat to the passed in user as recipient and empty message array as messages
  • Then, figure out a clean way to load the message history (may need to add code elsewhere)
  • Hint: You can load the message history by calling loadMessageHistory(user)

146

git reset --hard; git checkout w9-step7

Types & APIs: weblab.is/chatbook-docs

File: Chatbook.js

Line: 96

147 of 159

[Live Coding]

147

148 of 159

Step 8: Update /getChat

  • Update the query to handle DMs

148

git reset --hard; git checkout w9-step8

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 82

let query;

if (req.query.recipient_id === "ALL_CHAT") {

query = { "recipient._id": "ALL_CHAT" };

} else {

// get messages that are from me->you OR you->me

query = {

$or: [

{ "sender._id": req.user._id, "recipient._id": req.query.recipient_id },

{ "sender._id": req.query.recipient_id, "recipient._id": req.user._id },

],

};

}

149 of 159

Step 9: Emit a message event to relevant users

  • We emitted a message to the currently signed in user, now we just need to emit to the recipient!
  • Emit a “message” event to the socket connected to the recipient
  • Hint: Look at how we sent the message back to the sender (req.user)

149

git reset --hard; git checkout w9-step9

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 113

150 of 159

Step 9: Emit a message event to relevant users

  • We emitted a message to the currently signed in user, now we just need to emit to the recipient!
  • Emit a “message” event to the socket connected to the recipient
  • Hint1: you can get the recipient id using req.body.recipient

150

git reset --hard; git checkout w9-step9

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 113

151 of 159

Step 9: Emit a message event to relevant users

  • We emitted a message to the currently signed in user, now we just need to emit to the recipient!
  • Emit a “message” event to the socket connected to the recipient
  • Hint1: you can get the recipient id using req.body.recipient
  • Hint2: you want to emit the same contents as the message we just emitted to the current user

151

git reset --hard; git checkout w9-step9

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 113

152 of 159

Step 9: Emit a message event to relevant users

  • We emitted a message to the currently signed in user, now we just need to emit to the recipient!
  • Emit a “message” event to the socket connected to the recipient
  • Hint1: you can get the recipient id using req.body.recipient
  • Hint2: you want to emit the same contents as the message we just emitted to the current user
  • Hint3: use socketManager.getSocketFromUserID!

152

git reset --hard; git checkout w9-step9

Types & APIs: weblab.is/chatbook-docs

File: api.js

Line: 113

153 of 159

Step 10: Filter some messages at on the client side

  • Coming soon!

153

git reset --hard; git checkout w9-step10

Types & APIs: weblab.is/chatbook-docs

File:

Line:

154 of 159

Now you try! Catch the forceDisconnect event

  • Use “socket.on” to catch the forceDisconnect event.
  • In the callback function, set the state of socketDisconnected to false
  • Hint: this is what we did to catch the message event and change state in Chatbook.js

154

155 of 159

SHOUT: socketManager.getIO()

whisper: socketManager.getSocketFromUserId()

155

156 of 159

client-socket & server-socket

156

157 of 159

Sockets in Practice

// Client, inside useEffect() with cleanup!

socket.on("eventName", (data) => {

// Do stuff with data

});

// Server, probably inside an API call or helper function

socketManager.getIo().emit("eventName", data); // SHOUT

// whisper

socketManager.getSocketFromUserID(userID).emit("eventName", data);

157

Details: weblab.is/socket-guide

158 of 159

Be Back at 1:00pm :)

Do not eat in the lecture hall :)

159 of 159

EOD Announcements

  • No office hours today 🥲 but feel free to stay after lecture!
  • Render sponsor lecture on Friday at 1 PM!
  • HW3: Creating a Render account (due Friday) will be out tonight
  • Milestone 2 (MVP) due next Wednesday, Jan 24 at 6 PM
    • Guidelines can be found at weblab.mit.edu/about/#milestones
  • Recording for final steps of workshop 9 will be recorded and posted
    • Emitting events to individual sockets! Important for things like DMs and games
  • 🥛🍪 thoughts + opinion dump at weblab.is/milkandcookies !
  • 🌱 Feedback for today!! weblab.is/feedback