diff --git a/desk/app/chat.hoon b/desk/app/chat.hoon index 3b80cd2a2d..e54fe19f92 100644 --- a/desk/app/chat.hoon +++ b/desk/app/chat.hoon @@ -1134,8 +1134,6 @@ (put:log-on:c log.chat time d) =. ca-core (ca-give-updates time d) - =. cor - (give-brief flag/flag ca-brief) ?- -.d %add-sects =* p perm.chat @@ -1153,6 +1151,7 @@ :: %writs =. pact.chat (reduce:ca-pact time p.d) + =. cor (give-brief flag/flag ca-brief) ?- -.q.p.d ?(%del %add-feel %del-feel) ca-core %add diff --git a/desk/app/diary.hoon b/desk/app/diary.hoon index 1f2a755b0f..98978a7526 100644 --- a/desk/app/diary.hoon +++ b/desk/app/diary.hoon @@ -600,6 +600,7 @@ ?- -.dif %notes =. notes.diary (reduce:di-notes time p.dif) + =. cor (give-brief flag di-brief) =/ cons=(list (list content:ha)) (hark:di-notes our.bowl p.dif) =. cor diff --git a/desk/app/heap.hoon b/desk/app/heap.hoon index b734dd557a..ddc16f1e4a 100644 --- a/desk/app/heap.hoon +++ b/desk/app/heap.hoon @@ -540,6 +540,7 @@ ?- -.d %curios =. curios.heap (reduce:he-curios time q.p.d) + =. cor (give-brief flag he-brief) ?- -.q.p.d ?(%edit %del %add-feel %del-feel) he-core %add diff --git a/ui/package-lock.json b/ui/package-lock.json index 9a5aa8b1c8..cd99b2d65c 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -85,7 +85,7 @@ "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-select": "^5.3.2", - "react-virtuoso": "^2.19.0", + "react-virtuoso": "^3.1.4", "refractor": "^4.8.0", "tailwindcss-scoped-groups": "^2.0.0", "tippy.js": "^6.3.7", @@ -23779,9 +23779,9 @@ } }, "node_modules/react-virtuoso": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-2.19.0.tgz", - "integrity": "sha512-GeCleV9cmpYGh1Ldfgdu+4gADLzdWJ48qc4tWguFzYz7FvUSAoELe8268rR8zfIb5FcV3tqpsdvFS5i51c8jyA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-3.1.4.tgz", + "integrity": "sha512-oZt22JrSi/yLkp3HWa8teo0wqUg8zOA3i7y4dhHoM12njr5B8qGbVrq2fKGp3sbiZ9xiwX44KH5EEBo2GN2S4Q==", "dependencies": { "@virtuoso.dev/react-urx": "^0.2.12", "@virtuoso.dev/urx": "^0.2.12" @@ -47310,9 +47310,9 @@ } }, "react-virtuoso": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-2.19.0.tgz", - "integrity": "sha512-GeCleV9cmpYGh1Ldfgdu+4gADLzdWJ48qc4tWguFzYz7FvUSAoELe8268rR8zfIb5FcV3tqpsdvFS5i51c8jyA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-3.1.4.tgz", + "integrity": "sha512-oZt22JrSi/yLkp3HWa8teo0wqUg8zOA3i7y4dhHoM12njr5B8qGbVrq2fKGp3sbiZ9xiwX44KH5EEBo2GN2S4Q==", "requires": { "@virtuoso.dev/react-urx": "^0.2.12", "@virtuoso.dev/urx": "^0.2.12" diff --git a/ui/package.json b/ui/package.json index 75fb0fa884..039b6d9bb2 100644 --- a/ui/package.json +++ b/ui/package.json @@ -115,7 +115,7 @@ "react-router": "^6.3.0", "react-router-dom": "^6.3.0", "react-select": "^5.3.2", - "react-virtuoso": "^2.19.0", + "react-virtuoso": "^3.1.4", "refractor": "^4.8.0", "tailwindcss-scoped-groups": "^2.0.0", "tippy.js": "^6.3.7", diff --git a/ui/src/chat/ChatChannel.tsx b/ui/src/chat/ChatChannel.tsx index 5829514ba8..8a53bfe781 100644 --- a/ui/src/chat/ChatChannel.tsx +++ b/ui/src/chat/ChatChannel.tsx @@ -17,8 +17,8 @@ import { GROUP_ADMIN, } from '@/state/groups/groups'; import ChannelHeader from '@/channels/ChannelHeader'; -import { canReadChannel, createStorageKey } from '@/logic/utils'; -import { useLocalStorage } from 'usehooks-ts'; +import useRecentChannel from '@/logic/useRecentChannel'; +import { canReadChannel } from '@/logic/utils'; function ChatChannel({ title }: ViewProps) { const navigate = useNavigate(); @@ -26,15 +26,12 @@ function ChatChannel({ title }: ViewProps) { const chFlag = `${chShip}/${chName}`; const nest = `chat/${chFlag}`; const groupFlag = useRouteGroup(); - const [, setRecent] = useLocalStorage( - createStorageKey(`recent-chan:${groupFlag}`), - '' - ); + const { setRecentChannel } = useRecentChannel(groupFlag); useEffect(() => { useChatState.getState().initialize(chFlag); - setRecent(nest); - }, [chFlag, nest, setRecent]); + setRecentChannel(nest); + }, [chFlag, nest, setRecentChannel]); const messages = useMessagesForChat(chFlag); const perms = useChatPerms(chFlag); @@ -50,9 +47,9 @@ function ChatChannel({ title }: ViewProps) { useEffect(() => { if (channel && !canReadChannel(channel, vessel)) { navigate('../../activity'); - setRecent(''); + setRecentChannel(''); } - }, [channel, vessel, navigate, setRecent]); + }, [channel, vessel, navigate, setRecentChannel]); return ( { + async (newer: boolean, pageSize = STANDARD_MESSAGE_FETCH_PAGE_SIZE) => { const newest = messages.peekLargest(); const seenNewest = newer && newest && loaded.newest.geq(newest[0]); const oldest = messages.peekSmallest(); @@ -242,7 +245,7 @@ export default function ChatScroller({ }, [scrollTo, virtuoso]); /** - * By default, 100 messages are fetched on initial load. If there are more + * By default, 50 messages are fetched on initial load. If there are more * unreads per the brief, fetch those as well. That way, the user can click * the unread banner and see the unread messages. */ @@ -250,7 +253,7 @@ export default function ChatScroller({ if ( fetching === 'initial' && brief && - brief.count > MESSAGE_FETCH_PAGE_SIZE && + brief.count > INITIAL_MESSAGE_FETCH_PAGE_SIZE && firstUnreadID && !keys.includes(firstUnreadID) ) { diff --git a/ui/src/chat/ChatUnreadAlerts.tsx b/ui/src/chat/ChatUnreadAlerts.tsx index 9270b0339f..cf44c2fc7d 100644 --- a/ui/src/chat/ChatUnreadAlerts.tsx +++ b/ui/src/chat/ChatUnreadAlerts.tsx @@ -1,11 +1,11 @@ import React, { useCallback } from 'react'; import { format, isToday } from 'date-fns'; import { useLocation, useNavigate } from 'react-router'; +import { daToUnix, udToDec } from '@urbit/api'; import bigInt from 'big-integer'; import XIcon from '@/components/icons/XIcon'; -import { ChatBrief } from '@/types/chat'; -import { pluralize } from '../logic/utils'; -import { useChatKeys, useChatState } from '../state/chat'; +import { pluralize } from '@/logic/utils'; +import { useChatState, useGetFirstUnreadID } from '@/state/chat'; import { useChatInfo } from './useChatStore'; interface ChatUnreadAlertsProps { @@ -21,30 +21,24 @@ export default function ChatUnreadAlerts({ whom }: ChatUnreadAlertsProps) { const navigate = useNavigate(); const location = useLocation(); // TODO: how to handle replies? - const chatKeys = useChatKeys({ replying: false }); - const goToFirstUnread = useCallback( - (b: ChatBrief) => { - const { 'read-id': lastRead } = b; - if (!lastRead) { - return; - } - // lastRead is formatted like: ~zod/123.456.789... - const lastReadBN = bigInt(lastRead.split('/')[1].replaceAll('.', '')); - const firstUnread = chatKeys.find((key) => key.gt(lastReadBN)); - if (!firstUnread) { - return; - } - navigate(`${location.pathname}?msg=${firstUnread.toString()}`); - }, - [chatKeys, location.pathname, navigate] - ); + const firstUnreadID = useGetFirstUnreadID(whom); + const goToFirstUnread = useCallback(() => { + if (!firstUnreadID) { + return; + } + navigate(`${location.pathname}?msg=${firstUnreadID.toString()}`); + }, [firstUnreadID, location.pathname, navigate]); if (!chatInfo.unread || chatInfo.unread.seen) { return null; } const { brief } = chatInfo.unread; - const date = brief ? new Date(brief.last) : new Date(); + const readId = brief['read-id']; + const udTime = readId + ? daToUnix(bigInt(udToDec(readId.split('/')[1]))) + : null; + const date = udTime ? new Date(udTime) : new Date(); const since = isToday(date) ? `${format(date, 'HH:mm')} today` : format(date, 'LLLL d'); @@ -62,7 +56,7 @@ export default function ChatUnreadAlerts({ whom }: ChatUnreadAlertsProps) {
`; diff --git a/ui/src/groups/Groups.tsx b/ui/src/groups/Groups.tsx index a21534a9a5..f575a29e71 100644 --- a/ui/src/groups/Groups.tsx +++ b/ui/src/groups/Groups.tsx @@ -11,9 +11,8 @@ import api from '@/api'; import { useChatState } from '@/state/chat'; import { useHeapState } from '@/state/heap/heap'; import { useDiaryState } from '@/state/diary'; -import { createStorageKey, nestToFlag } from '@/logic/utils'; -import { useLocalStorage } from 'usehooks-ts'; import { useIsMobile } from '@/logic/useMedia'; +import useRecentChannel from '@/logic/useRecentChannel'; import _ from 'lodash'; function Groups() { @@ -27,10 +26,7 @@ function Groups() { path: '/groups/:ship/:name', end: true, }); - const [recentChannel] = useLocalStorage( - createStorageKey(`recent-chan:${flag}`), - '' - ); + const { recentChannel } = useRecentChannel(flag); useEffect(() => { if (initialized && !group && !gang) { diff --git a/ui/src/heap/HeapChannel.tsx b/ui/src/heap/HeapChannel.tsx index c6ea62dd3b..26e1b0f7c5 100644 --- a/ui/src/heap/HeapChannel.tsx +++ b/ui/src/heap/HeapChannel.tsx @@ -3,7 +3,7 @@ import _ from 'lodash'; import cn from 'classnames'; import { Outlet, useParams, useNavigate } from 'react-router'; import { Helmet } from 'react-helmet'; -import { useLocalStorage } from 'usehooks-ts'; +import bigInt from 'big-integer'; import { ViewProps } from '@/types/groups'; import Layout from '@/components/Layout/Layout'; import { @@ -33,7 +33,7 @@ import HeapRow from '@/heap/HeapRow'; import useDismissChannelNotifications from '@/logic/useDismissChannelNotifications'; import { canReadChannel, createStorageKey } from '@/logic/utils'; import { GRID, HeapCurio, HeapDisplayMode, HeapSortMode } from '@/types/heap'; -import bigInt from 'big-integer'; +import useRecentChannel from '@/logic/useRecentChannel'; import NewCurioForm from './NewCurioForm'; function HeapChannel({ title }: ViewProps) { @@ -45,17 +45,14 @@ function HeapChannel({ title }: ViewProps) { const vessel = useVessel(flag, window.our); const channel = useChannel(flag, nest); const group = useGroup(flag); - const [, setRecent] = useLocalStorage( - createStorageKey(`recent-chan:${flag}`), - '' - ); + const { setRecentChannel } = useRecentChannel(flag); useEffect(() => { if (channel && !canReadChannel(channel, vessel)) { navigate('../../activity'); - setRecent(''); + setRecentChannel(''); } - }, [channel, vessel, navigate, setRecent]); + }, [channel, vessel, navigate, setRecentChannel]); const displayMode = useHeapDisplayMode(chFlag); const settings = useHeapSettings(); @@ -99,8 +96,8 @@ function HeapChannel({ title }: ViewProps) { useEffect(() => { useHeapState.getState().initialize(chFlag); - setRecent(nest); - }, [chFlag, nest, setRecent]); + setRecentChannel(nest); + }, [chFlag, nest, setRecentChannel]); useDismissChannelNotifications({ nest, diff --git a/ui/src/logic/useChannelSort.ts b/ui/src/logic/useChannelSort.ts index 7ebbc55210..fc76bcdd49 100644 --- a/ui/src/logic/useChannelSort.ts +++ b/ui/src/logic/useChannelSort.ts @@ -1,72 +1,21 @@ import { get } from 'lodash'; -import { useCallback } from 'react'; import { useGroup, useRouteGroup } from '@/state/groups'; import { GroupChannel, Channels, Zone } from '@/types/groups'; -import { useGetLatestChat } from '@/state/chat'; -import { ChatWhom } from '@/types/chat'; -import { useGetLatestNote } from '@/state/diary'; -import { useGetLatestCurio } from '@/state/heap/heap'; import useSidebarSort, { ALPHABETICAL, DEFAULT, RECENT, sortAlphabetical, Sorter, + useRecentSort, } from './useSidebarSort'; -import { nestToFlag } from './utils'; const UNZONED = 'default'; -function useGetLatestPost() { - const getLatestChat = useGetLatestChat(); - const getLatestCurio = useGetLatestCurio(); - const getLatestNote = useGetLatestNote(); - - return (flag: string) => { - const [chType, _chFlag] = nestToFlag(flag); - - switch (chType) { - case 'chat': - return (getLatestChat(flag)[0] ?? Number.NEGATIVE_INFINITY).toString(); - - case 'diary': - return (getLatestNote(flag)[0] ?? Number.NEGATIVE_INFINITY).toString(); - - case 'heap': - return (getLatestCurio(flag)[0] ?? Number.NEGATIVE_INFINITY).toString(); - - default: - return Number.NEGATIVE_INFINITY.toString(); - } - }; -} - -function useRecentChannelSort() { - const getLatestPost = useGetLatestPost(); - - const sortRecent = useCallback( - (a: ChatWhom, b: ChatWhom) => { - const aLast = getLatestPost(a); - const bLast = getLatestPost(b); - - if (aLast < bLast) { - return -1; - } - if (aLast > bLast) { - return 1; - } - return 0; - }, - [getLatestPost] - ); - - return sortRecent; -} - export default function useChannelSort() { const groupFlag = useRouteGroup(); const group = useGroup(groupFlag); - const sortRecent = useRecentChannelSort(); + const sortRecent = useRecentSort(); const sortDefault = (a: Zone, b: Zone) => { if (!group) { diff --git a/ui/src/logic/useGroupSort.ts b/ui/src/logic/useGroupSort.ts index bbae6aa8bc..8932b31608 100644 --- a/ui/src/logic/useGroupSort.ts +++ b/ui/src/logic/useGroupSort.ts @@ -32,7 +32,11 @@ export default function useGroupSort() { }, }; - return sortRecordsBy(groups, accessors[sortFn], sortFn === RECENT); + return sortRecordsBy( + groups, + accessors[sortFn] || accessors[ALPHABETICAL], + sortFn === RECENT + ); } return { diff --git a/ui/src/logic/usePrefetchChannels.ts b/ui/src/logic/usePrefetchChannels.ts index a1f4a89e76..c220d305be 100644 --- a/ui/src/logic/usePrefetchChannels.ts +++ b/ui/src/logic/usePrefetchChannels.ts @@ -1,10 +1,13 @@ import { useCallback, useEffect } from 'react'; +import { chunk } from 'lodash'; import { useGroup } from '@/state/groups'; import { useChatState } from '@/state/chat'; import { asyncForEach } from '@/lib'; import { useHeapState } from '@/state/heap/heap'; import { useDiaryState } from '@/state/diary'; +import { FETCH_BATCH_SIZE } from '@/constants'; import { nestToFlag } from './utils'; +import useRecentChannel from './useRecentChannel'; /** * On load, prefetches the messages for the group that the user is currently in. @@ -14,6 +17,7 @@ import { nestToFlag } from './utils'; */ export default function usePrefetchChannels(flag: string) { const group = useGroup(flag); + const { recentChannel } = useRecentChannel(flag); const { initialize: initializeChat } = useChatState.getState(); const { initialize: initializeDiary } = useDiaryState.getState(); const { initialize: initializeHeap } = useHeapState.getState(); @@ -23,7 +27,7 @@ export default function usePrefetchChannels(flag: string) { const [chType, chFlag] = nestToFlag(channel); switch (chType) { case 'chat': - initializeChat(chFlag); + await initializeChat(chFlag); break; case 'diary': initializeDiary(chFlag); @@ -39,8 +43,20 @@ export default function usePrefetchChannels(flag: string) { ); const fetchAll = useCallback(async () => { - await asyncForEach(Object.keys(group?.channels ?? {}), fetchChannel); - }, [fetchChannel, group]); + // first, prioritize the recent channel + if (recentChannel && recentChannel !== '') { + await fetchChannel(recentChannel); + } + + // defer the rest, in batches + const channels = Object.keys(group?.channels ?? {}).filter( + (c) => c !== recentChannel + ); + const batched = chunk(channels, FETCH_BATCH_SIZE); + batched.forEach(async (batch) => { + await asyncForEach(batch, fetchChannel); + }); + }, [fetchChannel, group, recentChannel]); useEffect(() => { if (!group) { diff --git a/ui/src/logic/useRecentChannel.ts b/ui/src/logic/useRecentChannel.ts new file mode 100644 index 0000000000..365c6ba804 --- /dev/null +++ b/ui/src/logic/useRecentChannel.ts @@ -0,0 +1,15 @@ +import { useLocalStorage } from 'usehooks-ts'; +import { createStorageKey } from './utils'; + +/** + * Tracks which channel was most recently visited + * @param flag The group flag + */ +export default function useRecentChannel(flag: string) { + const [recentChannel, setRecentChannel] = useLocalStorage( + createStorageKey(`recent-chan:${flag}`), + '' + ); + + return { recentChannel, setRecentChannel }; +} diff --git a/ui/src/logic/useSidebarSort.ts b/ui/src/logic/useSidebarSort.ts index b77a299a93..deb87e0a19 100644 --- a/ui/src/logic/useSidebarSort.ts +++ b/ui/src/logic/useSidebarSort.ts @@ -1,11 +1,10 @@ import { useCallback } from 'react'; -import { useBriefs } from '@/state/chat'; -import { ChatWhom } from '@/types/chat'; import { SettingsState, useSettingsState, useGroupSideBarSort, } from '@/state/settings'; +import useAllBriefs from './useAllBriefs'; export const ALPHABETICAL = 'A → Z'; export const DEFAULT = 'Arranged'; @@ -21,19 +20,19 @@ interface UseSidebarSort { flag?: string; } -export const sortAlphabetical = (a: ChatWhom, b: ChatWhom) => - a.localeCompare(b); +export const sortAlphabetical = (aNest: string, bNest: string) => + aNest.localeCompare(bNest); const selSideBarSort = (s: SettingsState) => ({ sideBarSort: s.groups.sideBarSort, }); export function useRecentSort() { - const briefs = useBriefs(); + const briefs = useAllBriefs(); const sortRecent = useCallback( - (a: ChatWhom, b: ChatWhom) => { - const aLast = briefs[a]?.last ?? Number.NEGATIVE_INFINITY; - const bLast = briefs[b]?.last ?? Number.NEGATIVE_INFINITY; + (aNest: string, bNest: string) => { + const aLast = briefs[aNest]?.last ?? Number.NEGATIVE_INFINITY; + const bLast = briefs[bNest]?.last ?? Number.NEGATIVE_INFINITY; if (aLast < bLast) { return -1; } @@ -89,7 +88,8 @@ export default function useSidebarSort({ const aVal = accessor(aKey, aObj); const bVal = accessor(bKey, bObj); - return sortOptions[sortFn ?? 'A → Z'](aVal, bVal); + const sorter = sortOptions[sortFn] ?? sortOptions[ALPHABETICAL]; + return sorter(aVal, bVal); }); return reverse ? entries.reverse() : entries; diff --git a/ui/src/state/chat/chat.ts b/ui/src/state/chat/chat.ts index 175a700746..ab1d1d8b83 100644 --- a/ui/src/state/chat/chat.ts +++ b/ui/src/state/chat/chat.ts @@ -616,7 +616,7 @@ export const useChatState = createState( draft.chatSubs.push(whom); }); - await makeWritsStore( + makeWritsStore( whom, get, `/chat/${whom}/writs`, diff --git a/ui/src/state/chat/writs.ts b/ui/src/state/chat/writs.ts index 15e4c54aca..07fa00ea71 100644 --- a/ui/src/state/chat/writs.ts +++ b/ui/src/state/chat/writs.ts @@ -1,5 +1,6 @@ import { BigIntOrderedMap, decToUd, udToDec, unixToDa } from '@urbit/api'; import bigInt from 'big-integer'; +import { INITIAL_MESSAGE_FETCH_PAGE_SIZE } from '@/constants'; import api from '../../api'; import { ChatWrit, @@ -112,7 +113,9 @@ export default function makeWritsStore( }); return { initialize: async () => { - const writs = await scry(`/newest/100`); + const writs = await scry( + `/newest/${INITIAL_MESSAGE_FETCH_PAGE_SIZE}` + ); const sta = get(); sta.batchSet((draft) => { const pact: Pact = { diff --git a/ui/src/state/diary/notes.ts b/ui/src/state/diary/notes.ts index ed2957b2fc..3c48743712 100644 --- a/ui/src/state/diary/notes.ts +++ b/ui/src/state/diary/notes.ts @@ -1,17 +1,16 @@ +import bigInt from 'big-integer'; +import { BigIntOrderedMap, decToUd, udToDec } from '@urbit/api'; +import { INITIAL_MESSAGE_FETCH_PAGE_SIZE } from '@/constants'; import { - NoteDiff, NoteSeal, DiaryNote, DiaryNotes, DiaryFlag, - DiaryDiff, DiaryUpdate, DiaryOutlines, DiaryLetter, DiaryQuip, } from '@/types/diary'; -import { BigIntOrderedMap, decToUd, udToDec } from '@urbit/api'; -import bigInt from 'big-integer'; import api from '../../api'; import { DiaryState } from './type'; @@ -75,7 +74,9 @@ export default function makeNotesStore( return { initialize: async () => { - const notes = await scry(`/newest/100/outline`); + const notes = await scry( + `/newest/${INITIAL_MESSAGE_FETCH_PAGE_SIZE}/outline` + ); const sta = get(); sta.batchSet((draft) => { let noteMap = new BigIntOrderedMap(); diff --git a/ui/src/state/heap/curios.ts b/ui/src/state/heap/curios.ts index 379e671fbf..671db87614 100644 --- a/ui/src/state/heap/curios.ts +++ b/ui/src/state/heap/curios.ts @@ -1,3 +1,6 @@ +import { BigIntOrderedMap, decToUd, udToDec } from '@urbit/api'; +import bigInt from 'big-integer'; +import { INITIAL_MESSAGE_FETCH_PAGE_SIZE } from '@/constants'; import { CurioDiff, CurioSeal, @@ -5,8 +8,6 @@ import { HeapCurios, HeapFlag, } from '@/types/heap'; -import { BigIntOrderedMap, decToUd, udToDec } from '@urbit/api'; -import bigInt from 'big-integer'; import api from '../../api'; import { HeapState } from './type'; @@ -70,7 +71,9 @@ export default function makeCuriosStore( return { initialize: async () => { - const curios = await scry(`/newest/100`); + const curios = await scry( + `/newest/${INITIAL_MESSAGE_FETCH_PAGE_SIZE}` + ); const sta = get(); sta.batchSet((draft) => { let curioMap = new BigIntOrderedMap(); diff --git a/ui/src/state/settings.ts b/ui/src/state/settings.ts index da95b19b61..2ad31c8cfd 100644 --- a/ui/src/state/settings.ts +++ b/ui/src/state/settings.ts @@ -141,7 +141,7 @@ export const useSettingsState = createState( }, groups: { orderedGroupPins: [], - sideBarSort: ALPHABETICAL, + sideBarSort: DEFAULT, groupSideBarSort: '{"~": "A → Z"}' as Stringified, }, talk: { @@ -243,7 +243,7 @@ export function useHeapSortMode(flag: string): HeapSortMode { export function useHeapDisplayMode(flag: string): HeapDisplayMode { const settings = useHeapSettings(); const heapSetting = getSetting(settings, flag); - return heapSetting?.displayMode ?? 'list'; + return heapSetting?.displayMode ?? 'grid'; } const selDiarySettings = (s: SettingsState) => s.diary.settings;