notifications: surface pending DMs

This commit is contained in:
Liam Fitzgerald 2021-05-03 16:12:48 +10:00
parent bdf40b9deb
commit c21151bde7
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
4 changed files with 85 additions and 19 deletions

View File

@ -0,0 +1,57 @@
import React, { useCallback } from 'react';
import { Box, Col, Row, Text } from '@tlon/indigo-react';
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
import Author from '~/views/components/Author';
import GlobalApi from '~/logic/api/global';
import { useHistory } from 'react-router';
export function PendingDm(props: { ship: string; api: GlobalApi }) {
const { ship, api } = props;
const { push } = useHistory();
const onAccept = useCallback(async () => {
await api.graph.acceptDm(ship);
push(`/~landscape/messages/dm/${ship}`);
}, [ship, push, api]);
const onDecline = useCallback(async () => {
await api.graph.declineDm(ship);
}, [ship, api]);
return (
<Box
display="grid"
bg="washedGray"
borderRadius="2"
gridTemplateColumns={['1fr 24px', '1fr 200px']}
gridTemplateRows="auto"
gridTemplateAreas="'header actions' 'main main'"
p={2}
m={2}
>
<Row alignItems="center" gridArea="header">
<Author ship={ship} />
<Text ml="1" lineHeight="tall">
invited you to a DM
</Text>
</Row>
<Row
alignItems="center"
gapX="2"
gridArea="actions"
justifyContent="flex-end"
>
<StatelessAsyncAction height="auto" primary p="1" onClick={onAccept}>
Accept
</StatelessAsyncAction>
<StatelessAsyncAction
height="auto"
destructive
p="1"
onClick={onDecline}
>
Decline
</StatelessAsyncAction>
</Row>
</Box>
);
}

View File

@ -286,19 +286,22 @@ export function GraphNotification(props: {
const authors = _.uniq(_.map(contents, "author"));
const singleAuthor = authors.length === 1;
const { graph, group } = index;
const association = useAssocForGraph(graph)!;
const dm = isDm(graph);
const { graph, mark } = index;
const association = useAssocForGraph(graph);
const dm = mark === 'graph-validator-dm';
const desc = describeNotification(
index.description,
contents.length !== 1,
dm,
singleAuthor
);
const groupAssociation = useAssocForGroup(association?.group);
const groupAssociation = useAssocForGroup(association?.group ?? "");
const groups = useGroupState((state) => state.groups);
const onClick = useCallback(() => {
if(!association) {
history.push(`/~landscape/messages/dm/~${authors[0]}`);
}
if (
!(
(index.description === "note" || index.description === "link") &&
@ -343,7 +346,7 @@ export function GraphNotification(props: {
<GraphNodes
hideAuthors={hideAuthors}
posts={contents.slice(0, 4)}
mod={index.module}
mod={index.mark}
description={index.description}
index={contents?.[0].index}
association={association}

View File

@ -1,7 +1,7 @@
import React, { ReactElement, ReactNode } from 'react';
import _ from 'lodash';
import { Col, Box, Text } from '@tlon/indigo-react';
import { Col, Box, Text, Row } from '@tlon/indigo-react';
import {
Invites as IInvites,
Associations,
@ -11,7 +11,7 @@ import {
Contacts,
AppInvites,
JoinProgress,
JoinRequest
JoinRequest,
} from '@urbit/api';
import GlobalApi from '~/logic/api/global';
@ -19,6 +19,8 @@ import { resourceAsPath, alphabeticalOrder } from '~/logic/lib/util';
import InviteItem from '~/views/components/Invite';
import useInviteState from '~/logic/state/invite';
import useGroupState from '~/logic/state/group';
import useGraphState from '~/logic/state/graph';
import {PendingDm} from './PendingDm';
interface InvitesProps {
api: GlobalApi;
@ -33,7 +35,9 @@ interface InviteRef {
export function Invites(props: InvitesProps): ReactElement {
const { api } = props;
const invites = useInviteState(state => state.invites);
const invites = useInviteState((state) => state.invites);
const pendingDms = useGraphState((s) => s.pendingDms);
const inviteArr: InviteRef[] = _.reduce(
invites,
@ -54,24 +58,27 @@ export function Invites(props: InvitesProps): ReactElement {
const invitesAndStatus: { [rid: string]: JoinRequest | InviteRef } = {
..._.keyBy(inviteArr, ({ invite }) => resourceAsPath(invite.resource)),
...pendingJoin
...pendingJoin,
};
return (
<>
{[...pendingDms].map((ship) => (
<PendingDm key={ship} api={api} ship={`~${ship}`} />
))}
{Object.keys(invitesAndStatus)
.sort(alphabeticalOrder)
.map((resource) => {
const inviteOrStatus = invitesAndStatus[resource];
const join = pendingJoin[resource];
if ('progress' in inviteOrStatus) {
return (
<InviteItem
key={resource}
resource={resource}
api={api}
pendingJoin={join}
/>
return (
<InviteItem
key={resource}
resource={resource}
api={api}
pendingJoin={join}
/>
);
} else {
const { app, uid, invite } = inviteOrStatus;
@ -86,8 +93,7 @@ export function Invites(props: InvitesProps): ReactElement {
/>
);
}
})
}
})}
</>
);
}

View File

@ -5,7 +5,7 @@ import { LoadingSpinner, Action } from '@tlon/indigo-react';
interface AsyncActionProps {
children: ReactNode;
name: string;
name?: string;
disabled?: boolean;
onClick: (e: React.MouseEvent) => Promise<void>;
}