Skip to content

Commit

Permalink
Revert "[lib] Introduce MessageSpec.getLastUpdatedTime"
Browse files Browse the repository at this point in the history
This reverts commit 642c7eb.
  • Loading branch information
Ashoat committed Dec 10, 2024
1 parent d5b919b commit d0de5a7
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 128 deletions.
25 changes: 20 additions & 5 deletions lib/hooks/sidebar-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,32 @@
import _orderBy from 'lodash/fp/orderBy.js';
import * as React from 'react';

import { useGetLastUpdatedTimes } from './thread-time.js';
import { childThreadInfos } from '../selectors/thread-selectors.js';
import { getMostRecentNonLocalMessageID } from '../shared/message-utils.js';
import { threadInChatList } from '../shared/thread-utils.js';
import type { MessageStore, RawMessageInfo } from '../types/message-types.js';
import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
import { threadTypeIsSidebar } from '../types/thread-types-enum.js';
import type { SidebarInfo } from '../types/thread-types.js';
import { useSelector } from '../utils/redux-utils.js';

function getMostRecentRawMessageInfo(
threadInfo: ThreadInfo,
messageStore: MessageStore,
): ?RawMessageInfo {
const thread = messageStore.threads[threadInfo.id];
if (!thread) {
return null;
}
for (const messageID of thread.messageIDs) {
return messageStore.messages[messageID];
}
return null;
}

function useSidebarInfos(): { +[id: string]: $ReadOnlyArray<SidebarInfo> } {
const childThreadInfoByParentID = useSelector(childThreadInfos);
const messageStore = useSelector(state => state.messageStore);
const getLastUpdatedTimes = useGetLastUpdatedTimes();

return React.useMemo(() => {
const result: { [id: string]: $ReadOnlyArray<SidebarInfo> } = {};
Expand All @@ -28,11 +42,12 @@ function useSidebarInfos(): { +[id: string]: $ReadOnlyArray<SidebarInfo> } {
) {
continue;
}
const { lastUpdatedAtLeastTime: lastUpdatedTime } = getLastUpdatedTimes(
const mostRecentRawMessageInfo = getMostRecentRawMessageInfo(
childThreadInfo,
messageStore,
messageStore.messages,
);
const lastUpdatedTime =
mostRecentRawMessageInfo?.time ?? childThreadInfo.creationTime;
const mostRecentNonLocalMessage = getMostRecentNonLocalMessageID(
childThreadInfo.id,
messageStore,
Expand All @@ -46,7 +61,7 @@ function useSidebarInfos(): { +[id: string]: $ReadOnlyArray<SidebarInfo> } {
result[parentID] = _orderBy('lastUpdatedTime')('desc')(sidebarInfos);
}
return result;
}, [childThreadInfoByParentID, messageStore, getLastUpdatedTimes]);
}, [childThreadInfoByParentID, messageStore]);
}

export { useSidebarInfos };
116 changes: 17 additions & 99 deletions lib/hooks/thread-time.js
Original file line number Diff line number Diff line change
@@ -1,107 +1,25 @@
// @flow

import * as React from 'react';

import { useGetLatestMessageEdit } from './latest-message-edit.js';
import { messageSpecs } from '../shared/messages/message-specs.js';
import type {
MessageInfo,
RawMessageInfo,
MessageStore,
} from '../types/message-types.js';
import type { MessageInfo, MessageStore } from '../types/message-types.js';
import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js';
import type { LastUpdatedTimes } from '../types/thread-types.js';
import { useSelector } from '../utils/redux-utils.js';

