mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-24 15:34:10 +03:00
interface: pending graph updates
This commit is contained in:
parent
2d40d0655b
commit
276e2c2fa4
@ -24,7 +24,7 @@ export const bootstrapApi = async () => {
|
||||
})();
|
||||
};
|
||||
|
||||
airlock.onRetry = (e) => {
|
||||
airlock.onRetry = () => {
|
||||
useLocalState.setState({ subscription: 'reconnecting' });
|
||||
};
|
||||
|
||||
|
@ -152,6 +152,9 @@ function unreads(json: any, state: HarkState): HarkState {
|
||||
data.forEach(({ index, stats }) => {
|
||||
const { unreads, notifications, last } = stats;
|
||||
updateNotificationStats(state, index, 'last', () => last);
|
||||
if(index.graph.graph === '/ship/~hastuc-dibtux/test-book-7531') {
|
||||
console.log(index, stats);
|
||||
}
|
||||
_.each(notifications, ({ time, index }) => {
|
||||
if(!time) {
|
||||
addNotificationToUnread(state, index);
|
||||
@ -197,6 +200,9 @@ function updateUnreadCount(state: HarkState, index: NotifIndex, count: (c: numbe
|
||||
}
|
||||
const property = [index.graph.graph, index.graph.index, 'unreads'];
|
||||
const curr = _.get(state.unreads.graph, property, 0);
|
||||
if(typeof curr !== 'number') {
|
||||
return state;
|
||||
}
|
||||
const newCount = count(curr);
|
||||
_.set(state.unreads.graph, property, newCount);
|
||||
return state;
|
||||
|
@ -5,7 +5,7 @@ import { Association, deSig, GraphNode, Graphs, FlatGraphs, resourceFromPath, Th
|
||||
import { useCallback } from 'react';
|
||||
import { createState, createSubscription, reduceStateN } from './base';
|
||||
import airlock from '~/logic/api';
|
||||
import { getDeepOlderThan, getFirstborn, getNewest, getNode, getOlderSiblings, getYoungerSiblings } from '@urbit/api/graph';
|
||||
import { addDmMessage, addPost, Content, getDeepOlderThan, getFirstborn, getNewest, getNode, getOlderSiblings, getYoungerSiblings, markPending, Post, addNode, GraphNodePoke } from '@urbit/api/graph';
|
||||
import { GraphReducer, reduceDm } from '../reducers/graph-update';
|
||||
import _ from 'lodash';
|
||||
|
||||
@ -24,17 +24,16 @@ export interface GraphState {
|
||||
screening: boolean;
|
||||
graphTimesentMap: Record<number, string>;
|
||||
getDeepOlderThan: (ship: string, name: string, count: number, start?: string) => Promise<void>;
|
||||
// getKeys: () => Promise<void>;
|
||||
// getTags: () => Promise<void>;
|
||||
// getTagQueries: () => Promise<void>;
|
||||
// getGraph: (ship: string, resource: string) => Promise<void>;
|
||||
getNewest: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
||||
getOlderSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
||||
getYoungerSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
||||
// getGraphSubset: (ship: string, resource: string, start: string, end: string) => Promise<void>;
|
||||
getNode: (ship: string, resource: string, index: string) => Promise<void>;
|
||||
getFirstborn: (ship: string, resource: string, index: string) => Promise<void>;
|
||||
getGraph: (ship: string, name: string) => Promise<void>;
|
||||
addDmMessage: (ship: string, contents: Content[]) => Promise<void>;
|
||||
addPost: (ship: string, name: string, post: Post) => Promise<void>;
|
||||
|
||||
addNode: (ship: string, name: string, post: GraphNodePoke) => Promise<void>;
|
||||
}
|
||||
// @ts-ignore investigate zustand types
|
||||
const useGraphState = createState<GraphState>('Graph', (set, get) => ({
|
||||
@ -47,6 +46,37 @@ const useGraphState = createState<GraphState>('Graph', (set, get) => ({
|
||||
graphTimesentMap: {},
|
||||
pendingDms: new Set(),
|
||||
screening: false,
|
||||
addDmMessage: async (ship: string, contents: Content[]) => {
|
||||
const promise = airlock.poke(addDmMessage(window.ship, ship, contents));
|
||||
const { json } = addDmMessage(window.ship, ship, contents);
|
||||
markPending(json['add-nodes'].nodes);
|
||||
json['add-nodes'].resource.ship = json['add-nodes'].resource.ship.slice(1);
|
||||
GraphReducer({
|
||||
'graph-update': json
|
||||
});
|
||||
await promise;
|
||||
},
|
||||
addPost: async (ship, name, post) => {
|
||||
const promise = airlock.thread(addPost(ship, name, post));
|
||||
const { body } = addPost(ship, name, post);
|
||||
markPending(body['add-nodes'].nodes);
|
||||
body['add-nodes'].resource.ship = body['add-nodes'].resource.ship.slice(1);
|
||||
GraphReducer({
|
||||
'graph-update': body,
|
||||
'graph-update-flat': body
|
||||
});
|
||||
await promise;
|
||||
},
|
||||
addNode: async (ship, name, node) => {
|
||||
const promise = airlock.thread(addNode(ship, name, node));
|
||||
const { body } = addNode(ship, name, node);
|
||||
markPending(body['add-nodes'].nodes);
|
||||
body['add-nodes'].resource.ship = body['add-nodes'].resource.ship.slice(1);
|
||||
GraphReducer({
|
||||
'graph-update': body
|
||||
});
|
||||
await promise;
|
||||
},
|
||||
getDeepOlderThan: async (ship, name, count, start) => {
|
||||
const data = await airlock.scry(getDeepOlderThan(ship, name, count, start));
|
||||
|
||||
|
@ -31,7 +31,7 @@ const useGroupState = createState<GroupState>(
|
||||
reduceStateN(get(), e.groupUpdate, reduce);
|
||||
}
|
||||
}),
|
||||
(set, get) => createSubscription('group-view', '/groups', (e) => {
|
||||
(set, get) => createSubscription('group-view', '/all', (e) => {
|
||||
const data = _.get(e, 'group-view-update', false);
|
||||
if (data) {
|
||||
reduceStateN(get(), data, reduceView);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { addPost, Content, createPost, fetchIsAllowed, markCountAsRead, Post, removePosts } from '@urbit/api';
|
||||
import { Content, createPost, fetchIsAllowed, markCountAsRead, Post, removePosts } from '@urbit/api';
|
||||
import { Association } from '@urbit/api/metadata';
|
||||
import { BigInteger } from 'big-integer';
|
||||
import React, {
|
||||
@ -43,9 +43,10 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
|
||||
const [
|
||||
getNewest,
|
||||
getOlderSiblings,
|
||||
getYoungerSiblings
|
||||
getYoungerSiblings,
|
||||
addPost
|
||||
] = useGraphState(
|
||||
s => [s.getNewest, s.getOlderSiblings, s.getYoungerSiblings],
|
||||
s => [s.getNewest, s.getOlderSiblings, s.getYoungerSiblings, s.addPost],
|
||||
shallow
|
||||
);
|
||||
|
||||
@ -129,8 +130,8 @@ const ChatResource = (props: ChatResourceProps): ReactElement => {
|
||||
|
||||
const onSubmit = useCallback((contents: Content[]) => {
|
||||
const { ship, name } = resourceFromPath(resource);
|
||||
airlock.thread(addPost(ship, name, createPost(window.ship, contents)));
|
||||
}, [resource]);
|
||||
addPost(ship, name, createPost(window.ship, contents));
|
||||
}, [resource, addPost]);
|
||||
|
||||
const onDelete = useCallback((msg: Post) => {
|
||||
const { ship, name } = resourceFromPath(resource);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { addDmMessage, cite, Content, markCountAsRead, Post } from '@urbit/api';
|
||||
import { cite, Content, markCountAsRead, Post } from '@urbit/api';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import _ from 'lodash';
|
||||
import bigInt from 'big-integer';
|
||||
@ -10,7 +10,6 @@ import useGraphState, { useDM } from '~/logic/state/graph';
|
||||
import { useHarkDm } from '~/logic/state/hark';
|
||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||
import { ChatPane } from './components/ChatPane';
|
||||
import { patpToUd } from '~/logic/lib/util';
|
||||
import airlock from '~/logic/api';
|
||||
import shallow from 'zustand/shallow';
|
||||
|
||||
@ -60,11 +59,12 @@ export function DmResource(props: DmResourceProps) {
|
||||
const nickname = showNickname ? contact!.nickname : cite(ship) ?? ship;
|
||||
|
||||
const [
|
||||
getNewest,
|
||||
getYoungerSiblings,
|
||||
getOlderSiblings,
|
||||
getYoungerSiblings
|
||||
getNewest,
|
||||
addDmMessage
|
||||
] = useGraphState(
|
||||
s => [s.getYoungerSiblings, s.getOlderSiblings, s.getNewest],
|
||||
s => [s.getYoungerSiblings, s.getOlderSiblings, s.getNewest, s.addDmMessage],
|
||||
shallow
|
||||
);
|
||||
|
||||
@ -73,7 +73,7 @@ export function DmResource(props: DmResourceProps) {
|
||||
`~${window.ship}`,
|
||||
'dm-inbox',
|
||||
100,
|
||||
`/${patpToUd(ship)}`
|
||||
`/${patp2dec(ship)}`
|
||||
);
|
||||
}, [ship]);
|
||||
|
||||
@ -90,7 +90,7 @@ export function DmResource(props: DmResourceProps) {
|
||||
`~${window.ship}`,
|
||||
'dm-inbox',
|
||||
pageSize,
|
||||
`/${patpToUd(ship)}/${index.toString()}`
|
||||
`/${patp2dec(ship)}/${index.toString()}`
|
||||
);
|
||||
return expectedSize !== getCurrDmSize(ship);
|
||||
} else {
|
||||
@ -102,7 +102,7 @@ export function DmResource(props: DmResourceProps) {
|
||||
`~${window.ship}`,
|
||||
'dm-inbox',
|
||||
pageSize,
|
||||
`/${patpToUd(ship)}/${index.toString()}`
|
||||
`/${patp2dec(ship)}/${index.toString()}`
|
||||
);
|
||||
return expectedSize !== getCurrDmSize(ship);
|
||||
}
|
||||
@ -116,10 +116,9 @@ export function DmResource(props: DmResourceProps) {
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(contents: Content[]) => {
|
||||
// XX optimistic
|
||||
airlock.poke(addDmMessage(`~${window.ship}`, ship, contents));
|
||||
addDmMessage(ship, contents);
|
||||
},
|
||||
[ship]
|
||||
[ship, addDmMessage]
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -98,10 +98,10 @@ export const LinkItem = React.forwardRef((props: LinkItemProps, ref: RefObject<H
|
||||
};
|
||||
|
||||
const appPath = `/ship/~${resource}`;
|
||||
const unreads = useHarkState(state => state.unreads);
|
||||
const commColor = (unreads.graph?.[appPath]?.[`/${index}`]?.unreads ?? 0) > 0 ? 'blue' : 'gray';
|
||||
const unreads = useHarkState(state => state.unreads?.[appPath]);
|
||||
const commColor = (unreads?.[`/${index}`]?.unreads ?? 0) > 0 ? 'blue' : 'gray';
|
||||
// @ts-ignore hark will have to choose between sets and numbers
|
||||
const isUnread = unreads.graph?.[appPath]?.['/']?.unreads?.has(node.post.index);
|
||||
const isUnread = (unreads?.['/']?.unreads ?? new Set()).has(node.post.index);
|
||||
|
||||
return (
|
||||
<Box
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { BaseInput, Box, Button, LoadingSpinner, Text } from '@tlon/indigo-react';
|
||||
import { addPost } from '@urbit/api/graph';
|
||||
import { hasProvider } from 'oembed-parser';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { createPost } from '~/logic/api/graph';
|
||||
@ -7,7 +6,7 @@ import { parsePermalink, permalinkToReference } from '~/logic/lib/permalinks';
|
||||
import { useFileDrag } from '~/logic/lib/useDrag';
|
||||
import useStorage from '~/logic/lib/useStorage';
|
||||
import SubmitDragger from '~/views/components/SubmitDragger';
|
||||
import airlock from '~/logic/api';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
|
||||
interface LinkSubmitProps {
|
||||
name: string;
|
||||
@ -18,6 +17,7 @@ interface LinkSubmitProps {
|
||||
const LinkSubmit = (props: LinkSubmitProps) => {
|
||||
const { canUpload, uploadDefault, uploading, promptUpload } =
|
||||
useStorage();
|
||||
const addPost = useGraphState(s => s.addPost);
|
||||
|
||||
const [submitFocused, setSubmitFocused] = useState(false);
|
||||
const [urlFocused, setUrlFocused] = useState(false);
|
||||
@ -37,16 +37,15 @@ const LinkSubmit = (props: LinkSubmitProps) => {
|
||||
const parentIndex = props.parentIndex || '';
|
||||
const post = createPost(contents, parentIndex);
|
||||
|
||||
airlock.thread(addPost(
|
||||
addPost(
|
||||
`~${props.ship}`,
|
||||
props.name,
|
||||
post
|
||||
)).then(() => {
|
||||
setDisabled(false);
|
||||
setLinkValue('');
|
||||
setLinkTitle('');
|
||||
setLinkValid(false);
|
||||
});
|
||||
);
|
||||
setDisabled(false);
|
||||
setLinkValue('');
|
||||
setLinkTitle('');
|
||||
setLinkValid(false);
|
||||
};
|
||||
|
||||
const validateLink = (link) => {
|
||||
|
@ -13,7 +13,6 @@ import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
|
||||
import { SwipeMenu } from '~/views/components/SwipeMenu';
|
||||
import { GraphNotification } from './graph';
|
||||
import { GroupNotification } from './group';
|
||||
import airlock from '~/logic/api';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import shallow from 'zustand/shallow';
|
||||
|
||||
@ -47,7 +46,7 @@ export function NotificationWrapper(props: {
|
||||
if (!notification || read) {
|
||||
return;
|
||||
}
|
||||
return airlock.poke(readNote(notification.index));
|
||||
return readNote(notification.index);
|
||||
};
|
||||
|
||||
const { hovering, bind } = useHovering();
|
||||
|
@ -66,15 +66,15 @@ export function NotePreview(props: NotePreviewProps) {
|
||||
const noteId = post.index.split('/')[1];
|
||||
const url = `${props.baseUrl}/note/${noteId}`;
|
||||
|
||||
const [rev, title, body, content] = getLatestRevision(node);
|
||||
const [, title, body] = getLatestRevision(node);
|
||||
const appPath = `/ship/${props.host}/${props.book}`;
|
||||
const unreads = useHarkState(state => state.unreads);
|
||||
const unreads = useHarkState(state => state.unreads.graph?.[appPath]);
|
||||
// @ts-ignore hark will have to choose between sets and numbers
|
||||
const isUnread = unreads.graph?.[appPath]?.['/']?.unreads?.has(`/${noteId}/1/1`);
|
||||
const isUnread = (unreads?.['/'].unreads ?? new Set()).has(`/${noteId}/1/1`);
|
||||
|
||||
const snippet = getSnippet(body);
|
||||
|
||||
const commColor = (unreads.graph?.[appPath]?.[`/${noteId}`]?.unreads ?? 0) > 0 ? 'blue' : 'gray';
|
||||
const commColor = (unreads?.[`/${noteId}`]?.unreads ?? 0) > 0 ? 'blue' : 'gray';
|
||||
|
||||
const cursorStyle = post.pending ? 'default' : 'pointer';
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Col } from '@tlon/indigo-react';
|
||||
import { createPost, createBlankNodeWithChildPost, addNode, Association, GraphNode, Group, markCountAsRead, addPost } from '@urbit/api';
|
||||
import { createPost, createBlankNodeWithChildPost, Association, GraphNode, Group, markCountAsRead, addPost } from '@urbit/api';
|
||||
import bigInt from 'big-integer';
|
||||
import { FormikHelpers } from 'formik';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
@ -14,6 +14,7 @@ import { PropFunc } from '~/types/util';
|
||||
import CommentInput from './CommentInput';
|
||||
import { CommentItem } from './CommentItem';
|
||||
import airlock from '~/logic/api';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
|
||||
interface CommentsProps {
|
||||
comments: GraphNode;
|
||||
@ -35,6 +36,7 @@ export function Comments(props: CommentsProps & PropFunc<typeof Col>) {
|
||||
group,
|
||||
...rest
|
||||
} = props;
|
||||
const addNode = useGraphState(s => s.addNode);
|
||||
|
||||
const { query } = useQuery();
|
||||
const selectedComment = useMemo(() => {
|
||||
@ -54,12 +56,12 @@ export function Comments(props: CommentsProps & PropFunc<typeof Col>) {
|
||||
try {
|
||||
const content = tokenizeMessage(comment);
|
||||
const node = createBlankNodeWithChildPost(
|
||||
`~${window.ship}`,
|
||||
window.ship,
|
||||
comments?.post?.index,
|
||||
'1',
|
||||
content
|
||||
);
|
||||
await airlock.thread(addNode(ship, name, node));
|
||||
addNode(ship, name, node);
|
||||
actions.resetForm();
|
||||
actions.setStatus({ success: null });
|
||||
} catch (e) {
|
||||
|
@ -345,7 +345,7 @@ export const removePosts = (
|
||||
* @param ship recipient
|
||||
* @param contents contents of message
|
||||
*/
|
||||
export const addDmMessage = (our: Patp, ship: Patp, contents: Content[]): Poke<any> => {
|
||||
export const addDmMessage = (our: PatpNoSig, ship: Patp, contents: Content[]): Poke<any> => {
|
||||
const post = createPost(our, contents, `/${patp2dec(ship)}`);
|
||||
const node: GraphNode = {
|
||||
post,
|
||||
@ -356,7 +356,7 @@ export const addDmMessage = (our: Patp, ship: Patp, contents: Content[]): Poke<a
|
||||
mark: `graph-update-${GRAPH_UPDATE_VERSION}`,
|
||||
json: {
|
||||
'add-nodes': {
|
||||
resource: { ship: our, name: 'dm-inbox' },
|
||||
resource: { ship: `~${our}`, name: 'dm-inbox' },
|
||||
nodes: {
|
||||
[post.index]: node
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user