Skip to content

Commit 853f921

Browse files
authored
Merge pull request #1197 from tloncorp/t/1187-performance-enhancements
omnibus: scroller perf, devex enhancements
2 parents 38b495f + ec9db5f commit 853f921

26 files changed

+141
-156
lines changed

desk/app/chat.hoon

+1-2
Original file line numberDiff line numberDiff line change
@@ -1134,8 +1134,6 @@
11341134
(put:log-on:c log.chat time d)
11351135
=. ca-core
11361136
(ca-give-updates time d)
1137-
=. cor
1138-
(give-brief flag/flag ca-brief)
11391137
?- -.d
11401138
%add-sects
11411139
=* p perm.chat
@@ -1153,6 +1151,7 @@
11531151
::
11541152
%writs
11551153
=. pact.chat (reduce:ca-pact time p.d)
1154+
=. cor (give-brief flag/flag ca-brief)
11561155
?- -.q.p.d
11571156
?(%del %add-feel %del-feel) ca-core
11581157
%add

desk/app/diary.hoon

+1
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,7 @@
600600
?- -.dif
601601
%notes
602602
=. notes.diary (reduce:di-notes time p.dif)
603+
=. cor (give-brief flag di-brief)
603604
=/ cons=(list (list content:ha))
604605
(hark:di-notes our.bowl p.dif)
605606
=. cor

desk/app/heap.hoon

+1
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@
540540
?- -.d
541541
%curios
542542
=. curios.heap (reduce:he-curios time q.p.d)
543+
=. cor (give-brief flag he-brief)
543544
?- -.q.p.d
544545
?(%edit %del %add-feel %del-feel) he-core
545546
%add

ui/package-lock.json

+7-7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ui/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115
"react-router": "^6.3.0",
116116
"react-router-dom": "^6.3.0",
117117
"react-select": "^5.3.2",
118-
"react-virtuoso": "^2.19.0",
118+
"react-virtuoso": "^3.1.4",
119119
"refractor": "^4.8.0",
120120
"tailwindcss-scoped-groups": "^2.0.0",
121121
"tippy.js": "^6.3.7",

ui/src/chat/ChatChannel.tsx

+7-10
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,21 @@ import {
1717
GROUP_ADMIN,
1818
} from '@/state/groups/groups';
1919
import ChannelHeader from '@/channels/ChannelHeader';
20-
import { canReadChannel, createStorageKey } from '@/logic/utils';
21-
import { useLocalStorage } from 'usehooks-ts';
20+
import useRecentChannel from '@/logic/useRecentChannel';
21+
import { canReadChannel } from '@/logic/utils';
2222

2323
function ChatChannel({ title }: ViewProps) {
2424
const navigate = useNavigate();
2525
const { chShip, chName } = useParams();
2626
const chFlag = `${chShip}/${chName}`;
2727
const nest = `chat/${chFlag}`;
2828
const groupFlag = useRouteGroup();
29-
const [, setRecent] = useLocalStorage(
30-
createStorageKey(`recent-chan:${groupFlag}`),
31-
''
32-
);
29+
const { setRecentChannel } = useRecentChannel(groupFlag);
3330

3431
useEffect(() => {
3532
useChatState.getState().initialize(chFlag);
36-
setRecent(nest);
37-
}, [chFlag, nest, setRecent]);
33+
setRecentChannel(nest);
34+
}, [chFlag, nest, setRecentChannel]);
3835

3936
const messages = useMessagesForChat(chFlag);
4037
const perms = useChatPerms(chFlag);
@@ -50,9 +47,9 @@ function ChatChannel({ title }: ViewProps) {
5047
useEffect(() => {
5148
if (channel && !canReadChannel(channel, vessel)) {
5249
navigate('../../activity');
53-
setRecent('');
50+
setRecentChannel('');
5451
}
55-
}, [channel, vessel, navigate, setRecent]);
52+
}, [channel, vessel, navigate, setRecentChannel]);
5653

