diff --git a/js/expiring_messages.js b/js/expiring_messages.js index 365c03fc5..fd4e5e881 100644 --- a/js/expiring_messages.js +++ b/js/expiring_messages.js @@ -34,11 +34,10 @@ Message: Whisper.Message, }); - Whisper.events.trigger( - 'messageExpired', - message.id, - message.conversationId - ); + Whisper.events.trigger('messageExpired', { + conversationKey: message.attributes.conversationId, + messageId: message.id, + }); const conversation = message.getConversation(); if (conversation) { diff --git a/ts/components/conversation/ExpireTimer.tsx b/ts/components/conversation/ExpireTimer.tsx index 929f386c9..43f18016a 100644 --- a/ts/components/conversation/ExpireTimer.tsx +++ b/ts/components/conversation/ExpireTimer.tsx @@ -1,80 +1,59 @@ -import React from 'react'; +import React, { useState } from 'react'; import classNames from 'classnames'; import { getIncrement, getTimerBucket } from '../../util/timer'; +import { useInterval } from '../../hooks/useInterval'; -interface Props { +type Props = { withImageNoCaption: boolean; expirationLength: number; expirationTimestamp: number; direction: 'incoming' | 'outgoing'; -} - -export class ExpireTimer extends React.Component { - private interval: any; - - constructor(props: Props) { - super(props); - - this.interval = null; - } - - public componentDidMount() { - const { expirationLength } = this.props; - const increment = getIncrement(expirationLength); - const updateFrequency = Math.max(increment, 500); - - const update = () => { - this.setState({ - lastUpdated: Date.now(), - }); - }; - this.interval = setInterval(update, updateFrequency); - } - - public componentWillUnmount() { - if (this.interval) { - clearInterval(this.interval); - } - } - - public render() { - const { - direction, - expirationLength, - expirationTimestamp, - withImageNoCaption, - } = this.props; - - const bucket = getTimerBucket(expirationTimestamp, expirationLength); - let timeLeft = Math.round((expirationTimestamp - Date.now()) / 1000); - timeLeft = timeLeft >= 0 ? timeLeft : 0; - if (timeLeft <= 60) { - return ( - - {timeLeft} - - ); - } - +}; + +export const ExpireTimer = (props: Props) => { + const [lastUpdated, setLastUpdated] = useState(Date.now()); + const update = () => { + setLastUpdated(Date.now()); + }; + const { + direction, + expirationLength, + expirationTimestamp, + withImageNoCaption, + } = props; + + const increment = getIncrement(expirationLength); + const updateFrequency = Math.max(increment, 500); + + useInterval(update, updateFrequency); + + const bucket = getTimerBucket(expirationTimestamp, expirationLength); + let timeLeft = Math.round((expirationTimestamp - Date.now()) / 1000); + timeLeft = timeLeft >= 0 ? timeLeft : 0; + if (timeLeft <= 60) { return ( -
+ > + {timeLeft} + ); } -} + + return ( +
+ ); +}; diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 160d8b668..0c1298131 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -189,8 +189,8 @@ export type RemoveAllConversationsActionType = { export type MessageExpiredActionType = { type: 'MESSAGE_EXPIRED'; payload: { - id: string; - conversationId: string; + messageId: string; + conversationKey: string; }; }; export type MessageChangedActionType = { @@ -294,15 +294,18 @@ function removeAllConversations(): RemoveAllConversationsActionType { }; } -function messageExpired( - id: string, - conversationId: string -): MessageExpiredActionType { +function messageExpired({ + conversationKey, + messageId, +}: { + conversationKey: string; + messageId: string; +}): MessageExpiredActionType { return { type: 'MESSAGE_EXPIRED', payload: { - id, - conversationId, + conversationKey, + messageId, }, }; } @@ -445,9 +448,7 @@ export function reducer( if (action.type === 'CONVERSATIONS_REMOVE_ALL') { return getEmptyState(); } - if (action.type === 'MESSAGE_EXPIRED') { - // nothing to do here - } + if (action.type === 'SELECTED_CONVERSATION_CHANGED') { const { payload } = action; const { id } = payload; @@ -527,8 +528,7 @@ export function reducer( } return state; } - - if (action.type === 'MESSAGE_DELETED') { + if (action.type === 'MESSAGE_EXPIRED' || action.type === 'MESSAGE_DELETED') { const { conversationKey, messageId } = action.payload; if (conversationKey === state.selectedConversation) { // search if we find this message id. diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index 357ff03fd..bbeab1888 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -391,11 +391,11 @@ export function reducer( } const { payload } = action; - const { id } = payload; + const { messageId } = payload; return { ...state, - messages: reject(messages, message => id === message.id), + messages: reject(messages, message => messageId === message.id), messageLookup: omit(messageLookup, ['id']), }; } diff --git a/ts/util/timer.ts b/ts/util/timer.ts index 3783ef5a4..fe14ebfe8 100644 --- a/ts/util/timer.ts +++ b/ts/util/timer.ts @@ -4,6 +4,10 @@ export function getIncrement(length: number): number { if (length < 0) { return 1000; } + // if less than one minute, default to 500 ms so that UI counter is accurate + if (length <= 60000) { + return 500; + } return Math.ceil(length / 12); }