function useGetLastUpdatedTimes(): (
function getLastUpdatedTime(
threadInfo: ThreadInfo,
messageStore: MessageStore,
messages: { +[id: string]: ?MessageInfo | RawMessageInfo },
) => LastUpdatedTimes {
const viewerID = useSelector(state => state.currentUserInfo?.id);
const fetchMessage = useGetLatestMessageEdit();
return React.useCallback(
(threadInfo, messageStore, messages) => {
// This callback returns two variables:
// - lastUpdatedTime: this is a Promise that resolves with the final value
// - lastUpdatedAtLeastTime: this is a number that represents what we
// should use while we're waiting for lastUpdatedTime to resolve. It's
// set based on the most recent message whose spec returns a non-Promise
// when getLastUpdatedTime is called
let lastUpdatedAtLeastTime = threadInfo.creationTime;

const thread = messageStore.threads[threadInfo.id];
if (!thread || !viewerID) {
return {
lastUpdatedAtLeastTime,
lastUpdatedTime: Promise.resolve(lastUpdatedAtLeastTime),
};
}

const getLastUpdatedTimeParams = {
threadInfo,
viewerID,
fetchMessage,
};

let lastUpdatedTime: ?Promise<?number>;
for (const messageID of thread.messageIDs) {
const messageInfo = messages[messageID];
if (!messageInfo) {
continue;
}

// We call getLastUpdatedTime on the message spec. It can return either
// ?number or Promise<?number>. If the message spec doesn't implement
// getLastUpdatedTime, then we default to messageInfo.time.
const { getLastUpdatedTime } = messageSpecs[messageInfo.type];
const lastUpdatedTimePromisable = getLastUpdatedTime
? getLastUpdatedTime(messageInfo, getLastUpdatedTimeParams)
: messageInfo.time;

// We rely on the fact that thread.messageIDs is ordered chronologically
// (newest first) to chain together lastUpdatedTime. An older message's
// lastUpdatedTime is only considered if all of the newer messages
// return falsey.
lastUpdatedTime = (async () => {
if (lastUpdatedTime) {
const earlierChecks = await lastUpdatedTime;
if (earlierChecks) {
return earlierChecks;
}
}
return await lastUpdatedTimePromisable;
})();

if (typeof lastUpdatedTimePromisable === 'number') {
// We break from the loop the first time this condition is met.
// There's no need to consider any older messages, since both
// lastUpdated and lastUpdatedAtLeastTime will be this value (or
// higher, in the case of lastUpdated). That is also why this loop
// only sets lastUpdatedAtLeastTime once: once we get to this
// "baseline" case, there's no need to consider any more messages.
lastUpdatedAtLeastTime = lastUpdatedTimePromisable;
break;
}
}

const lastUpdatedWithFallback = (async () => {
if (lastUpdatedTime) {
const earlierChecks = await lastUpdatedTime;
if (earlierChecks) {
return earlierChecks;
}
}
return lastUpdatedAtLeastTime;
})();

return {
lastUpdatedAtLeastTime,
lastUpdatedTime: lastUpdatedWithFallback,
};
},
[viewerID, fetchMessage],
);
messages: { +[id: string]: ?MessageInfo },
): number {
const thread = messageStore.threads[threadInfo.id];
if (!thread) {
return threadInfo.creationTime;
}
for (const messageID of thread.messageIDs) {
const messageInfo = messages[messageID];
if (!messageInfo) {
continue;
}
return messageInfo.time;
}
return threadInfo.creationTime;
}

export { useGetLastUpdatedTimes };
export { getLastUpdatedTime };
8 changes: 3 additions & 5 deletions lib/selectors/chat-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
threadInfoSelector,
} from './thread-selectors.js';
import { useSidebarInfos } from '../hooks/sidebar-hooks.js';
import { useGetLastUpdatedTimes } from '../hooks/thread-time.js';
import { getLastUpdatedTime } from '../hooks/thread-time.js';
import {
createMessageInfo,
getMostRecentNonLocalMessageID,
Expand Down Expand Up @@ -97,15 +97,13 @@ function useCreateChatThreadItem(): ThreadInfo => ChatThreadItem {
const messageInfos = useSelector(messageInfoSelector);
const sidebarInfos = useSidebarInfos();
const messageStore = useSelector(state => state.messageStore);
const getLastUpdatedTimes = useGetLastUpdatedTimes();
return React.useCallback(
threadInfo => {
const mostRecentNonLocalMessage = getMostRecentNonLocalMessageID(
threadInfo.id,
messageStore,
);

const { lastUpdatedAtLeastTime: lastUpdatedTime } = getLastUpdatedTimes(
const lastUpdatedTime = getLastUpdatedTime(
threadInfo,
messageStore,
messageInfos,
Expand Down Expand Up @@ -172,7 +170,7 @@ function useCreateChatThreadItem(): ThreadInfo => ChatThreadItem {
sidebars: sidebarItems,
};
},
[messageInfos, messageStore, sidebarInfos, getLastUpdatedTimes],
[messageInfos, messageStore, sidebarInfos],
);
}

Expand Down
4 changes: 0 additions & 4 deletions lib/shared/messages/message-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,4 @@ export type MessageSpec<Data, RawInfo, Info> = {
messageInfo: Info,
params: ShowInMessagePreviewParams,
) => Promise<boolean>,
+getLastUpdatedTime?: (
messageInfoOrRawMessageInfo: Info | RawInfo,
params: ShowInMessagePreviewParams,
) => ?number | Promise<?number>,
};
8 changes: 0 additions & 8 deletions lib/shared/messages/multimedia-message-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,6 @@ export const multimediaMessageSpec: MultimediaMessageSpec = Object.freeze({

showInMessagePreview: (messageInfo: MediaMessageInfo | ImagesMessageInfo) =>
Promise.resolve(messageInfo.media.length > 0),

getLastUpdatedTime: (
messageInfo:
| MediaMessageInfo
| ImagesMessageInfo
| RawMediaMessageInfo
| RawImagesMessageInfo,
) => (messageInfo.media.length > 0 ? messageInfo.time : null),
});

// Four photos were uploaded before dimensions were calculated server-side,
Expand Down
7 changes: 0 additions & 7 deletions lib/types/thread-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -436,13 +436,6 @@ export type ThreadFetchMediaRequest = {
+offset: number,
};

export type LastUpdatedTimes = {
// The last updated time is at least this number, but possibly higher
// We won't know for sure until the below Promise resolves
+lastUpdatedAtLeastTime: number,
+lastUpdatedTime: Promise<number>,
};

export type SidebarInfo = {
+threadInfo: ThreadInfo,
+lastUpdatedTime: number,
Expand Down

0 comments on commit d0de5a7

Please sign in to comment.