5754
return (
5855
<Layout

ui/src/chat/ChatScroller/ChatScroller.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import {
1919
useGetFirstUnreadID,
2020
useLoadedWrits,
2121
} from '@/state/chat/chat';
22-
import { MESSAGE_FETCH_PAGE_SIZE } from '@/constants';
22+
import {
23+
INITIAL_MESSAGE_FETCH_PAGE_SIZE,
24+
STANDARD_MESSAGE_FETCH_PAGE_SIZE,
25+
} from '@/constants';
2326
import { ChatBrief, ChatWrit } from '@/types/chat';
2427
import { useIsMobile } from '@/logic/useMedia';
2528
import { IChatScroller } from './IChatScroller';
@@ -182,7 +185,7 @@ export default function ChatScroller({
182185
);
183186

184187
const fetchMessages = useCallback(
185-
async (newer: boolean, pageSize = MESSAGE_FETCH_PAGE_SIZE) => {
188+
async (newer: boolean, pageSize = STANDARD_MESSAGE_FETCH_PAGE_SIZE) => {
186189
const newest = messages.peekLargest();
187190
const seenNewest = newer && newest && loaded.newest.geq(newest[0]);
188191
const oldest = messages.peekSmallest();
@@ -242,15 +245,15 @@ export default function ChatScroller({
242245
}, [scrollTo, virtuoso]);
243246

244247
/**
245-
* By default, 100 messages are fetched on initial load. If there are more
248+
* By default, 50 messages are fetched on initial load. If there are more
246249
* unreads per the brief, fetch those as well. That way, the user can click
247250
* the unread banner and see the unread messages.
248251
*/
249252
useEffect(() => {
250253
if (
251254
fetching === 'initial' &&
252255
brief &&
253-
brief.count > MESSAGE_FETCH_PAGE_SIZE &&
256+
brief.count > INITIAL_MESSAGE_FETCH_PAGE_SIZE &&
254257
firstUnreadID &&
255258
!keys.includes(firstUnreadID)
256259
) {

ui/src/chat/ChatUnreadAlerts.tsx

+16-22
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React, { useCallback } from 'react';
22
import { format, isToday } from 'date-fns';
33
import { useLocation, useNavigate } from 'react-router';
4+
import { daToUnix, udToDec } from '@urbit/api';
45
import bigInt from 'big-integer';
56
import XIcon from '@/components/icons/XIcon';
6-
import { ChatBrief } from '@/types/chat';
7-
import { pluralize } from '../logic/utils';
8-
import { useChatKeys, useChatState } from '../state/chat';
7+
import { pluralize } from '@/logic/utils';
8+
import { useChatState, useGetFirstUnreadID } from '@/state/chat';
99
import { useChatInfo } from './useChatStore';
1010

1111
interface ChatUnreadAlertsProps {
@@ -21,30 +21,24 @@ export default function ChatUnreadAlerts({ whom }: ChatUnreadAlertsProps) {
2121
const navigate = useNavigate();
2222
const location = useLocation();
2323
// TODO: how to handle replies?
24-
const chatKeys = useChatKeys({ replying: false });
25-
const goToFirstUnread = useCallback(
26-
(b: ChatBrief) => {
27-
const { 'read-id': lastRead } = b;
28-
if (!lastRead) {
29-
return;
30-
}
31-
// lastRead is formatted like: ~zod/123.456.789...
32-
const lastReadBN = bigInt(lastRead.split('/')[1].replaceAll('.', ''));
33-
const firstUnread = chatKeys.find((key) => key.gt(lastReadBN));
34-
if (!firstUnread) {
35-
return;
36-
}
37-
navigate(`${location.pathname}?msg=${firstUnread.toString()}`);
38-
},
39-
[chatKeys, location.pathname, navigate]
40-
);
24+
const firstUnreadID = useGetFirstUnreadID(whom);
25+
const goToFirstUnread = useCallback(() => {
26+
if (!firstUnreadID) {
27+
return;
28+
}
29+
navigate(`${location.pathname}?msg=${firstUnreadID.toString()}`);
30+
}, [firstUnreadID, location.pathname, navigate]);
4131

4232
if (!chatInfo.unread || chatInfo.unread.seen) {
4333
return null;
4434
}
4535

4636
const { brief } = chatInfo.unread;
47-
const date = brief ? new Date(brief.last) : new Date();
37+
const readId = brief['read-id'];
38+
const udTime = readId
39+
? daToUnix(bigInt(udToDec(readId.split('/')[1])))
40+
: null;
41+
const date = udTime ? new Date(udTime) : new Date();
4842
const since = isToday(date)
4943
? `${format(date, 'HH:mm')} today`
5044
: format(date, 'LLLL d');
@@ -62,7 +56,7 @@ export default function ChatUnreadAlerts({ whom }: ChatUnreadAlertsProps) {
6256
<div className="absolute top-2 left-1/2 z-20 flex w-full -translate-x-1/2 flex-wrap items-center justify-center gap-2">
6357
<button
6458
className="button whitespace-nowrap bg-blue-soft text-sm text-blue dark:bg-blue-900 lg:text-base"
65-
onClick={() => goToFirstUnread(brief)}
59+
onClick={goToFirstUnread}
6660
>
6761
<span className="whitespace-nowrap font-normal">
6862
{unreadMessage}&nbsp;&mdash;&nbsp;Click to View

ui/src/components/ButterBar.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { useLocalStorage } from 'usehooks-ts';
3+
import { createStorageKey } from '@/logic/utils';
34
import AsteriskIcon from './icons/Asterisk16Icon';
45

56
interface ButterBarProps {
@@ -8,7 +9,10 @@ interface ButterBarProps {
89
}
910

1011
function ButterBar({ dismissKey, message }: ButterBarProps) {
11-
const [isDismissed, setIsDismissed] = useLocalStorage(dismissKey, false);
12+
const [isDismissed, setIsDismissed] = useLocalStorage(
13+
createStorageKey(dismissKey),
14+
false
15+
);
1216

1317
function onClick() {
1418
setIsDismissed(true);

ui/src/components/PrereleaseNotice.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default function PrereleaseNotice() {
77

88
return (
99
<ButterBar
10-
dismissKey={`${app}-prerelease-notice-dismissed`}
10+
dismissKey={`prerelease-notice-dismissed`}
1111
message={`Reminder: you are using a Beta version of ${app}. Everything you write or create, including groups and messages, will be deleted prior to official launch.`}
1212
/>
1313
);

ui/src/constants.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// eslint-disable-next-line import/prefer-default-export
2-
export const MESSAGE_FETCH_PAGE_SIZE = 100;
2+
export const INITIAL_MESSAGE_FETCH_PAGE_SIZE = 50;
3+
export const STANDARD_MESSAGE_FETCH_PAGE_SIZE = 100;
4+
export const LARGE_MESSAGE_FETCH_PAGE_SIZE = 200;
5+
export const FETCH_BATCH_SIZE = 3;
36
export const MAX_DISPLAYED_OPTIONS = 40;
47

58
export const AUTHORS = [

ui/src/diary/DiaryChannel.tsx

+6-9
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import useDismissChannelNotifications from '@/logic/useDismissChannelNotificatio
2727
import { DiaryDisplayMode } from '@/types/diary';
2828
import DiaryGridView from '@/diary/DiaryList/DiaryGridView';
2929
import { Link } from 'react-router-dom';
30-
import { useLocalStorage } from 'usehooks-ts';
3130
import * as Toast from '@radix-ui/react-toast';
31+
import useRecentChannel from '@/logic/useRecentChannel';
3232
import { canReadChannel, createStorageKey } from '@/logic/utils';
3333
import DiaryListItem from './DiaryList/DiaryListItem';
3434
import useDiaryActions from './useDiaryActions';
@@ -42,18 +42,15 @@ function DiaryChannel() {
4242
const letters = useNotesForDiary(chFlag);
4343
const location = useLocation();
4444
const navigate = useNavigate();
45-
const [, setRecent] = useLocalStorage(
46-
createStorageKey(`recent-chan:${flag}`),
47-
''
48-
);
45+
const { setRecentChannel } = useRecentChannel(flag);
4946
const channel = useChannel(flag, nest);
5047

5148
useEffect(() => {
5249
if (channel && !canReadChannel(channel, vessel)) {
5350
navigate('../../activity');
54-
setRecent('');
51+
setRecentChannel('');
5552
}
56-
}, [channel, vessel, navigate, setRecent]);
53+
}, [channel, vessel, navigate, setRecentChannel]);
5754

5855
const newNote = new URLSearchParams(location.search).get('new');
5956
const [showToast, setShowToast] = useState(false);
@@ -93,8 +90,8 @@ function DiaryChannel() {
9390

9491
useEffect(() => {
9592
useDiaryState.getState().initialize(chFlag);
96-
setRecent(nest);
97-
}, [chFlag, nest, setRecent]);
93+
setRecentChannel(nest);
94+
}, [chFlag, nest, setRecentChannel]);
9895

9996
useEffect(() => {
10097
let timeout: any;

ui/src/groups/GroupSidebar/ChannelList.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ export default function ChannelList({ flag, className }: ChannelListProps) {
7575
const { isChannelUnread } = useIsChannelUnread();
7676
const vessel = useVessel(flag, window.our);
7777

78-
usePrefetchChannels(flag);
79-
8078
if (!group) {
8179
return null;
8280
}

ui/src/groups/GroupSidebar/__snapshots__/ChannelList.test.tsx.snap

+6-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ exports[`ChannelList > renders as expected 1`] = `
3434
<span
3535
class="mr-2 pl-1"
3636
>
37-
Sort: A → Z
37+
Sort: Arranged
3838
</span>
3939
</span>
4040
<svg
@@ -55,7 +55,11 @@ exports[`ChannelList > renders as expected 1`] = `
5555
</div>
5656
<ul
5757
class="space-y-1"
58-
/>
58+
>
59+
<div
60+
class="space-y-1"
61+
/>
62+
</ul>
5963
</div>
6064
</DocumentFragment>
6165
`;

ui/src/groups/Groups.tsx

+2-6
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ import api from '@/api';
1111
import { useChatState } from '@/state/chat';
1212
import { useHeapState } from '@/state/heap/heap';
1313
import { useDiaryState } from '@/state/diary';
14-
import { createStorageKey, nestToFlag } from '@/logic/utils';
15-
import { useLocalStorage } from 'usehooks-ts';
1614
import { useIsMobile } from '@/logic/useMedia';
15+
import useRecentChannel from '@/logic/useRecentChannel';
1716
import _ from 'lodash';
1817

1918
function Groups() {
@@ -27,10 +26,7 @@ function Groups() {
2726
path: '/groups/:ship/:name',
2827
end: true,
2928
});
30-
const [recentChannel] = useLocalStorage(
31-
createStorageKey(`recent-chan:${flag}`),
32-
''
33-
);
29+
const { recentChannel } = useRecentChannel(flag);
3430

3531
useEffect(() => {
3632
if (initialized && !group && !gang) {

0 commit comments

Comments
 (0)