interface: build in mentions FE support

This commit is contained in:
Liam Fitzgerald 2020-11-03 16:12:34 +10:00
parent 26f2e9e951
commit 94f787d120
5 changed files with 101 additions and 13 deletions

View File

@ -3,10 +3,10 @@ import { StoreState } from '../store/type';
import { Patp, Path, PatpNoSig } from '~/types/noun';
import _ from 'lodash';
import {makeResource, resourceFromPath} from '../lib/group';
import {GroupPolicy, Enc, Post, NodeMap} from '~/types';
import {GroupPolicy, Enc, Post, NodeMap, Content} from '~/types';
import { numToUd, unixToDa } from '~/logic/lib/util';
export const createPost = (contents: Object[], parentIndex: string = '') => {
export const createPost = (contents: Content[], parentIndex: string = '') => {
return {
author: `~${window.ship}`,
index: parentIndex + '/' + unixToDa(Date.now()).toString(),

View File

@ -0,0 +1,24 @@
import { Content } from "~/types";
import urbitOb from "urbit-ob";
export function scanForMentions(text: string) {
const regex = /~([a-z]|-)+/g;
let result: Content[] = [];
let match: RegExpExecArray | null;
let lastPos = 0;
while ((match = regex.exec(text)) !== null) {
const newPos = match.index + match[0].length;
if (urbitOb.isValidPatp(match[0])) {
if (match.index !== lastPos) {
result.push({ text: text.slice(lastPos, match.index) });
}
result.push({ mention: match[0] });
}
lastPos = newPos;
}
const remainder = text.slice(lastPos, text.length);
if (remainder) {
result.push({ text: remainder });
}
return result;
}

View File

@ -1,12 +1,28 @@
import { Patp } from "./noun";
import { BigIntOrderedMap } from "~/logic/lib/BigIntOrderedMap";
export interface TextContent { text: string; };
export interface UrlContent { url: string; }
export interface CodeContent { expresssion: string; output: string; };
export interface ReferenceContent { uid: string; }
export type Content = TextContent | UrlContent | CodeContent | ReferenceContent;
export interface TextContent {
text: string;
}
export interface UrlContent {
url: string;
}
export interface CodeContent {
expresssion: string;
output: string;
}
export interface ReferenceContent {
uid: string;
}
export interface MentionContent {
mention: string;
}
export type Content =
| TextContent
| UrlContent
| CodeContent
| ReferenceContent
| MentionContent;
export interface Post {
author: Patp;
@ -15,10 +31,9 @@ export interface Post {
index: string;
pending?: boolean;
signatures: string[];
'time-sent': number;
"time-sent": number;
}
export interface GraphNode {
children: Graph;
post: Post;
@ -27,5 +42,3 @@ export interface GraphNode {
export type Graph = BigIntOrderedMap<GraphNode>;
export type Graphs = { [rid: string]: Graph };

View File

@ -0,0 +1,51 @@
import React from "react";
import _ from "lodash";
import { Text } from "@tlon/indigo-react";
import { Contacts, Content, LocalUpdateRemoteContentPolicy } from "~/types";
import RichText from "~/views/components/RichText";
import { cite } from "~/logic/lib/util";
interface MentionTextProps {
contacts: Contacts;
content: Content[];
remoteContentPolicy: LocalUpdateRemoteContentPolicy;
}
export function MentionText(props: MentionTextProps) {
const { content, contacts } = props;
return (
<>
{_.map(content, (c, idx) => {
if ("text" in c) {
return (
<RichText
inline
key={idx}
remoteContentPolicy={props.remoteContentPolicy}
>
{c.text}
</RichText>
);
} else if ("mention" in c) {
return (
<Mention key={idx} contacts={contacts || {}} ship={c.mention} />
);
}
return null;
})}
</>
);
}
function Mention(props: { ship: string; contacts: Contacts }) {
const { contacts, ship } = props;
const contact = contacts[ship];
const showNickname = !!contact?.nickname;
const name = showNickname ? contact?.nickname : cite(ship);
return (
<Text mx="2px" px="2px" bg="washedBlue" color="blue" mono={!showNickname}>
{name}
</Text>
);
}

View File

@ -30,7 +30,7 @@ const RichText = React.memo(({ remoteContentPolicy, ...props }) => (
return <BaseAnchor target='_blank' rel='noreferrer noopener' borderBottom='1px solid' {...props}>{props.children}</BaseAnchor>;
},
paragraph: (paraProps) => {
return <Text display='block' mb='2' {...props}>{paraProps.children}</Text>;
return <Text display={props.inline ? 'inline' : 'block'} mb='2' {...props}>{paraProps.children}</Text>;
}
}}
plugins={[[