From c21151bde7c315175a489b23daed9b84dd620025 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Mon, 3 May 2021 16:12:48 +1000 Subject: [PATCH] notifications: surface pending DMs --- .../views/apps/notifications/PendingDm.tsx | 57 +++++++++++++++++++ .../src/views/apps/notifications/graph.tsx | 13 +++-- .../src/views/apps/notifications/invites.tsx | 32 ++++++----- .../views/components/StatelessAsyncAction.tsx | 2 +- 4 files changed, 85 insertions(+), 19 deletions(-) create mode 100644 pkg/interface/src/views/apps/notifications/PendingDm.tsx diff --git a/pkg/interface/src/views/apps/notifications/PendingDm.tsx b/pkg/interface/src/views/apps/notifications/PendingDm.tsx new file mode 100644 index 000000000..fa4646a73 --- /dev/null +++ b/pkg/interface/src/views/apps/notifications/PendingDm.tsx @@ -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 ( + + + + + invited you to a DM + + + + + Accept + + + Decline + + + + ); +} diff --git a/pkg/interface/src/views/apps/notifications/graph.tsx b/pkg/interface/src/views/apps/notifications/graph.tsx index cb3242477..135d73fe4 100644 --- a/pkg/interface/src/views/apps/notifications/graph.tsx +++ b/pkg/interface/src/views/apps/notifications/graph.tsx @@ -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: { 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) => ( + + ))} {Object.keys(invitesAndStatus) .sort(alphabeticalOrder) .map((resource) => { const inviteOrStatus = invitesAndStatus[resource]; const join = pendingJoin[resource]; if ('progress' in inviteOrStatus) { - return ( - + return ( + ); } else { const { app, uid, invite } = inviteOrStatus; @@ -86,8 +93,7 @@ export function Invites(props: InvitesProps): ReactElement { /> ); } - }) - } + })} ); } diff --git a/pkg/interface/src/views/components/StatelessAsyncAction.tsx b/pkg/interface/src/views/components/StatelessAsyncAction.tsx index 68ab25f63..74f08d3c8 100644 --- a/pkg/interface/src/views/components/StatelessAsyncAction.tsx +++ b/pkg/interface/src/views/components/StatelessAsyncAction.tsx @@ -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; }