mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-14 08:34:25 +03:00
interface: reworked thread view so that one can navigate to it from any child to see the conversation around that particular child
This commit is contained in:
parent
43a7c12ef7
commit
6b102450a5
@ -361,15 +361,18 @@ export default class GraphApi extends BaseApi<StoreState> {
|
||||
});
|
||||
}
|
||||
|
||||
async getFirstborn(ship: string, resource: string, topAncestor: string) {
|
||||
const top = topAncestor ? decToUd(topAncestor) : null;
|
||||
async getFirstborn(ship: string, resource: string, index = '') {
|
||||
const idx = index.split('/').map(decToUd).join('/');
|
||||
const data = await this.scry<any>('graph-store',
|
||||
`/firstborn/${ship}/${resource}/${top}`
|
||||
`/firstborn/${ship}/${resource}/${idx}`
|
||||
);
|
||||
const node = data['graph-update'];
|
||||
this.store.handleEvent({
|
||||
data: {
|
||||
'graph-update-thread': node,
|
||||
'graph-update-thread': {
|
||||
index,
|
||||
...node
|
||||
},
|
||||
'graph-update': node
|
||||
},
|
||||
});
|
||||
|
@ -67,6 +67,7 @@ const addNodesFlat = (json: any, state: GraphState): GraphState => {
|
||||
}
|
||||
|
||||
const indices = Array.from(Object.keys(data.nodes));
|
||||
console.log(indices);
|
||||
|
||||
indices.forEach((index) => {
|
||||
if (index.split('/').length === 0) { return; }
|
||||
@ -85,7 +86,9 @@ const addNodesFlat = (json: any, state: GraphState): GraphState => {
|
||||
|
||||
const addNodesThread = (json: any, state: GraphState): GraphState => {
|
||||
const data = _.get(json, 'add-nodes', false);
|
||||
if (data) {
|
||||
const parentIndex = _.get(json, 'index', false);
|
||||
console.log(json);
|
||||
if (data && parentIndex) {
|
||||
if (!('threadGraphs' in state)) {
|
||||
return state;
|
||||
}
|
||||
@ -96,21 +99,25 @@ const addNodesThread = (json: any, state: GraphState): GraphState => {
|
||||
}
|
||||
|
||||
const indices = Array.from(Object.keys(data.nodes));
|
||||
if (!(parentIndex in state.threadGraphs[resource])) {
|
||||
state.threadGraphs[resource][parentIndex] = new BigIntArrayOrderedMap([], true);
|
||||
}
|
||||
|
||||
console.log(state.threadGraphs);
|
||||
|
||||
indices.forEach((index) => {
|
||||
if (index.split('/').length === 0) { return; }
|
||||
const indexArr = index.split('/').slice(1).map((ind) => bigInt(ind));
|
||||
|
||||
if (indexArr.length === 0) { return state; }
|
||||
|
||||
let parentKey = indexArr[0].toString();
|
||||
if (!(parentKey in state.threadGraphs[resource])) {
|
||||
state.threadGraphs[resource][parentKey] = new BigIntArrayOrderedMap([], true);
|
||||
}
|
||||
|
||||
let node = data.nodes[index];
|
||||
node.children = mapifyChildren({});
|
||||
state.threadGraphs[resource][parentKey] =
|
||||
state.threadGraphs[resource][parentKey].set(indexArr, node);
|
||||
state.threadGraphs[resource][parentIndex] =
|
||||
state.threadGraphs[resource][parentIndex].set(indexArr,
|
||||
produce(node, (draft) => {
|
||||
draft.children = mapifyChildren({});
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -148,6 +148,28 @@ export function useGraph(ship: string, name: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export function useFlatGraph(ship: string, name: string) {
|
||||
return useGraphState(
|
||||
useCallback(s => s.flatGraphs[`${deSig(ship)}/${name}`], [ship, name])
|
||||
);
|
||||
}
|
||||
|
||||
export function useThreadGraph(ship: string, name: string, index: string) {
|
||||
return useGraphState(
|
||||
useCallback(s => s.threadGraphs[`${deSig(ship)}/${name}/${index}`], [
|
||||
ship,
|
||||
name,
|
||||
index
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
export function useGraphTimesentMap(ship: string, name: string) {
|
||||
return useGraphState(
|
||||
useCallback(s => s.graphTimesentMap[`${deSig(ship)}/${name}`], [ship, name])
|
||||
);
|
||||
}
|
||||
|
||||
export function useGraphForAssoc(association: Association) {
|
||||
const { resource } = association;
|
||||
const { ship, name } = resourceFromPath(resource);
|
||||
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||
|
||||
export function GroupFeedHeader(props) {
|
||||
const { baseUrl, history, graphResource, vip } = props;
|
||||
|
||||
let graph = props.graph;
|
||||
const historyLocation = history.location.pathname;
|
||||
const graphId = `${graphResource.ship.slice(1)}/${graphResource.name}`;
|
||||
|
@ -4,9 +4,9 @@ import React, {
|
||||
} from 'react';
|
||||
import { Route, Switch, useHistory } from 'react-router-dom';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
import { useFlatGraph, useGraphTimesentMap } from '~/logic/state/graph';
|
||||
import { useGroup } from '~/logic/state/group';
|
||||
import { useAssocForGraph } from '~/logic/state/metadata';
|
||||
import { Loading } from '~/views/components/Loading';
|
||||
import { GroupFeedHeader } from './GroupFeedHeader';
|
||||
import PostThread from './Post/PostThread';
|
||||
@ -23,36 +23,27 @@ function GroupFlatFeed(props) {
|
||||
vip
|
||||
} = props;
|
||||
|
||||
const groups = useGroupState(state => state.groups);
|
||||
const group = groups[groupPath];
|
||||
const group = useGroup(groupPath);
|
||||
|
||||
const associations = useMetadataState(state => state.associations);
|
||||
const flatGraphs = useGraphState(state => state.flatGraphs);
|
||||
|
||||
const graphResource =
|
||||
const graphRid =
|
||||
graphPath ? resourceFromPath(graphPath) : resourceFromPath('/ship/~zod/null');
|
||||
const graphTimesentMap = useGraphState(state => state.graphTimesentMap);
|
||||
|
||||
const pendingSize = Object.keys(
|
||||
graphTimesentMap[`${graphResource.ship.slice(1)}/${graphResource.name}`] ||
|
||||
{}
|
||||
).length;
|
||||
const flatGraph = useFlatGraph(graphRid.ship, graphRid.name);
|
||||
const association = useAssocForGraph(graphPath);
|
||||
|
||||
const graphTimesentMap = useGraphTimesentMap(graphRid.ship, graphRid.name);
|
||||
const pendingSize = Object.keys(graphTimesentMap || {}).length;
|
||||
|
||||
const relativePath = path => baseUrl + path;
|
||||
const association = associations.graph[graphPath];
|
||||
|
||||
const history = useHistory();
|
||||
const locationUrl = history.location.pathname;
|
||||
|
||||
const graphId = `${graphResource.ship.slice(1)}/${graphResource.name}`;
|
||||
const flatGraph = flatGraphs[graphId];
|
||||
|
||||
useEffect(() => {
|
||||
// TODO: VirtualScroller should support lower starting values than 100
|
||||
if (graphResource.ship === '~zod' && graphResource.name === 'null') {
|
||||
if (graphRid.ship === '~zod' && graphRid.name === 'null') {
|
||||
return;
|
||||
}
|
||||
api.graph.getDeepOlderThan(graphResource.ship, graphResource.name, null, 100);
|
||||
api.graph.getDeepOlderThan(graphRid.ship, graphRid.name, null, 100);
|
||||
api.hark.markCountAsRead(association, '/', 'post');
|
||||
}, [graphPath]);
|
||||
|
||||
@ -72,9 +63,8 @@ function GroupFlatFeed(props) {
|
||||
<GroupFeedHeader
|
||||
baseUrl={baseUrl}
|
||||
history={history}
|
||||
graphs={flatGraphs}
|
||||
vip={vip}
|
||||
graphResource={graphResource}
|
||||
graphResource={graphRid}
|
||||
/>
|
||||
<Switch>
|
||||
<Route
|
||||
|
@ -55,7 +55,6 @@ class PostFlatFeed extends React.Component<PostFeedProps, PostFeedState> {
|
||||
} = this.props;
|
||||
|
||||
const node = flatGraph.get(index);
|
||||
console.log(arrToString(index))
|
||||
const parentNode = index.length > 1 ?
|
||||
flatGraph.get(index.slice(0, index.length - 1)) : null;
|
||||
|
||||
@ -63,6 +62,10 @@ class PostFlatFeed extends React.Component<PostFeedProps, PostFeedState> {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (arrToString(index) !== node.post.index) {
|
||||
console.log(node.post.index, arrToString(index), node);
|
||||
}
|
||||
|
||||
const first = flatGraph.peekLargest()?.[0];
|
||||
const last = flatGraph.peekSmallest()?.[0];
|
||||
const post = node?.post;
|
||||
|
@ -47,6 +47,7 @@ const PostInput = (props: PostInputProps): ReactElement | null => {
|
||||
const [code, toggleCode] = useToggleState(false);
|
||||
const { canUpload, promptUpload, uploading } = useStorage();
|
||||
const [postContent, setPostContent] = useState('');
|
||||
|
||||
const uploadImage = useCallback(async () => {
|
||||
try {
|
||||
setDisabled(true);
|
||||
|
@ -41,8 +41,7 @@ class PostItem extends React.Component<PostItemProps, PostItemState> {
|
||||
|
||||
this.state = { inReplyMode: false };
|
||||
this.toggleReplyMode = this.toggleReplyMode.bind(this);
|
||||
this.navigateToReplies = this.navigateToReplies.bind(this);
|
||||
this.navigateToThread = this.navigateToThread.bind(this);
|
||||
this.navigateToChildren = this.navigateToChildren.bind(this);
|
||||
this.submitCallback = this.submitCallback.bind(this);
|
||||
}
|
||||
|
||||
@ -69,22 +68,8 @@ class PostItem extends React.Component<PostItemProps, PostItemState> {
|
||||
this.setState({ inReplyMode: !this.state.inReplyMode });
|
||||
}
|
||||
|
||||
navigateToReplies() {
|
||||
const { history, baseUrl, index, isParent } = this.props;
|
||||
if (isParent) {
|
||||
return;
|
||||
}
|
||||
let indexString = '';
|
||||
|
||||
index.forEach((i) => {
|
||||
indexString = indexString + '/' + i.toString();
|
||||
});
|
||||
|
||||
history.push(`${baseUrl}/feed/replies${indexString}`);
|
||||
}
|
||||
|
||||
navigateToThread() {
|
||||
const { history, baseUrl, index, isParent } = this.props;
|
||||
navigateToChildren() {
|
||||
const { history, baseUrl, index, isParent, isThread } = this.props;
|
||||
if (isParent) {
|
||||
return;
|
||||
}
|
||||
@ -94,7 +79,10 @@ class PostItem extends React.Component<PostItemProps, PostItemState> {
|
||||
indexString = indexString + '/' + i.toString();
|
||||
});
|
||||
|
||||
// TODO: ensure that the logic here works properly
|
||||
history.push(`${baseUrl}/feed/thread${indexString}`);
|
||||
|
||||
//history.push(`${baseUrl}/feed/replies${indexString}`);
|
||||
}
|
||||
|
||||
submitCallback() {
|
||||
@ -148,7 +136,7 @@ class PostItem extends React.Component<PostItemProps, PostItemState> {
|
||||
width="100%"
|
||||
maxWidth="600px"
|
||||
backgroundColor={ hovering ? 'washedGray' : 'transparent' }
|
||||
onClick={isThread ? this.navigateToReplies : this.navigateToThread}
|
||||
onClick={this.navigateToChildren}
|
||||
cursor={isParent ? "default": "pointer"}
|
||||
{...bind}>
|
||||
{ (postExists) ? (
|
||||
|
@ -5,6 +5,7 @@ import React, {
|
||||
} from 'react';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
import { Loading } from '~/views/components/Loading';
|
||||
import { arrToString } from '~/views/components/ArrayVirtualScroller';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
import PostFlatFeed from './PostFlatFeed';
|
||||
import PostItem from './PostItem/PostItem';
|
||||
@ -36,12 +37,11 @@ export default function PostThread(props) {
|
||||
if (index.length < 1) {
|
||||
return;
|
||||
}
|
||||
console.log(index[0].toString());
|
||||
|
||||
api.graph.getFirstborn(
|
||||
graphResource.ship,
|
||||
graphResource.name,
|
||||
index[0].toString()
|
||||
arrToString(index)
|
||||
);
|
||||
}, [graphPath, props.locationUrl]);
|
||||
|
||||
@ -49,7 +49,7 @@ export default function PostThread(props) {
|
||||
const graphId = `${graphResource.ship.slice(1)}/${graphResource.name}`;
|
||||
|
||||
const shouldRenderFeed =
|
||||
graphId in threadGraphs && index[0].toString() in threadGraphs[graphId];
|
||||
graphId in threadGraphs && arrToString(index) in threadGraphs[graphId];
|
||||
|
||||
if (!shouldRenderFeed) {
|
||||
return (
|
||||
@ -59,7 +59,9 @@ export default function PostThread(props) {
|
||||
);
|
||||
}
|
||||
|
||||
const threadGraph = threadGraphs[graphId][index[0].toString()];
|
||||
// TODO: improve performance characteristics of the useGraphState required
|
||||
// to fetch this
|
||||
const threadGraph = threadGraphs[graphId][arrToString(index)];
|
||||
|
||||
const first = threadGraph.peekLargest()?.[0];
|
||||
if (!first) {
|
||||
|
Loading…
Reference in New Issue
Block a user