ChatHub Integration Guide - wwestlake/Labyrinth GitHub Wiki

ChatHub Integration Guide

Overview

The ChatHub is a SignalR hub in the Labyrinth project that facilitates real-time communication between clients. It supports joining and leaving rooms (channels), sending messages to specific channels, and broadcasting notices to the general chat channel.

SignalR Hub Methods

1. JoinRoom

  • Method: JoinRoom(string roomId)

  • Description: Adds the current connection to a specified room (channel).

  • Client-Side Usage:

    • To join a room, invoke this method from the client after establishing the SignalR connection.
    • Example:
      await connection.invoke("JoinRoom", roomId);
  • Server Behavior:

    • The client is added to a SignalR group corresponding to the roomId.
    • A system message is broadcasted to all users in the room announcing the new user's arrival.

2. LeaveRoom

  • Method: LeaveRoom(string roomId)

  • Description: Removes the current connection from a specified room (channel).

  • Client-Side Usage:

    • To leave a room, invoke this method when the user wants to exit a room.
    • Example:
      await connection.invoke("LeaveRoom", roomId);
  • Server Behavior:

    • The client is removed from the SignalR group corresponding to the roomId.
    • A system message is broadcasted to all users in the room announcing the user's departure.

3. SendMessage

  • Method: SendMessage(string channelId, string user, string message)

  • Description: Sends a message to a specific channel (e.g., room or role-based channel).

  • Client-Side Usage:

    • Use this method to send a message from a user to a specific channel.
    • Example:
      await connection.invoke("SendMessage", channelId, user, message);
  • Server Behavior:

    • The message is sent to all clients connected to the specified channelId.

4. SendNotice

  • Method: SendNotice(string message)

  • Description: Broadcasts a notice message to the general chat channel.

  • Client-Side Usage:

    • This method is typically used by administrators to broadcast important messages.
    • Example:
      await connection.invoke("SendNotice", message);
  • Server Behavior:

    • The notice message is sent to all clients connected to the "General" chat channel, with the sender identified as "Admin".

5. OnDisconnectedAsync

  • Method: OnDisconnectedAsync(Exception exception)

  • Description: Handles client disconnection, including any necessary cleanup.

  • Client-Side Usage:

    • This is handled automatically by the SignalR framework, and there is no need to invoke this method manually.
  • Server Behavior:

    • Custom logic can be added to manage cleanup when a client disconnects. The default behavior simply ensures that the disconnection is logged and handled gracefully.

Client-Side Implementation Example

Here's how to set up a client-side connection to the ChatHub using JavaScript (React):

import React, { useState, useEffect } from 'react';
import { HubConnectionBuilder } from '@microsoft/signalr';

const ChatBox = () => {
  const [connection, setConnection] = useState(null);
  const [currentChannel, setCurrentChannel] = useState('general');
  const [messages, setMessages] = useState([]);
  const [message, setMessage] = useState('');

  useEffect(() => {
    const setupConnection = async () => {
      try {
        const user = auth.currentUser;

        if (user) {
          const token = await user.getIdToken(true); // Get the JWT token

          const newConnection = new HubConnectionBuilder()
            .withUrl("http://localhost:5232/chat", {
              accessTokenFactory: () => token,
              withCredentials: true,
            })
            .withAutomaticReconnect()
            .build();

          newConnection.on("ReceiveMessage", (user, message) => {
            setMessages(messages => [...messages, { user, text: message, channel: currentChannel, timestamp: new Date().toLocaleTimeString() }]);
          });

          await newConnection.start();
          console.log("Connected to SignalR hub");

          await newConnection.invoke("JoinRoom", currentChannel);

          setConnection(newConnection);
        }
      } catch (e) {
        console.log("Connection failed: ", e);
      }
    };

    setupConnection();

    return () => {
      if (connection) {
        connection.stop();
      }
    };
  }, []);

  const handleSendMessage = async () => {
    if (connection && connection.connectionStarted) {
      try {
        await connection.invoke("SendMessage", currentChannel, "currentUser", message);
        setMessage('');
      } catch (e) {
        console.error("Message send failed: ", e);
      }
    } else {
      console.error("No connection to server yet.");
    }
  };

  const handleChannelChange = async (channel) => {
    if (connection) {
      await connection.invoke("LeaveRoom", currentChannel);
      await connection.invoke("JoinRoom", channel);
      setCurrentChannel(channel);
      setMessages([]); // Clear messages when switching channels
    }
  };

  return (
    <div className="chat-box">
      <ChatHeader currentChannel={currentChannel} />
      <ChannelTabs currentChannel={currentChannel} onChannelChange={handleChannelChange} />
      <ChatMessages messages={messages.filter(msg => msg.channel === currentChannel)} />
      <ChatInput
        message={message}
        onMessageChange={setMessage}
        onSendMessage={handleSendMessage}
      />
    </div>
  );
};

export default ChatBox;

Summary

The ChatHub provides a robust foundation for real-time communication within the Labyrinth application. By correctly implementing the methods provided by the hub, users can interact within various channels, send messages, and receive real-time updates. This document serves as a guide to understanding and using the ChatHub effectively in the client-side application.

⚠️ **GitHub.com Fallback** ⚠️