Merge branch 'release/next-userspace' into la/feed-perf

This commit is contained in:
Logan Allen 2021-03-29 13:39:57 -05:00
commit bf49fd81f9
18 changed files with 153 additions and 45 deletions

View File

@ -193,6 +193,11 @@
(~(put by joining) rid [%.n now.bowl ship %start])
=. jn-core
(jn-abed rid)
=. jn-core
%- emit
%+ fact:io
group-view-update+!>([%started rid (~(got by joining) rid)])
~[/all]
?< ~|("already joined {<rid>}" (has-joined rid))
=. jn-core
%- emit

View File

@ -54,9 +54,17 @@
?- -.upd
%initial (initial +.upd)
%progress (progress +.upd)
%started (started +.upd)
%hide s+(enjs-path:resource +.upd)
==
::
++ started
|= [rid=resource req=^request]
%- pairs
:~ resource+s+(enjs-path:resource rid)
request+(request req)
==
::
++ progress
|= [rid=resource prog=^progress]
%- pairs

View File

@ -52,7 +52,7 @@
:: top-level link post; title and url
::
[@ ~]
?> ?=([[%text @] [%url @] ~] contents.p.ip)
?> ?=([[%text @] $%([%url @] [%reference *]) ~] contents.p.ip)
ip
::
:: comment on link post; container structure

View File

