Skip to content

Commit

Permalink
Merge pull request #3771 from tloncorp/hm/better-auto-reads
Browse files Browse the repository at this point in the history
activity: don't mark read if tab not focused and automatically mark read at chat bottom
  • Loading branch information
arthyn authored Jul 19, 2024
2 parents f4b09aa + 2f60d1e commit b25b9ec
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 22 deletions.
17 changes: 17 additions & 0 deletions apps/tlon-web/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,23 @@ function RoutedApp() {
const theme = useTheme();
const isDarkMode = useIsDark();

useEffect(() => {
const onFocus = () => {
useLocalState.setState({ inFocus: true });
};
window.addEventListener('focus', onFocus);

const onBlur = () => {
useLocalState.setState({ inFocus: false });
};
window.addEventListener('blur', onBlur);

return () => {
window.removeEventListener('focus', onFocus);
window.removeEventListener('blur', onBlur);
};
}, []);

useEffect(() => {
window.toggleDevTools = () => toggleDevTools();
}, []);
Expand Down
13 changes: 11 additions & 2 deletions apps/tlon-web/src/chat/ChatMessage/ChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import {
useTrackedMessageStatus,
} from '@/state/chat';
import { useRouteGroup } from '@/state/groups';
import { useInFocus } from '@/state/local';

import ReactionDetails from '../ChatReactions/ReactionDetails';
import {
Expand Down Expand Up @@ -219,14 +220,15 @@ const ChatMessage = React.memo<
[isMessageHidden, isPostHidden]
);

const inFocus = useInFocus();
const { ref: viewRef, inView } = useInView({
threshold: 1,
});

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

Expand All @@ -235,7 +237,14 @@ const ChatMessage = React.memo<
} else {
markReadChannel();
}
}, [inView, unreadDisplay, isDMOrMultiDM, markReadChannel, markDmRead]);
}, [
inFocus,
inView,
unreadDisplay,
isDMOrMultiDM,
markReadChannel,
markDmRead,
]);

const cacheId = {
author: window.our,
Expand Down
6 changes: 4 additions & 2 deletions apps/tlon-web/src/chat/ChatMessage/DeletedChatMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import DateDivider from '@/chat/ChatMessage/DateDivider';
import { useMarkChannelRead } from '@/logic/channel';
import { useStickyUnread } from '@/logic/useStickyUnread';
import { useSourceActivity } from '@/state/activity';
import { useInFocus } from '@/state/local';

export interface DeletedChatMessageProps {
whom: string;
Expand Down Expand Up @@ -61,17 +62,18 @@ const DeletedChatMessage = React.memo<
);
const { markRead: markReadChannel } = useMarkChannelRead(`chat/${whom}`);

const inFocus = useInFocus();
const { ref: viewRef, inView } = useInView({
threshold: 1,
});

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

markReadChannel();
}, [inView, isUnread, markReadChannel]);
}, [inFocus, inView, isUnread, markReadChannel]);

return (
<div
Expand Down
2 changes: 1 addition & 1 deletion apps/tlon-web/src/chat/ChatScroller/ChatScroller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ export default function ChatScroller({
if (isAtTop && !hasLoadedOldest) {
logger.log('triggering onAtTop');
onAtTop?.();
} else if (isAtBottom && !hasLoadedNewest) {
} else if (isAtBottom) {
logger.log('triggering onAtBottom');
onAtBottom?.();
}
Expand Down
14 changes: 12 additions & 2 deletions apps/tlon-web/src/replies/ReplyMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
useTrackedMessageStatus,
} from '@/state/chat';
import { useRouteGroup } from '@/state/groups';
import { useInFocus } from '@/state/local';

import ReplyMessageOptions from './ReplyMessageOptions';
import ReplyReactions from './ReplyReactions/ReplyReactions';
Expand Down Expand Up @@ -160,13 +161,14 @@ const ReplyMessage = React.memo<
() => isMessageHidden || isPostHidden,
[isMessageHidden, isPostHidden]
);
const inFocus = useInFocus();
const { ref: viewRef, inView } = useInView({
threshold: 1,
});

useEffect(() => {
// if no tracked unread we don't need to take any action
if (!inView || !isUnread) {
if (!inFocus || !inView || !isUnread) {
return;
}

Expand All @@ -175,7 +177,15 @@ const ReplyMessage = React.memo<
} else {
markChannelRead();
}
}, [whom, inView, isUnread, isDMOrMultiDM, markChannelRead, markDmRead]);
}, [
whom,
inFocus,
inView,
isUnread,
isDMOrMultiDM,
markChannelRead,
markDmRead,
]);

