You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.5 KiB
TypeScript
132 lines
3.5 KiB
TypeScript
import React, { useCallback, useEffect, useState } from 'react';
|
|
import { useDispatch } from 'react-redux';
|
|
import { useInterval } from 'react-use';
|
|
import styled from 'styled-components';
|
|
import { Data } from '../../../../data/data';
|
|
import { MessageModelType } from '../../../../models/messageType';
|
|
import { getConversationController } from '../../../../session/conversations';
|
|
import { messagesExpired, PropsForExpiringMessage } from '../../../../state/ducks/conversations';
|
|
import { getIncrement } from '../../../../util/timer';
|
|
import { ExpireTimer } from '../../ExpireTimer';
|
|
import { ReadableMessage, ReadableMessageProps } from './ReadableMessage';
|
|
|
|
const EXPIRATION_CHECK_MINIMUM = 2000;
|
|
|
|
function useIsExpired(props: PropsForExpiringMessage) {
|
|
const {
|
|
convoId,
|
|
messageId,
|
|
expirationLength,
|
|
expirationTimestamp,
|
|
isExpired: isExpiredProps,
|
|
} = props;
|
|
|
|
const dispatch = useDispatch();
|
|
|
|
const [isExpired] = useState(isExpiredProps);
|
|
|
|
const checkExpired = useCallback(async () => {
|
|
const now = Date.now();
|
|
|
|
if (!expirationTimestamp || !expirationLength) {
|
|
return;
|
|
}
|
|
|
|
if (isExpired || now >= expirationTimestamp) {
|
|
await Data.removeMessage(messageId);
|
|
if (convoId) {
|
|
dispatch(
|
|
messagesExpired([
|
|
{
|
|
conversationKey: convoId,
|
|
messageId,
|
|
},
|
|
])
|
|
);
|
|
const convo = getConversationController().get(convoId);
|
|
convo?.updateLastMessage();
|
|
}
|
|
}
|
|
}, [expirationTimestamp, expirationLength, isExpired, messageId, convoId]);
|
|
|
|
let checkFrequency: number | null = null;
|
|
if (expirationLength) {
|
|
const increment = getIncrement(expirationLength || EXPIRATION_CHECK_MINIMUM);
|
|
checkFrequency = Math.max(EXPIRATION_CHECK_MINIMUM, increment);
|
|
}
|
|
|
|
useEffect(() => {
|
|
void checkExpired();
|
|
}, []); // check on mount
|
|
|
|
useInterval(checkExpired, checkFrequency); // check every 2sec or sooner if needed
|
|
|
|
return { isExpired };
|
|
}
|
|
|
|
const StyledReadableMessage = styled(ReadableMessage)<{ isIncoming: boolean }>`
|
|
display: flex;
|
|
justify-content: ${props => (props.isIncoming ? 'flex-start' : 'flex-end')};
|
|
align-items: center;
|
|
width: 100%;
|
|
`;
|
|
|
|
export interface ExpirableReadableMessageProps
|
|
extends ReadableMessageProps,
|
|
PropsForExpiringMessage {
|
|
direction: MessageModelType;
|
|
}
|
|
|
|
export const ExpirableReadableMessage = (props: ExpirableReadableMessageProps) => {
|
|
const {
|
|
convoId,
|
|
messageId,
|
|
direction,
|
|
receivedAt,
|
|
isUnread,
|
|
expirationLength,
|
|
expirationTimestamp,
|
|
} = props;
|
|
|
|
const expiringProps: PropsForExpiringMessage = {
|
|
convoId,
|
|
messageId,
|
|
expirationLength,
|
|
expirationTimestamp,
|
|
isExpired: props.isExpired,
|
|
direction,
|
|
};
|
|
const { isExpired } = useIsExpired(expiringProps);
|
|
const isIncoming = direction === 'incoming';
|
|
|
|
if (isExpired) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<StyledReadableMessage
|
|
messageId={messageId}
|
|
receivedAt={receivedAt}
|
|
isUnread={!!isUnread}
|
|
isIncoming={isIncoming}
|
|
key={`readable-message-${messageId}`}
|
|
>
|
|
{expirationLength && expirationTimestamp && (
|
|
<ExpireTimer
|
|
isCorrectSide={!isIncoming}
|
|
expirationLength={expirationLength}
|
|
expirationTimestamp={expirationTimestamp}
|
|
/>
|
|
)}
|
|
{props.children}
|
|
{expirationLength && expirationTimestamp && (
|
|
<ExpireTimer
|
|
isCorrectSide={isIncoming}
|
|
expirationLength={expirationLength}
|
|
expirationTimestamp={expirationTimestamp}
|
|
/>
|
|
)}
|
|
</StyledReadableMessage>
|
|
);
|
|
};
|