@ -12,10 +12,11 @@
++ graph-permissions-remove
|= vip=vip-metadata:met
[%yes %self %self]
:: +notification-kind: no notifications for now
:: +notification-kind: don't track unreads, notify on replies
::
++ notification-kind
=/ len (lent index.p.i)
?: =(1 len) ~
`[%post [(dec len) len] %none %children]
::
++ transform-add-nodes

View File

@ -31,6 +31,7 @@
::
+$ update
$% [%initial initial=(map resource request)]
[%started =resource =request]
[%progress =resource =progress]
[%hide =resource]
==

View File

@ -308,10 +308,8 @@ export default class GraphApi extends BaseApi<StoreState> {
}
getGraph(ship: string, resource: string) {
console.log(ship, resource);
return this.scry<any>('graph-store', `/graph/${ship}/${resource}`)
.then((graph) => {
console.log(graph);
this.store.handleEvent({
data: graph
});

View File

@ -11,12 +11,22 @@ const initial = (json: any, state: GroupState): GroupState => {
return state;
};
const started = (json: any, state: GroupState): GroupState => {
const data = json.started;
if(data) {
const { resource, request } = data;
state.pendingJoin[resource] = request;
}
return state;
}
const progress = (json: any, state: GroupState): GroupState => {
const data = json.progress;
if(data) {
const { progress, resource } = data;
state.pendingJoin[resource].progress = progress;
if(progress === 'done') {
setTimeout(() => {
delete state.pendingJoin[resource];
}, 10000);
@ -40,6 +50,7 @@ export const GroupViewReducer = (json: any) => {
reduceState<GroupState, GroupUpdate>(useGroupState, data, [
progress,
hide,
started,
initial
]);
}

View File

@ -144,7 +144,6 @@ export default class ChatEditor extends Component {
messageChange(editor, data, value) {
if(value.endsWith('/')) {
console.log('showing');
editor.showHint(['test', 'foo']);
}
if (this.state.message !== '' && value == '') {

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect, useRef, useCallback, ReactElement } from 'react';
import { Link } from 'react-router-dom';
import { Row, Col, Anchor, Box, Text, Icon, Action } from '@tlon/indigo-react';
import { Row, Col, Anchor, Box, Text, Icon, Action, Rule } from '@tlon/indigo-react';
import { GraphNode, Group, Rolodex, Unreads, Association } from '@urbit/api';
import { writeText } from '~/logic/lib/util';
@ -12,7 +12,8 @@ import { Dropdown } from '~/views/components/Dropdown';
import RemoteContent from '~/views/components/RemoteContent';
import useHarkState from '~/logic/state/hark';
import {useCopy} from '~/logic/lib/useCopy';
import {usePermalinkForGraph, getPermalinkForGraph} from '~/logic/lib/permalinks';
import {usePermalinkForGraph, getPermalinkForGraph, referenceToPermalink} from '~/logic/lib/permalinks';
import {PermalinkEmbed} from '../../permalinks/embed';
interface LinkItemProps {
node: GraphNode;
@ -78,11 +79,12 @@ export const LinkItem = (props: LinkItemProps): ReactElement => {
const { doCopy: doCopyLink, copyDisplay: locationText } = useCopy(
contents[1].url,
'Copy Link Location'
'Copy block source'
);
const { doCopy: doCopyNode, copyDisplay: nodeText } = useCopy(
permalink,
'Copy Node Permalink'
'Copy reference'
);
const deleteLink = () => {
@ -119,6 +121,13 @@ export const LinkItem = (props: LinkItemProps): ReactElement => {
onClick={markRead}
>
<Text p={2}>{contents[0].text}</Text>
{ 'reference' in contents[1] ? (
<>
<Rule />
<PermalinkEmbed full link={referenceToPermalink(contents[1]).link} api={api} transcluded={0} />
</>
) : (
<>
<RemoteContent
ref={r => { remoteRef.current = r }}
renderUrl={false}
@ -146,12 +155,14 @@ export const LinkItem = (props: LinkItemProps): ReactElement => {
}}
/>
<Text color="gray" p={2} flexShrink={0}>
<Anchor target="_blank" rel="noopener noreferrer" style={{ textDecoration: 'none' }} href={href}>
<Box display='flex'>
<Icon icon='ArrowExternal' mr={1} />{hostname}
</Box>
</Anchor>
</Text>
<Anchor target="_blank" rel="noopener noreferrer" style={{ textDecoration: 'none' }} href={href}>
<Box display='flex'>
<Icon icon='ArrowExternal' mr={1} />{hostname}
</Box>
</Anchor>
</Text>
</>
)}
</Box>
<Row minWidth='0' flexShrink={0} width="100%" justifyContent="space-between" py={3} bg="white">
<Author

View File

@ -7,6 +7,7 @@ import { StorageState } from '~/types';
import SubmitDragger from '~/views/components/SubmitDragger';
import { createPost } from '~/logic/api/graph';
import { hasProvider } from 'oembed-parser';
import {parsePermalink, permalinkToReference} from '~/logic/lib/permalinks';
interface LinkSubmitProps {
api: GlobalApi;
@ -28,12 +29,13 @@ const LinkSubmit = (props: LinkSubmitProps) => {
const doPost = () => {
const url = linkValue;
const text = linkTitle ? linkTitle : linkValue;
const contents = url.startsWith('web+urbitgraph:/')
? [{ text }, permalinkToReference(parsePermalink(url)!) ]
: [{ text }, { url }];
setDisabled(true);
const parentIndex = props.parentIndex || '';
const post = createPost([
{ text },
{ url }
], parentIndex);
const post = createPost(contents, parentIndex);
props.api.graph.addPost(
`~${props.ship}`,
@ -61,6 +63,13 @@ const LinkSubmit = (props: LinkSubmitProps) => {
setLinkValue(link);
}
}
if(link.startsWith('web+urbitgraph://')) {
const permalink = parsePermalink(link);
if(!permalink) {
setLinkValid(false);
return;
}
}
if (linkValid) {
if (hasProvider(linkValue)) {

View File

@ -21,6 +21,8 @@ import ChatMessage from '../chat/components/ChatMessage';
import useContactState from '~/logic/state/contact';
import useGroupState from '~/logic/state/group';
import useMetadataState from '~/logic/state/metadata';
import {PermalinkEmbed} from '../permalinks/embed';
import {parsePermalink, referenceToPermalink} from '~/logic/lib/permalinks';
function getGraphModuleIcon(module: string) {
if (module === 'link') {
@ -63,14 +65,27 @@ function describeNotification(description: string, plural: boolean): string {
}
}
const GraphUrl = ({ url, title }) => (
<Box borderRadius='2' p='2' bg='scales.black05'>
<Anchor underline={false} target='_blank' color='black' href={url}>
<Icon verticalAlign='bottom' mr='2' icon='ArrowExternal' />
{title}
</Anchor>
</Box>
);
const GraphUrl = ({ contents, api }) => {
const [{ text }, link] = contents;
if('reference' in link) {
return (
<PermalinkEmbed
transcluded={1}
link={referenceToPermalink(link).link}
api={api}
/>);
}
return (
<Box borderRadius='2' p='2' bg='scales.black05'>
<Anchor underline={false} target='_blank' color='black' href={link.url}>
<Icon verticalAlign='bottom' mr='2' icon='ArrowExternal' />
{text}
</Anchor>
</Box>
);
}
export const GraphNodeContent = ({
group,
@ -83,8 +98,7 @@ export const GraphNodeContent = ({
const idx = index.slice(1).split('/');
if (mod === 'link') {
if (idx.length === 1) {
const [{ text }, { url }] = contents;
return <GraphUrl title={text} url={url} />;
return <GraphUrl contents={contents} />;
} else if (idx.length === 3) {
return <MentionText content={contents} group={group} />;
}
@ -172,7 +186,7 @@ function getNodeUrl(
return `${graphUrl}/note/${noteId}`;
} else if (mod === 'link') {
const [linkId] = idx;
return `${graphUrl}/${linkId}`;
return `${graphUrl}/index/${linkId}`;
} else if (mod === 'chat') {
if(idx.length > 0) {
return `${graphUrl}?msg=${idx[0]}`;

View File

@ -89,6 +89,7 @@ export function Invites(props: InvitesProps): ReactElement {
invite={invite}
app={app}
uid={uid}
join={join}
resource={resource}
/>
);

View File

@ -14,6 +14,7 @@ import GroupSearch from '~/views/components/GroupSearch';
import { useTutorialModal } from '~/views/components/useTutorialModal';
import useHarkState from '~/logic/state/hark';
import useMetadataState from '~/logic/state/metadata';
import useGroupState from '~/logic/state/group';
const baseUrl = '/~notifications';
@ -41,6 +42,7 @@ export default function NotificationsScreen(props: any): ReactElement {
const [filter, setFilter] = useState<NotificationFilter>({ groups: [] });
const associations = useMetadataState(state => state.associations);
const pendingJoin = useGroupState(s => s.pendingJoin);
const onSubmit = async ({ groups } : NotificationFilter) => {
setFilter({ groups });
};
@ -128,7 +130,11 @@ export default function NotificationsScreen(props: any): ReactElement {
</Dropdown>
</Row>
</Row>
{!view && <Inbox {...props} filter={filter.groups} />}
{!view && <Inbox
pendingJoin={pendingJoin}
{...props}
filter={filter.groups}
/>}
</Col>
</Body>
</>

View File

@ -1,15 +1,18 @@
import React from "react";
import { Anchor, Icon, Box, Row, Col, Text } from "@tlon/indigo-react";
import ChatMessage from "../chat/components/ChatMessage";
import { Association, GraphNode } from "@urbit/api";
import { Association, GraphNode, Post, Group } from "@urbit/api";
import { useGroupForAssoc } from "~/logic/state/group";
import { MentionText } from "~/views/components/MentionText";
import Author from "~/views/components/Author";
import { NoteContent } from "../publish/components/Note";
import { PostContent } from "~/views/landscape/components/Home/Post/PostContent";
import bigInt from "big-integer";
import { getSnippet } from "~/logic/lib/publish";
import { NotePreviewContent } from "../publish/components/NotePreview";
import GlobalApi from "~/logic/api/global";
import {PermalinkEmbed} from "./embed";
import {referenceToPermalink} from "~/logic/lib/permalinks";
function TranscludedLinkNode(props: {
node: GraphNode;
@ -22,10 +25,16 @@ function TranscludedLinkNode(props: {
switch (idx.length) {
case 1:
const [{ text }, { url }] = node.post.contents;
const [{ text }, link] = node.post.contents;
if('reference' in link) {
const permalink = referenceToPermalink(link).link;
return <PermalinkEmbed transcluded={transcluded + 1} api={api} link={permalink} association={assoc} />
}
return (
<Box borderRadius="2" p="2" bg="scales.black05">
<Anchor underline={false} target="_blank" color="black" href={url}>
<Anchor underline={false} target="_blank" color="black" href={link.url}>
<Icon verticalAlign="bottom" mr="2" icon="ArrowExternal" />
{text}
</Anchor>
@ -124,6 +133,34 @@ function TranscludedPublishNode(props: {
}
}
export function TranscludedPost(props: {
post: Post;
api: GlobalApi;
transcluded: number;
group: Group;
}) {
const { transcluded, post, group, api } = props;
return (
<Col>
<Author
p="2"
showImage
ship={post.author}
date={post?.["time-sent"]}
group={group}
/>
<Box p="2">
<MentionText
api={api}
transcluded={transcluded}
content={post.contents}
group={group}
/>
</Box>
</Col>
);
}
export function TranscludedNode(props: {
assoc: Association;
node: GraphNode;
@ -158,6 +195,15 @@ export function TranscludedNode(props: {
return <TranscludedPublishNode {...props} />;
case "link":
return <TranscludedLinkNode {...props} />;
case "post":
return (
<TranscludedPost
api={props.api}
post={node.post}
group={group}
transcluded={transcluded}
/>)
;
default:
return null;
}

View File

@ -29,13 +29,11 @@ export function PermalinkRoutes(props: {}) {
path="/perma/group/:ship/:name"
render={({ match, history, location }) => {
const { ship, name } = match.params as ResourceRouteProps;
console.log(ship);
const { url } = match;
const path = `/ship/${ship}/${name}`;
const group = groups[path];
if(!group) {
if (Object.keys(groups).length > 0) {
console.log(groups);
const redir = location.pathname;
const to = toQuery({ redir }, `/~landscape/join/${ship}/${name}`);
return <Redirect to={to} />;
@ -60,7 +58,6 @@ function FallbackRoutes(props: { query: URLSearchParams }) {
return <Redirect to={{ pathname: url }} />;
}
console.log('aaaaa');
return <Redirect to="/~404" />;
}
@ -71,7 +68,6 @@ function GroupRoutes(props: { group: string; url: string }) {
const graphKeys = useGraphState(s => s.graphKeys);
const { toQuery } = useQuery();
const groupUrl = `/~landscape${group}`;
console.log(group);
return (
<Switch>
@ -85,7 +81,6 @@ function GroupRoutes(props: { group: string; url: string }) {
if(!association) {
return null;
}
console.log(graphKeys);
if(!graphKeys.has(`${ship.slice(1)}/${name}`)) {
if(graphKeys.size > 0) {
return <Redirect

View File

@ -44,9 +44,10 @@ function GraphPermalink(
transcluded: number;
pending?: boolean;
showOurContact?: boolean;
full?: boolean;
}
) {
const { showOurContact, pending, link, graph, group, index, api, transcluded } = props;
const { full = false, showOurContact, pending, link, graph, group, index, api, transcluded } = props;
const { ship, name } = resourceFromPath(graph);
const node = useGraphState(
useCallback((s) => s.looseNodes?.[`${ship.slice(1)}/${name}`]?.[index], [
@ -79,10 +80,9 @@ function GraphPermalink(
return (
<Col
width="100%"
my="1"
bg="white"
maxWidth="500px"
border="1"
maxWidth={full ? null : "500px"}
border={full ? null : "1"}
borderColor="lightGray"
borderRadius="2"
onClick={(e) => { e.stopPropagation(); }}
@ -161,6 +161,7 @@ export function PermalinkEmbed(props: {
api: GlobalApi;
transcluded: number;
showOurContact?: boolean;
full?: boolean;
}) {
const permalink = parsePermalink(props.link);
@ -177,6 +178,7 @@ export function PermalinkEmbed(props: {
transcluded={props.transcluded}
{...permalink}
api={props.api}
full={props.full}
showOurContact={props.showOurContact}
/>
);

View File

@ -108,7 +108,7 @@ export function InviteItem(props: InviteItemProps) {
}
}, [invite]);
if(status?.hidden) {
if(pendingJoin?.hidden) {
return null;
}
@ -119,7 +119,7 @@ export function InviteItem(props: InviteItemProps) {
api={api}
preview={preview}
invite={invite}
status={status}
status={pendingJoin}
{...handlers}
/>
);

View File

@ -19,6 +19,7 @@ export function PostContent(props) {
contacts={contacts}
content={post.contents}
api={api}
transcluded={0}
/>
</Col>
);