mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 16:51:42 +03:00
notifications: update header to match spec
This commit is contained in:
parent
711bb8d88c
commit
8bfb7da796
@ -1,103 +1,90 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
import f from 'lodash/fp';
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
import React, { ReactElement } from "react";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
import { Text as NormalText, Row, Rule, Box, Col } from "@tlon/indigo-react";
|
||||
|
||||
import { Text as NormalText, Row, Icon, Rule } from '@tlon/indigo-react';
|
||||
import { Associations, Contact, Contacts, Rolodex } from '@urbit/api';
|
||||
|
||||
import { PropFunc } from '~/types/util';
|
||||
import { useShowNickname } from '~/logic/lib/util';
|
||||
import Timestamp from '~/views/components/Timestamp';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
import { PropFunc } from "~/types/util";
|
||||
import Timestamp from "~/views/components/Timestamp";
|
||||
import Author from "~/views/components/Author";
|
||||
import Dot from "~/views/components/Dot";
|
||||
|
||||
const Text = (props: PropFunc<typeof Text>) => (
|
||||
<NormalText fontWeight="500" {...props} />
|
||||
);
|
||||
|
||||
function Author(props: { patp: string; last?: boolean }): ReactElement {
|
||||
const contacts = useContactState(state => state.contacts);
|
||||
const contact: Contact | undefined = contacts?.[`~${props.patp}`];
|
||||
|
||||
const showNickname = useShowNickname(contact);
|
||||
const name = showNickname ? contact.nickname : `~${props.patp}`;
|
||||
export function Header(
|
||||
props: {
|
||||
channelTitle?: string;
|
||||
groupTitle?: string;
|
||||
description: string;
|
||||
time?: number;
|
||||
authors?: string[];
|
||||
content?: boolean;
|
||||
} & PropFunc<typeof Row>
|
||||
): ReactElement {
|
||||
const {
|
||||
description,
|
||||
channelTitle = "",
|
||||
groupTitle,
|
||||
authors = [],
|
||||
content = false,
|
||||
time,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Text mono={!showNickname}>
|
||||
{name}
|
||||
{!props.last && ', '}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
export function Header(props: {
|
||||
authors: string[];
|
||||
archived?: boolean;
|
||||
channel?: string;
|
||||
group: string;
|
||||
description: string;
|
||||
moduleIcon?: string;
|
||||
time: number;
|
||||
read: boolean;
|
||||
} & PropFunc<typeof Row> ): ReactElement {
|
||||
const { description, channel, moduleIcon, read } = props;
|
||||
const associations = useMetadataState(state => state.associations);
|
||||
|
||||
const authors = _.uniq(props.authors);
|
||||
|
||||
const authorDesc = f.flow(
|
||||
f.take(3),
|
||||
f.entries,
|
||||
f.map(([idx, p]: [string, string]) => {
|
||||
const lent = Math.min(3, authors.length);
|
||||
const last = lent - 1 === parseInt(idx, 10);
|
||||
return <Author key={idx} patp={p} last={last} />;
|
||||
}),
|
||||
auths => (
|
||||
<React.Fragment>
|
||||
{auths}
|
||||
|
||||
{authors.length > 3 &&
|
||||
` and ${authors.length - 3} other${authors.length === 4 ? '' : 's'}`}
|
||||
</React.Fragment>
|
||||
)
|
||||
)(authors);
|
||||
|
||||
const time = moment(props.time).format('HH:mm');
|
||||
const groupTitle =
|
||||
associations.groups?.[props.group]?.metadata?.title;
|
||||
|
||||
const app = 'graph';
|
||||
const channelTitle =
|
||||
(channel && associations?.[app]?.[channel]?.metadata?.title) ||
|
||||
channel;
|
||||
|
||||
return (
|
||||
<Row onClick={props.onClick} p="2" flexWrap="wrap" alignItems="center" gridArea="header">
|
||||
{!props.archived && (
|
||||
<Icon
|
||||
display="block"
|
||||
opacity={read ? 0 : 1}
|
||||
mr={2}
|
||||
icon="Bullet"
|
||||
color="blue"
|
||||
/>
|
||||
)}
|
||||
<Text mr="1" mono>
|
||||
{authorDesc}
|
||||
</Text>
|
||||
<Text mr="1">{description}</Text>
|
||||
{Boolean(moduleIcon) && <Icon icon={moduleIcon as any} mr={1} />}
|
||||
{Boolean(channel) && <Text fontWeight="500" mr={1}>{channelTitle}</Text>}
|
||||
<Rule vertical height="12px" mr={1} />
|
||||
{groupTitle &&
|
||||
<>
|
||||
<Text fontWeight="500" mr={1}>{groupTitle}</Text>
|
||||
<Rule vertical height="12px" mr={1} />
|
||||
</>
|
||||
}
|
||||
<Timestamp stamp={moment(props.time)} color="lightGray" date={false} />
|
||||
<Row
|
||||
flexDirection={["column-reverse", "row"]}
|
||||
minHeight="4"
|
||||
mb={content ? 2 : 0}
|
||||
onClick={props.onClick}
|
||||
flexWrap="wrap"
|
||||
alignItems={["flex-start", "center"]}
|
||||
gridArea="header"
|
||||
overflow="hidden"
|
||||
>
|
||||
<Row gapX="1" overflow="hidden" alignItems="center">
|
||||
{authors.length > 0 && (
|
||||
<>
|
||||
<Author
|
||||
flexShrink={0}
|
||||
sigilPadding={6}
|
||||
size={24}
|
||||
dontShowTime
|
||||
date={time}
|
||||
ship={authors[0]}
|
||||
showImage
|
||||
/>
|
||||
{authors.length > 1 && (
|
||||
<Text lineHeight="tall">+ {authors.length - 1} more</Text>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Box whiteSpace="nowrap" overflow="hidden" textOverflow="ellipsis">
|
||||
<Text lineHeight="tall" mr="1">
|
||||
{description} {channelTitle}
|
||||
</Text>
|
||||
</Box>
|
||||
</Row>
|
||||
<Row ml={[0, 1]} mb={[1, 0]} gapX="1" alignItems="center">
|
||||
{groupTitle && (
|
||||
<>
|
||||
<Text lineHeight="tall" fontSize="1" gray>
|
||||
{groupTitle}
|
||||
</Text>
|
||||
<Dot color="gray" />
|
||||
</>
|
||||
)}
|
||||
{time && (
|
||||
<Timestamp
|
||||
lineHeight="tall"
|
||||
fontSize="1"
|
||||
relative
|
||||
stamp={moment(time)}
|
||||
color="gray"
|
||||
date={false}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user