Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ops: sync staging to dev #3746

Merged
merged 13 commits into from
Jul 15, 2024
Merged
4 changes: 0 additions & 4 deletions apps/tlon-web/src/chat/ChatInput/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ import {
} from '@/state/chat';
import { useGroupFlag } from '@/state/groups';
import { useFileStore, useUploader } from '@/state/storage';
import { useUnreadsStore } from '@/state/unreads';

interface ChatInputProps {
whom: string;
Expand Down Expand Up @@ -392,9 +391,6 @@ export default function ChatInput({
onUpdate.current.flush();
setDraft(inlinesToJSON(['']));
setTimeout(() => {
const key = replying ? getThreadKey(whom, replying) : getKey(whom);
useUnreadsStore.getState().read(key);
useUnreadsStore.getState().bump(key);
clearAttachments();
}, 0);
},
Expand Down
89 changes: 40 additions & 49 deletions apps/tlon-web/src/chat/ChatMessage/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import { Editor } from '@tiptap/react';
import {
ActivitySummary,
getChannelSource,
getDmSource,
getKey,
getThreadKey,
} from '@tloncorp/shared/dist/urbit/activity';
Expand All @@ -12,7 +14,7 @@ import {
constructStory,
} from '@tloncorp/shared/dist/urbit/channel';
import { daToUnix } from '@urbit/api';
import { formatUd, unixToDa } from '@urbit/aura';
import { formatUd } from '@urbit/aura';
import { BigInteger } from 'big-integer';
import bigInt from 'big-integer';
import cn from 'classnames';
Expand Down Expand Up @@ -43,12 +45,14 @@ import { useMarkChannelRead } from '@/logic/channel';
import { JSONToInlines, diaryMixedToJSON } from '@/logic/tiptap';
import useLongPress from '@/logic/useLongPress';
import { useIsMobile } from '@/logic/useMedia';
import { useStickyUnread } from '@/logic/useStickyUnread';
import {
useIsDmOrMultiDm,
whomIsDm,
whomIsFlag,
whomIsMultiDm,
} from '@/logic/utils';
import { useSourceActivity, useThreadActivity } from '@/state/activity';
import {
useEditPostMutation,
useIsEdited,
Expand All @@ -60,7 +64,7 @@ import {
useMessageToggler,
useTrackedMessageStatus,
} from '@/state/chat';
import { Unread, useUnread, useUnreadsStore } from '@/state/unreads';
import { useRouteGroup } from '@/state/groups';

import ReactionDetails from '../ChatReactions/ReactionDetails';
import {
Expand All @@ -87,11 +91,11 @@ export interface ChatMessageProps {
}

function getUnreadDisplay(
unread: Unread | undefined,
unread: ActivitySummary,
id: string,
thread: Unread | undefined
thread: ActivitySummary
): 'none' | 'top' | 'thread' | 'top-with-thread' {
const isTop = unread?.lastUnread?.id === id && unread.status !== 'read';
const isTop = unread.unread?.id === id;

// if this message is the oldest unread in the main chat,
// and has an unread thread, show the divider and thread indicator
Expand All @@ -101,7 +105,7 @@ function getUnreadDisplay(

// if we have a thread, only mark it as explicitly unread
// if it's not nested under main chat unreads
if (thread && thread.status !== 'read') {
if (thread && thread.count > 0) {
return 'thread';
}

Expand Down Expand Up @@ -166,6 +170,7 @@ const ChatMessage = React.memo<
idShip: string;
idTime: string;
}>();
const groupFlag = useRouteGroup();
const isThread = !!idShip && !!idTime;
const threadOpId = isThread ? `${idShip}/${idTime}` : '';
const isThreadOp = threadOpId === seal.id && hideReplies;
Expand All @@ -176,20 +181,28 @@ const ChatMessage = React.memo<
const unreadId = !isChannel ? seal.id : formatUd(bigInt(seal.id));
const chatInfo = useChatInfo(whom);
const unreadsKey = getKey(whom);
const unread = useUnread(unreadsKey);
const threadUr = useUnread(getThreadKey(whom, unreadId));
const { activity: summary } = useSourceActivity(unreadsKey);
const unread = useStickyUnread(summary);
const nest = `chat/${whom}`;
const source = isChannel
? getChannelSource(groupFlag, nest)
: getDmSource(whom);
const { activity: threadSum } = useThreadActivity(
source,
getThreadKey(whom, unreadId)
);
const unreadDisplay = useMemo(
() =>
getUnreadDisplay(
unread,
!isChannel ? unreadId : `${essay.author}/${unreadId}`,
threadUr
threadSum
),
[unread, threadUr, unreadId]
[unread, threadSum, unreadId]
);
const topUnread =
unreadDisplay === 'top' || unreadDisplay === 'top-with-thread';
const threadNotify = threadUr?.notify;
const threadNotify = threadSum.notify;
const threadUnread =
unreadDisplay === 'thread' ||
unreadDisplay === 'top-with-thread' ||
Expand All @@ -211,41 +224,18 @@ const ChatMessage = React.memo<
});

useEffect(() => {
if (!inView || !unread) {
const mainUnread =
unreadDisplay === 'top' || unreadDisplay === 'top-with-thread';
if (!inView || !mainUnread) {
return;
}

const unseen = unread.status === 'unread';
const { seen: markSeen, delayedRead } = useUnreadsStore.getState();
/* once the unseen marker comes into view we need to mark it
as seen and start a timer to mark it read so it goes away.
we ensure that the brief matches and hasn't changed before
doing so. we don't want to accidentally clear unreads when
the state has changed
*/
if (
inView &&
(unreadDisplay === 'top' || unreadDisplay === 'top-with-thread') &&
unseen
) {
markSeen(unreadsKey);
delayedRead(unreadsKey, () => {
if (isDMOrMultiDM) {
markDmRead();
} else {
markReadChannel();
}
});
if (isDMOrMultiDM) {
markDmRead();
} else {
markReadChannel();
}
}, [
inView,
unread,
unreadsKey,
unreadDisplay,
isDMOrMultiDM,
markReadChannel,
markDmRead,
]);
}, [inView, unreadDisplay, isDMOrMultiDM, markReadChannel, markDmRead]);

const cacheId = {
author: window.our,
Expand Down Expand Up @@ -420,8 +410,12 @@ const ChatMessage = React.memo<
id="chat-message-target"
{...handlers}
>
{unread && topUnread ? (
<DateDivider date={unix} unreadCount={unread.count} ref={viewRef} />
{unread.unread && topUnread ? (
<DateDivider
date={unix}
unreadCount={unread.unread.count}
ref={viewRef}
/>
) : null}
{newDay && unreadDisplay === 'none' ? (
<DateDivider date={unix} />
Expand Down Expand Up @@ -542,10 +536,7 @@ const ChatMessage = React.memo<

<span
className={cn(
threadUnread &&
threadUr?.status !== 'unread' &&
'mr-2',
threadUnread && threadUr?.status === 'unread'
threadUnread
? threadNotify
? 'text-blue'
: ''
Expand All @@ -554,7 +545,7 @@ const ChatMessage = React.memo<
>
{replyCount} {replyCount > 1 ? 'replies' : 'reply'}{' '}
</span>
{threadUnread && threadUr?.status === 'unread' ? (
{threadUnread ? (
<UnreadIndicator
count={0}
notify={threadNotify}
Expand Down
27 changes: 9 additions & 18 deletions apps/tlon-web/src/chat/ChatMessage/DeletedChatMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable react/no-unused-prop-types */
import { getKey } from '@tloncorp/shared/dist/urbit/activity';
import { daToUnix } from '@urbit/api';
import { formatUd } from '@urbit/aura';
import { BigInteger } from 'big-integer';
import cn from 'classnames';
import { format } from 'date-fns';
Expand All @@ -10,7 +9,8 @@ import { useInView } from 'react-intersection-observer';

import DateDivider from '@/chat/ChatMessage/DateDivider';
import { useMarkChannelRead } from '@/logic/channel';
import { useUnread, useUnreadsStore } from '@/state/unreads';
import { useStickyUnread } from '@/logic/useStickyUnread';
import { useSourceActivity } from '@/state/activity';

export interface DeletedChatMessageProps {
whom: string;
Expand Down Expand Up @@ -52,9 +52,11 @@ const DeletedChatMessage = React.memo<
const container = useRef<HTMLDivElement>(null);
const unix = new Date(daToUnix(time));
const unreadsKey = getKey(whom);
const unread = useUnread(unreadsKey);
const { activity } = useSourceActivity(unreadsKey);
const summary = useStickyUnread(activity);
const { unread } = summary;
const isUnread = useMemo(
() => unread && unread.lastUnread?.time === time.toString(),
() => unread && unread.time === time.toString(),
[unread, time]
);
const { markRead: markReadChannel } = useMarkChannelRead(`chat/${whom}`);
Expand All @@ -64,23 +66,12 @@ const DeletedChatMessage = React.memo<
});

useEffect(() => {
if (!inView || !unread) {
if (!inView || !isUnread) {
return;
}

const unseen = unread.status === 'unread';
const { seen: markSeen, delayedRead } = useUnreadsStore.getState();
/* once the unseen marker comes into view we need to mark it
as seen and start a timer to mark it read so it goes away.
we ensure that the brief matches and hasn't changed before
doing so. we don't want to accidentally clear unreads when
the state has changed
*/
if (inView && isUnread && unseen) {
markSeen(unreadsKey);
delayedRead(unreadsKey, markReadChannel);
}
}, [inView, unread, unreadsKey, isUnread, markReadChannel]);
markReadChannel();
}, [inView, isUnread, markReadChannel]);

return (
<div
Expand Down
33 changes: 4 additions & 29 deletions apps/tlon-web/src/chat/ChatThread/ChatThread.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getThreadKey } from '@tloncorp/shared/dist/urbit/activity';
import { ReplyTuple } from '@tloncorp/shared/dist/urbit/channel';
import { formatUd, unixToDa } from '@urbit/aura';
import { formatUd } from '@urbit/aura';
import bigInt from 'big-integer';
import cn from 'classnames';
import _ from 'lodash';
Expand All @@ -22,11 +21,7 @@ import EllipsisIcon from '@/components/icons/EllipsisIcon';
import X16Icon from '@/components/icons/X16Icon';
import keyMap from '@/keyMap';
import { useDragAndDrop } from '@/logic/DragAndDropContext';
import {
useChannelCompatibility,
useChannelFlag,
useMarkChannelRead,
} from '@/logic/channel';
import { useChannelCompatibility, useChannelFlag } from '@/logic/channel';
import { useBottomPadding } from '@/logic/position';
import { useIsScrolling } from '@/logic/scroll';
import { firstInlineSummary } from '@/logic/tiptap';
Expand All @@ -44,10 +39,9 @@ import {
useRouteGroup,
useVessel,
} from '@/state/groups/groups';
import { unreadStoreLogger, useUnread, useUnreadsStore } from '@/state/unreads';

import ChatScrollerPlaceholder from '../ChatScroller/ChatScrollerPlaceholder';
import { chatStoreLogger, useChatStore } from '../useChatStore';
import { useChatStore } from '../useChatStore';

export default function ChatThread() {
const { name, chShip, ship, chName, idTime } = useParams<{
Expand Down Expand Up @@ -87,8 +81,6 @@ export default function ChatThread() {
}),
[id, idTime]
);
const chatUnreadsKey = getThreadKey(flag, time);
const { markRead } = useMarkChannelRead(nest, msgKey);
const replies = note?.seal.replies || null;
const idTimeIsNumber = !Number.isNaN(Number(idTime));
if (note && replies !== null && idTimeIsNumber) {
Expand Down Expand Up @@ -132,8 +124,6 @@ export default function ChatThread() {
_.intersection(perms.writers, vessel.sects).length !== 0;
const { compatible, text } = useChannelCompatibility(`chat/${flag}`);
const { paddingBottom } = useBottomPadding();
const readTimeout = useUnread(chatUnreadsKey)?.readTimeout;
const path = location.pathname;
const activeTab = useActiveTab();

const returnURL = useCallback(
Expand All @@ -154,10 +144,8 @@ export default function ChatThread() {

const onAtBottom = useCallback(() => {
const { bottom } = useChatStore.getState();
const { delayedRead } = useUnreadsStore.getState();
bottom(true);
delayedRead(chatUnreadsKey, markRead);
}, [chatUnreadsKey, markRead]);
}, []);

const onEscape = useCallback(
(e: KeyboardEvent) => {
Expand All @@ -169,19 +157,6 @@ export default function ChatThread() {
);
useEventListener('keydown', onEscape, threadRef);

// read the messages once navigated away
useEffect(() => {
return () => {
const winPath = window.location.pathname.replace('/apps/groups', '');
if (winPath !== path && readTimeout) {
unreadStoreLogger.log(winPath, path);
unreadStoreLogger.log('marking read from dismount', chatUnreadsKey);
useUnreadsStore.getState().read(chatUnreadsKey);
markRead();
}
};
}, [path, readTimeout, chatUnreadsKey, markRead]);

useEffect(() => {
if (!idTimeIsNumber) {
navigate(returnURLWithoutMsg());
Expand Down
Loading