const msgStatus = useTrackedMessageStatus({
author: window.our,
Expand Down
44 changes: 29 additions & 15 deletions apps/tlon-web/src/state/activity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useInfiniteQuery, useMutation } from '@tanstack/react-query';
import {
Activity,
ActivityAction,
ActivityBundle,
ActivityDeleteUpdate,
ActivityFeed,
ActivityReadUpdate,
Expand All @@ -16,17 +15,20 @@ import {
Source,
VolumeMap,
VolumeSettings,
getKey,
sourceToString,
stripSourcePrefix,
} from '@tloncorp/shared/dist/urbit/activity';
import _ from 'lodash';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import api from '@/api';
import { useChatStore } from '@/chat/useChatStore';
import useReactQueryScry from '@/logic/useReactQueryScry';
import { createDevLogger } from '@/logic/utils';
import queryClient from '@/queryClient';

import { useLocalState } from './local';
import { SidebarFilter } from './settings';

const actLogger = createDevLogger('activity', false);
Expand Down Expand Up @@ -128,17 +130,41 @@ function activityVolumeUpdates(events: ActivityVolumeUpdate[]) {
}, {} as VolumeSettings);
}

function optimisticActivityUpdate(d: Activity, source: string): Activity {
const old = d[source];
return {
...d,
[source]: {
...old,
unread: null,
count: Math.min(0, old.count - (old.unread?.count || 0)),
'notify-count':
old.unread && old.unread.notify
? Math.min(old['notify-count'] - old.unread.count)
: old['notify-count'],
},
};
}

function updateActivity({
main,
threads,
}: {
main: Activity;
threads: Record<string, Activity>;
}) {
const { current, atBottom } = useChatStore.getState();
const source = getKey(current);
const inFocus = useLocalState.getState().inFocus;
const filteredMain =
inFocus && atBottom && source in main
? optimisticActivityUpdate(main, source)
: main;
console.log({ inFocus, source, atBottom, filteredMain });
queryClient.setQueryData(unreadsKey(), (d: Activity | undefined) => {
return {
...d,
...main,
...filteredMain,
};
});

Expand Down Expand Up @@ -304,19 +330,7 @@ export function useMarkReadMutation(recursive = false) {
};
}

const old = d[source];
return {
...d,
[source]: {
...old,
unread: null,
count: Math.min(0, old.count - (old.unread?.count || 0)),
'notify-count':
old.unread && old.unread.notify
? Math.min(old['notify-count'] - old.unread.count)
: old['notify-count'],
},
};
return optimisticActivityUpdate(d, source);
});

return { current };
Expand Down
7 changes: 7 additions & 0 deletions apps/tlon-web/src/state/local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ interface LocalState {
errorCount: number;
airLockErrorCount: number;
lastReconnect: number;
inFocus: boolean;
onReconnect: (() => void) | null;
logs: string[];
log: (msg: string) => void;
Expand All @@ -44,6 +45,7 @@ export const useLocalState = create<LocalState>(
lastReconnect: Date.now(),
onReconnect: null,
logs: [],
inFocus: true,
log: (msg: string) => {
set(
produce((s) => {
Expand Down Expand Up @@ -107,3 +109,8 @@ const selLast = (s: LocalState) => s.lastReconnect;
export function useLastReconnect() {
return useLocalState(selLast);
}

const selInFocus = (s: LocalState) => s.inFocus;
export function useInFocus() {
return useLocalState(selInFocus);
}

0 comments on commit b25b9ec

Please sign in to comment.