DM: lazy loading, status bar

This commit is contained in:
Liam Fitzgerald 2021-05-03 13:20:05 +10:00
parent 772a134108
commit 5b317e8af1
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
4 changed files with 116 additions and 18 deletions

View File

@ -69,6 +69,17 @@ export class HarkApi extends BaseApi<StoreState> {
return this.actOnNotification('unread-note', time, index); return this.actOnNotification('unread-note', time, index);
} }
dismissReadCount(graph: string, index: string) {
return this.harkAction({
'read-count': {
graph: {
graph,
index
}
}
});
}
markCountAsRead(association: Association, parent: string, description: GraphNotifDescription) { markCountAsRead(association: Association, parent: string, description: GraphNotifDescription) {
return this.harkAction( return this.harkAction(
{ 'read-count': { { 'read-count': {

View File

@ -98,7 +98,7 @@ class App extends React.Component {
componentDidMount() { componentDidMount() {
this.subscription.start(); this.subscription.start();
this.api.graph.getGraph(`~${window.ship}`, 'inbox'); this.api.graph.getShallowChildren(`~${window.ship}`, 'inbox');
this.themeWatcher = window.matchMedia('(prefers-color-scheme: dark)'); this.themeWatcher = window.matchMedia('(prefers-color-scheme: dark)');
this.themeWatcher.onchange = this.updateTheme; this.themeWatcher.onchange = this.updateTheme;
setTimeout(() => { setTimeout(() => {

View File

@ -1,20 +1,81 @@
import { Content, createPost } from '@urbit/api'; import { cite, Content, createPost } from '@urbit/api';
import React, { useCallback } from 'react'; import React, { useCallback, useEffect } from 'react';
import bigInt from 'big-integer';
import { Box, Row, Col, Text } from '@tlon/indigo-react';
import { patp2dec } from 'urbit-ob'; import { patp2dec } from 'urbit-ob';
import GlobalApi from '~/logic/api/global'; import GlobalApi from '~/logic/api/global';
import { useDM } from '~/logic/state/graph'; import { useContact } from '~/logic/state/contact';
import useGraphState, { useDM } from '~/logic/state/graph';
import useHarkState, { useHarkDm } from '~/logic/state/hark'; import useHarkState, { useHarkDm } from '~/logic/state/hark';
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
import { ChatPane } from './components/ChatPane'; import { ChatPane } from './components/ChatPane';
interface DmResourceProps { interface DmResourceProps {
ship: string; ship: string;
api: GlobalApi; api: GlobalApi;
} }
const getCurrDmSize = (ship: string) => {
const { graphs } = useGraphState.getState();
const graph = graphs[`${window.ship}/inbox`];
if (!graph) {
return 0;
}
const shipGraph = graph.get(bigInt(patp2dec(ship)));
return shipGraph?.children?.size ?? 0;
};
export function DmResource(props: DmResourceProps) { export function DmResource(props: DmResourceProps) {
const { ship, api } = props; const { ship, api } = props;
const dm = useDM(ship); const dm = useDM(ship);
const hark = useHarkDm(ship); const hark = useHarkDm(ship);
const unreadCount = (hark?.unreads as number) ?? 0; const unreadCount = (hark?.unreads as number) ?? 0;
const contact = useContact(ship);
const { hideNicknames } = useSettingsState(selectCalmState);
const showNickname = !hideNicknames && !!contact;
const nickname = showNickname ? contact!.nickname : cite(ship) ?? ship;
useEffect(() => {
api.graph.getNewest(`~${window.ship}`, 'inbox', 100, `/${patp2dec(ship)}`);
}, [ship]);
const fetchMessages = useCallback(
async (newer: boolean) => {
const pageSize = 100;
const expectedSize = dm.size + pageSize;
if (newer) {
const index = dm.peekLargest()?.[0];
if (!index) {
return true;
}
await api.graph.getYoungerSiblings(
`~${window.ship}`,
'inbox',
pageSize,
`/${patp2dec(ship)}/${index.toString()}`
);
return expectedSize !== getCurrDmSize(ship);
} else {
const index = dm.peekSmallest()?.[0];
if (!index) {
return true;
}
await api.graph.getOlderSiblings(
`~${window.ship}`,
'inbox',
pageSize,
`/${patp2dec(ship)}/${index.toString()}`
);
return expectedSize !== getCurrDmSize(ship);
}
},
[ship, dm, api]
);
const dismissUnread = useCallback(() => {
api.hark.dismissReadCount(`/ship/~${window.ship}/inbox`, `/${patp2dec(ship)}`);
}, [ship]);
const onSubmit = useCallback( const onSubmit = useCallback(
(contents: Content[]) => { (contents: Content[]) => {
@ -24,18 +85,44 @@ export function DmResource(props: DmResourceProps) {
); );
return ( return (
<ChatPane <Col width="100%" height="100%" overflow="hidden">
api={api} <Row
canWrite px="3"
id={ship} gapX="3"
graph={dm} flexShrink={0}
unreadCount={unreadCount} alignItems="center"
onReply={() => ''} height="6"
fetchMessages={async () => true} borderBottom="1"
dismissUnread={() => {}} borderBottomColor="lightGray"
getPermalink={() => ''} >
isAdmin <Row gapX="2" alignItems="baseline">
onSubmit={onSubmit} {showNickname && (
/> <Box>
<Text fontWeight="medium" fontSize={2} mono={!showNickname}>
{nickname}
</Text>
</Box>
)}
<Box>
<Text gray={showNickname} mono>
{cite(ship)}
</Text>
</Box>
</Row>
</Row>
<ChatPane
api={api}
canWrite
id={ship}
graph={dm}
unreadCount={unreadCount}
onReply={() => ''}
fetchMessages={fetchMessages}
dismissUnread={dismissUnread}
getPermalink={() => ''}
isAdmin
onSubmit={onSubmit}
/>
</Col>
); );
} }

View File

@ -111,7 +111,7 @@ export function SidebarDmItem(props: {
const img = (contact?.avatar && !hideAvatars) ? ( const img = (contact?.avatar && !hideAvatars) ? (
<BaseImage referrerPolicy="no-referrer" src={contact.avatar} width='16px' height='16px' borderRadius={2} /> <BaseImage referrerPolicy="no-referrer" src={contact.avatar} width='16px' height='16px' borderRadius={2} />
) : ( ) : (
<Sigil ship={title} color={`#${uxToHex(contact?.color || '0x0')}`} icon padding={2} size={16} /> <Sigil ship={ship} color={`#${uxToHex(contact?.color || '0x0')}`} icon padding={2} size={16} />
); );
return ( return (