From 3baac2909b15f6153e36a5282965fd79a5f43100 Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Mon, 22 Jul 2024 09:06:30 -0500 Subject: [PATCH 1/3] activity: moving mark everything as read button --- .../src/components/Settings/Settings.tsx | 47 +++++++++++++++++++ .../tlon-web/src/components/VolumeSetting.tsx | 2 +- .../src/notifications/Notifications.tsx | 39 +-------------- 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/apps/tlon-web/src/components/Settings/Settings.tsx b/apps/tlon-web/src/components/Settings/Settings.tsx index 40f629e974..16c2a17795 100644 --- a/apps/tlon-web/src/components/Settings/Settings.tsx +++ b/apps/tlon-web/src/components/Settings/Settings.tsx @@ -1,7 +1,13 @@ +import { useMutation } from '@tanstack/react-query'; +import { ActivityAction, ActivityUpdate } from '@tloncorp/shared/dist/urbit'; +import cn from 'classnames'; +import { useCallback } from 'react'; import { Link, useLocation } from 'react-router-dom'; +import api from '@/api'; import LoadingSpinner from '@/components/LoadingSpinner/LoadingSpinner'; import { useIsMobile } from '@/logic/useMedia'; +import { activityAction } from '@/state/activity'; import { Theme, useCalm, @@ -44,9 +50,50 @@ export default function Settings() { usePutEntryMutation({ bucket: window.desk, key: 'logActivity' }); const { mutate: resetAnalyticsId, status: resetAnalyticsIdStatus } = useResetAnalyticsIdMutation(); + const { mutate: markRead, isLoading } = useMutation({ + mutationFn: async () => { + await api.trackedPoke( + activityAction({ + read: { + source: { base: null }, + action: { all: { time: null, deep: true } }, + }, + }), + { app: 'activity', path: '/v4' }, + (event) => 'activity' in event + ); + + await new Promise((res) => setTimeout(res, 1000)); + }, + }); + const isMarkReadPending = isLoading; + const markAllRead = useCallback(async () => { + markRead(); + }, []); return ( <> +
+
+

Activity

+

+ Mark all channels, DMs, and threads read (aka get rid of dots) +

+ +
+

Blocked Users

diff --git a/apps/tlon-web/src/components/VolumeSetting.tsx b/apps/tlon-web/src/components/VolumeSetting.tsx index 6b34d9d89d..35b59dbadf 100644 --- a/apps/tlon-web/src/components/VolumeSetting.tsx +++ b/apps/tlon-web/src/components/VolumeSetting.tsx @@ -71,7 +71,7 @@ export default function VolumeSetting({ source }: { source: Source }) { ); return ( -
+
0; const getMore = useCallback(() => { if (hasNextPage) { @@ -103,36 +98,6 @@ export default function Notifications({ title }: NotificationsProps) { } }, [hasNextPage]); - const markAllRead = useCallback(async () => { - mutate({ source: { base: null } }); - }, []); - - const MarkAsRead = ( - - ); - - const MobileMarkAsRead = ( - - ); - return ( <> {isMobile && ( @@ -141,7 +106,6 @@ export default function Notifications({ title }: NotificationsProps) { action={
- {hasUnreads && MobileMarkAsRead}
} /> @@ -163,7 +127,6 @@ export default function Notifications({ title }: NotificationsProps) {

Activity

- {hasUnreads && MarkAsRead}
)} From fcbb3de054a926b37a83858132eec2d844a7fd9f Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Mon, 22 Jul 2024 09:29:21 -0500 Subject: [PATCH 2/3] activity: remove bell tab dot when visiting --- .../src/notifications/Notifications.tsx | 22 ++++++++++++- apps/tlon-web/src/state/activity.ts | 32 +++++++++++++++++-- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/apps/tlon-web/src/notifications/Notifications.tsx b/apps/tlon-web/src/notifications/Notifications.tsx index 6de688132c..6a71d222bb 100644 --- a/apps/tlon-web/src/notifications/Notifications.tsx +++ b/apps/tlon-web/src/notifications/Notifications.tsx @@ -1,7 +1,7 @@ import { ActivityBundle, ActivitySummary } from '@tloncorp/shared/dist/urbit'; import { ViewProps } from '@tloncorp/shared/dist/urbit/groups'; import cn from 'classnames'; -import { PropsWithChildren, useCallback } from 'react'; +import { PropsWithChildren, useCallback, useEffect } from 'react'; import { Helmet } from 'react-helmet'; import { Virtuoso } from 'react-virtuoso'; @@ -11,6 +11,11 @@ import WelcomeCard from '@/components/WelcomeCard'; import { useBottomPadding } from '@/logic/position'; import { useIsMobile } from '@/logic/useMedia'; import { makePrettyDay, randomElement, randomIntInRange } from '@/logic/utils'; +import { + emptySummary, + useActivity, + useOptimisticMarkRead, +} from '@/state/activity'; import Notification from './Notification'; import { useNotifications } from './useNotifications'; @@ -91,6 +96,21 @@ export default function Notifications({ title }: NotificationsProps) { const { paddingBottom } = useBottomPadding(); const { loaded, notifications, fetchNextPage, hasNextPage } = useNotifications(); + const { activity, isLoading } = useActivity(); + const markRead = useOptimisticMarkRead('base'); + + useEffect(() => { + const hasActivity = Object.keys(activity).length > 0; + const base = activity['base'] || emptySummary; + const baseIsRead = + base.count === 0 && + base.unread === null && + !base.notify && + base['notify-count'] === 0; + if (hasActivity && !baseIsRead && !isLoading) { + markRead(); + } + }, [activity, isLoading]); const getMore = useCallback(() => { if (hasNextPage) { diff --git a/apps/tlon-web/src/state/activity.ts b/apps/tlon-web/src/state/activity.ts index 0afea54100..99a84cd70c 100644 --- a/apps/tlon-web/src/state/activity.ts +++ b/apps/tlon-web/src/state/activity.ts @@ -131,7 +131,14 @@ function activityVolumeUpdates(events: ActivityVolumeUpdate[]) { }, {} as VolumeSettings); } -function optimisticActivityUpdate(d: Activity, source: string): Activity { +function optimisticActivityUpdate( + d: Activity | undefined, + source: string +): Activity | undefined { + if (!d) { + return d; + } + const old = d[source]; return { ...d, @@ -141,7 +148,7 @@ function optimisticActivityUpdate(d: Activity, source: string): Activity { 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) + ? Math.min(0, old['notify-count'] - old.unread.count) : old['notify-count'], }, }; @@ -610,3 +617,24 @@ export function useCombinedGroupUnreads() { }; }, defaultUnread); } + +export function useOptimisticMarkRead(source: string) { + return useCallback(() => { + queryClient.setQueryData(unreadsKey(), (d) => { + if (d === undefined) { + return undefined; + } + + return { + ...d, + [source]: { + ...d[source], + unread: null, + count: 0, + notify: false, + 'notify-count': 0, + }, + }; + }); + }, [source]); +} From b6855071025cf1173b6c868f9cb8a317d62b0d24 Mon Sep 17 00:00:00 2001 From: Hunter Miller Date: Mon, 22 Jul 2024 09:41:33 -0500 Subject: [PATCH 3/3] activity: fix optimistic marking --- apps/tlon-web/src/state/activity.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/tlon-web/src/state/activity.ts b/apps/tlon-web/src/state/activity.ts index 99a84cd70c..34c05b6790 100644 --- a/apps/tlon-web/src/state/activity.ts +++ b/apps/tlon-web/src/state/activity.ts @@ -131,14 +131,7 @@ function activityVolumeUpdates(events: ActivityVolumeUpdate[]) { }, {} as VolumeSettings); } -function optimisticActivityUpdate( - d: Activity | undefined, - source: string -): Activity | undefined { - if (!d) { - return d; - } - +function optimisticActivityUpdate(d: Activity, source: string): Activity { const old = d[source]; return { ...d, @@ -374,8 +367,8 @@ export function useMarkReadMutation(recursive = false) { const mutationFn = async (variables: { source: Source; action?: ReadAction; - }) => { - await api.poke( + }) => + api.poke( activityAction({ read: { source: variables.source, @@ -383,12 +376,14 @@ export function useMarkReadMutation(recursive = false) { }, }) ); - }; return useMutation({ mutationFn, onMutate: async (variables) => { const current = queryClient.getQueryData(unreadsKey()); + variables.action = variables.action || { + all: { time: null, deep: recursive }, + }; queryClient.setQueryData(unreadsKey(), (d) => { if (d === undefined) { return undefined;