Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { renderHook } from '@testing-library/react-hooks';

import { useCooldownTimer } from '../useCooldownTimer';

import { ChannelStateProvider, ChatProvider } from '../../../../context';
import { getTestClient } from '../../../../mock-builders';

async function renderUseCooldownTimerHook({ channel, chatContext }) {
const client = await getTestClient();

const wrapper = ({ children }) => (
<ChatProvider value={{ client, ...chatContext }}>
<ChannelStateProvider value={{ channel }}>{children}</ChannelStateProvider>
</ChatProvider>
);
return renderHook(useCooldownTimer, { wrapper });
}

const cid = 'cid';
const cooldown = 30;
describe('useCooldownTimer', () => {
it('should set remaining cooldown time to if no channel.cooldown', async () => {
const channel = { cid };
const chatContext = { latestMessageDatesByChannels: {} };
const { result } = await renderUseCooldownTimerHook({ channel, chatContext });
expect(result.current.cooldownRemaining).toBe(0);
});
it('should set remaining cooldown time to 0 if skip-slow-mode is among own_capabilities', async () => {
const channel = { cid, data: { cooldown, own_capabilities: ['skip-slow-mode'] } };
const chatContext = { latestMessageDatesByChannels: { cid: new Date() } };
const { result } = await renderUseCooldownTimerHook({ channel, chatContext });
expect(result.current.cooldownRemaining).toBe(0);
});
it('should set remaining cooldown time to 0 if no previous messages sent', async () => {
const channel = { cid, data: { cooldown } };
const chatContext = { latestMessageDatesByChannels: {} };
const { result } = await renderUseCooldownTimerHook({ channel, chatContext });
expect(result.current.cooldownRemaining).toBe(0);
});
it('should set remaining cooldown time to 0 if previous messages sent earlier than channel.cooldown', async () => {
const channel = { cid, data: { cooldown } };
const chatContext = { latestMessageDatesByChannels: { cid: new Date('1970-1-1') } };
const { result } = await renderUseCooldownTimerHook({ channel, chatContext });
expect(result.current.cooldownRemaining).toBe(0);
});
it('should set remaining cooldown time to time left from previous messages sent', async () => {
const channel = { cid, data: { cooldown } };
const lastSentSecondsAgo = 5;
const chatContext = {
latestMessageDatesByChannels: {
cid: new Date(new Date().getTime() - lastSentSecondsAgo * 1000),
},
};
const { result } = await renderUseCooldownTimerHook({ channel, chatContext });
expect(result.current.cooldownRemaining).toBe(cooldown - lastSentSecondsAgo);
});
});
31 changes: 16 additions & 15 deletions src/components/MessageInput/hooks/useCooldownTimer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import React, { useEffect, useMemo, useState } from 'react';

import { useChatContext } from '../../../context/ChatContext';
import { useChannelStateContext } from '../../../context/ChannelStateContext';

import type { ChannelResponse } from 'stream-chat';

import { useChannelStateContext, useChatContext } from '../../../context';

import type { DefaultStreamChatGenerics } from '../../../types/types';

export type CooldownTimerState = {
Expand All @@ -16,15 +14,16 @@ export type CooldownTimerState = {
export const useCooldownTimer = <
StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics
>(): CooldownTimerState => {
const { latestMessageDatesByChannels } = useChatContext<StreamChatGenerics>('useCooldownTimer');
const { client, latestMessageDatesByChannels } = useChatContext<StreamChatGenerics>(
'useCooldownTimer',
);
const { channel, messages = [] } = useChannelStateContext<StreamChatGenerics>('useCooldownTimer');
const { client } = useChatContext<StreamChatGenerics>('useCooldownTimer');
const [cooldownRemaining, setCooldownRemaining] = useState<number>();

const { cooldown: cooldownInterval, own_capabilities } = (channel.data ||
const { cooldown: cooldownInterval = 0, own_capabilities } = (channel.data ||
{}) as ChannelResponse<StreamChatGenerics>;

const skipCooldown = !own_capabilities?.includes('slow-mode');
const skipCooldown = own_capabilities?.includes('skip-slow-mode');

const ownLatestMessageDate = useMemo(
() =>
Expand All @@ -36,17 +35,19 @@ export const useCooldownTimer = <
) as Date;

useEffect(() => {
if (skipCooldown || !cooldownInterval || !ownLatestMessageDate) return;

const remainingCooldown = Math.round(
cooldownInterval - (new Date().getTime() - ownLatestMessageDate.getTime()) / 1000,
const timeSinceOwnLastMessage = ownLatestMessageDate
? (new Date().getTime() - ownLatestMessageDate.getTime()) / 1000
: undefined;

setCooldownRemaining(
!skipCooldown && timeSinceOwnLastMessage && cooldownInterval > timeSinceOwnLastMessage
? Math.round(cooldownInterval - timeSinceOwnLastMessage)
: 0,
);

if (remainingCooldown > 0) setCooldownRemaining(remainingCooldown);
}, [cooldownInterval, ownLatestMessageDate, skipCooldown]);

return {
cooldownInterval: cooldownInterval ?? 0,
cooldownInterval,
cooldownRemaining,
setCooldownRemaining,
};
Expand Down