RocketChat/Rocket.Chat

View on GitHub
apps/meteor/client/views/room/contexts/RoomContext.ts

Summary

Maintainability
A
0 mins
Test Coverage
import type { IRoom, IOmnichannelRoom, IVoipRoom, ISubscription } from '@rocket.chat/core-typings';
import { isOmnichannelRoom, isVoipRoom } from '@rocket.chat/core-typings';
import { createContext, useContext } from 'react';

export interface IRoomWithFederationOriginalName extends IRoom {
    federationOriginalName?: string;
}

type RoomContextValue = {
    rid: IRoom['_id'];
    room: IRoomWithFederationOriginalName;
    subscription?: ISubscription;
    hasMorePreviousMessages: boolean;
    hasMoreNextMessages: boolean;
    isLoadingMoreMessages: boolean;
};

export const RoomContext = createContext<RoomContextValue | null>(null);

export const useUserIsSubscribed = (): boolean => {
    const context = useContext(RoomContext);

    if (!context) {
        throw new Error('use useRoom only inside opened rooms');
    }

    return !!context.subscription;
};

export const useRoom = (): IRoom => {
    const context = useContext(RoomContext);

    if (!context) {
        throw new Error('use useRoom only inside opened rooms');
    }

    return context.room;
};

export const useRoomSubscription = (): ISubscription | undefined => {
    const context = useContext(RoomContext);

    if (!context) {
        throw new Error('use useRoomSubscription only inside opened rooms');
    }

    return context.subscription;
};

export const useRoomMessages = (): {
    hasMorePreviousMessages: boolean;
    hasMoreNextMessages: boolean;
    isLoadingMoreMessages: boolean;
} => {
    const context = useContext(RoomContext);

    if (!context) {
        throw new Error('use useRoomMessages only inside opened rooms');
    }

    return {
        hasMorePreviousMessages: context.hasMorePreviousMessages,
        hasMoreNextMessages: context.hasMoreNextMessages,
        isLoadingMoreMessages: context.isLoadingMoreMessages,
    };
};

export const useOmnichannelRoom = (): IOmnichannelRoom => {
    // TODO: today if the user do not belong in the room, the room object will not update on new changes
    // for normal rooms this is OK, but for Omnichannel rooms,
    // there are cases where an agent can be outside of the room but need to see the room changes
    // A solution would be to use subscribeToRoom to get the room updates

    const { room } = useContext(RoomContext) || {};

    if (!room) {
        throw new Error('use useRoom only inside opened rooms');
    }

    if (!isOmnichannelRoom(room)) {
        throw new Error('invalid room type');
    }

    return room;
};

export const useVoipRoom = (): IVoipRoom => {
    const { room } = useContext(RoomContext) || {};

    if (!room) {
        throw new Error('use useRoom only inside opened rooms');
    }

    if (!isVoipRoom(room)) {
        throw new Error('invalid room type');
    }

    return room;
};