mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-13 20:04:35 +03:00
group-feed: improve performance and make mobile load
This commit is contained in:
parent
b7e52edd58
commit
2dddf1b837
20
pkg/interface/src/logic/lib/withMemo.js
Normal file
20
pkg/interface/src/logic/lib/withMemo.js
Normal file
@ -0,0 +1,20 @@
|
||||
import { memo } from 'react';
|
||||
|
||||
const withMemo = (Component, checkedProps) => {
|
||||
function areEqual(prevProps, nextProps) {
|
||||
let isEqual = true;
|
||||
for (let i = 0; i < checkedProps.length; i++) {
|
||||
const checkedProp = checkedProps[i];
|
||||
console.log(checkedProp);
|
||||
if (JSON.stringify(prevProps[checkedProp]) !== JSON.stringify(nextProps[checkedProp])) {
|
||||
isEqual = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
return memo(Component, areEqual);
|
||||
};
|
||||
|
||||
export default withMemo;
|
@ -210,7 +210,6 @@ export function GroupsPane(props: GroupsPaneProps) {
|
||||
associations={associations}
|
||||
groups={groups}
|
||||
groupPath={groupPath}
|
||||
contacts={contacts}
|
||||
workspace={workspace}
|
||||
/>
|
||||
{popovers(routeProps, baseUrl)}
|
||||
|
@ -6,8 +6,8 @@ import { Col } from '@tlon/indigo-react'
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
import { GroupFeedHeader } from './GroupFeedHeader';
|
||||
import { PostTimeline } from './Post/PostTimeline';
|
||||
import { PostReplies } from './Post/PostReplies';
|
||||
import PostTimeline from './Post/PostTimeline';
|
||||
import PostReplies from './Post/PostReplies';
|
||||
|
||||
|
||||
export function GroupFeed(props) {
|
||||
@ -16,7 +16,7 @@ export function GroupFeed(props) {
|
||||
api,
|
||||
history,
|
||||
associations,
|
||||
graphPath
|
||||
graphPath,
|
||||
} = props;
|
||||
const graphs = useGraphState(state => state.graphs);
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
@ -29,6 +29,9 @@ export function GroupFeed(props) {
|
||||
const relativePath = (path) => baseUrl + path;
|
||||
const association = associations.graph[graphPath];
|
||||
|
||||
const graphId = `${graphResource.ship.slice(1)}/${graphResource.name}`;
|
||||
const graph = graphs[graphId];
|
||||
|
||||
useEffect(() => {
|
||||
// TODO: VirtualScroller should support lower starting values than 100
|
||||
api.graph.getNewest(graphResource.ship, graphResource.name, 100);
|
||||
@ -53,11 +56,13 @@ export function GroupFeed(props) {
|
||||
render={(routeProps) => {
|
||||
return (
|
||||
<PostTimeline
|
||||
{...props}
|
||||
baseUrl={baseUrl}
|
||||
api={api}
|
||||
history={history}
|
||||
graphPath={graphPath}
|
||||
association={association}
|
||||
graphs={graphs}
|
||||
pendingSize={pendingSize}
|
||||
graphResource={graphResource} />
|
||||
graph={graph}
|
||||
pendingSize={pendingSize} />
|
||||
);
|
||||
}} />
|
||||
<Route
|
||||
@ -65,11 +70,13 @@ export function GroupFeed(props) {
|
||||
render={(routeProps) => {
|
||||
return (
|
||||
<PostReplies
|
||||
{...props}
|
||||
baseUrl={baseUrl}
|
||||
api={api}
|
||||
history={history}
|
||||
graphPath={graphPath}
|
||||
association={association}
|
||||
graphs={graphs}
|
||||
pendingSize={pendingSize}
|
||||
graphResource={graphResource} />
|
||||
graph={graph}
|
||||
pendingSize={pendingSize} />
|
||||
);
|
||||
}} />
|
||||
</Switch>
|
||||
|
@ -15,8 +15,7 @@ export function GroupHome(props) {
|
||||
groupPath,
|
||||
groups,
|
||||
graphs,
|
||||
baseUrl,
|
||||
contacts,
|
||||
baseUrl
|
||||
} = props;
|
||||
|
||||
const metadata = associations?.groups[groupPath]?.metadata;
|
||||
@ -59,7 +58,6 @@ export function GroupHome(props) {
|
||||
<GroupFeed
|
||||
associations={associations}
|
||||
groups={groups}
|
||||
contacts={contacts}
|
||||
graphPath={graphPath}
|
||||
graphs={graphs}
|
||||
api={api}
|
||||
|
@ -1,10 +1,13 @@
|
||||
import React from 'react';
|
||||
import { Col } from '@tlon/indigo-react';
|
||||
import { MentionText } from '~/views/components/MentionText';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
|
||||
export function PostContent(props) {
|
||||
const { post, contacts, isParent, api } = props;
|
||||
const { post, isParent, api } = props;
|
||||
const contacts = useContactState(state => state.contacts);
|
||||
|
||||
return (
|
||||
<Col
|
||||
width="100%"
|
||||
|
@ -3,13 +3,13 @@ import bigInt from 'big-integer';
|
||||
import VirtualScroller from "~/views/components/VirtualScroller";
|
||||
import PostItem from './PostItem';
|
||||
import { Col } from '@tlon/indigo-react';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
|
||||
|
||||
const virtualScrollerStyle = {
|
||||
height: "100%"
|
||||
};
|
||||
|
||||
|
||||
export class PostFeed extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -18,14 +18,14 @@ export class PostFeed extends React.Component {
|
||||
this.renderItem = React.forwardRef(({ index, scrollWindow }, ref) => {
|
||||
const {
|
||||
graph,
|
||||
graphResource,
|
||||
contacts,
|
||||
graphPath,
|
||||
api,
|
||||
history,
|
||||
baseUrl,
|
||||
parentNode,
|
||||
association
|
||||
} = this.props;
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
const node = graph.get(index);
|
||||
if (!node) { return null; }
|
||||
|
||||
@ -39,7 +39,6 @@ export class PostFeed extends React.Component {
|
||||
}) : [];
|
||||
|
||||
if (parentNode && index.eq(first ?? bigInt.zero)) {
|
||||
|
||||
return (
|
||||
<React.Fragment key={index.toString()}>
|
||||
<Col
|
||||
@ -52,8 +51,7 @@ export class PostFeed extends React.Component {
|
||||
key={parentNode.post.index}
|
||||
ref={ref}
|
||||
node={parentNode}
|
||||
contacts={contacts}
|
||||
graphResource={graphResource}
|
||||
graphPath={graphPath}
|
||||
association={association}
|
||||
api={api}
|
||||
index={nodeIndex}
|
||||
@ -65,8 +63,7 @@ export class PostFeed extends React.Component {
|
||||
<PostItem
|
||||
ref={ref}
|
||||
node={node}
|
||||
contacts={contacts}
|
||||
graphResource={graphResource}
|
||||
graphPath={graphPath}
|
||||
association={association}
|
||||
api={api}
|
||||
index={[...nodeIndex, index]}
|
||||
@ -84,8 +81,7 @@ export class PostFeed extends React.Component {
|
||||
key={index.toString()}
|
||||
ref={ref}
|
||||
node={node}
|
||||
contacts={contacts}
|
||||
graphResource={graphResource}
|
||||
graphPath={graphPath}
|
||||
association={association}
|
||||
api={api}
|
||||
index={[...nodeIndex, index]}
|
||||
@ -102,7 +98,8 @@ export class PostFeed extends React.Component {
|
||||
}
|
||||
|
||||
async fetchPosts(newer) {
|
||||
const { graph, graphResource, api } = this.props;
|
||||
const { graph, graphPath, api } = this.props;
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
|
||||
if (this.isFetching) {
|
||||
return false;
|
||||
@ -134,11 +131,12 @@ export class PostFeed extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { graph, pendingSize, parentNode } = this.props;
|
||||
const { graph, pendingSize, parentNode, history } = this.props;
|
||||
|
||||
return (
|
||||
<Col width="100%" height="100%" position="relative">
|
||||
<VirtualScroller
|
||||
key={history.location.pathname}
|
||||
origin="top"
|
||||
offset={0}
|
||||
data={graph}
|
||||
|
@ -4,11 +4,12 @@ import Author from '~/views/components/Author';
|
||||
import { useCopy } from '~/logic/lib/useCopy';
|
||||
import { getPermalinkForGraph } from '~/logic/lib/permalinks';
|
||||
import { Dropdown } from '~/views/components/Dropdown';
|
||||
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
|
||||
export function PostHeader(props) {
|
||||
const { post, contacts, api, association, isReply } = props;
|
||||
const { post, api, association, isReply } = props;
|
||||
const contacts = useContactState(state => state.contacts);
|
||||
const mb = isReply ? "2" : "3";
|
||||
|
||||
const permalink = !!association ? getPermalinkForGraph(
|
||||
|
@ -7,10 +7,12 @@ import tokenizeMessage from '~/logic/lib/tokenizeMessage';
|
||||
import { useToggleState } from '~/logic/lib/useToggleState';
|
||||
import { createPost } from '~/logic/api/graph';
|
||||
import useStorage from '~/logic/lib/useStorage';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
|
||||
|
||||
export function PostInput(props) {
|
||||
const { api, graphResource, index, submitCallback } = props;
|
||||
const { api, graphPath, index, submitCallback } = props;
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const [code, toggleCode] = useToggleState(false);
|
||||
|
@ -7,6 +7,7 @@ import { PostInput } from './PostInput';
|
||||
import { Mention } from "~/views/components/MentionText";
|
||||
import withState from '~/logic/lib/withState';
|
||||
import { useHovering } from '~/logic/lib/util';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
|
||||
|
||||
class PostItem extends React.Component {
|
||||
@ -43,9 +44,8 @@ class PostItem extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
node,
|
||||
contacts,
|
||||
api,
|
||||
graphResource,
|
||||
graphPath,
|
||||
association,
|
||||
index,
|
||||
innerRef,
|
||||
@ -55,6 +55,7 @@ class PostItem extends React.Component {
|
||||
hovering,
|
||||
bind
|
||||
} = this.props;
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
|
||||
let indexString = '';
|
||||
|
||||
@ -113,7 +114,7 @@ class PostItem extends React.Component {
|
||||
borderLeftColor="lightGray"></Box>
|
||||
<PostInput
|
||||
api={api}
|
||||
graphResource={graphResource}
|
||||
graphPath={graphPath}
|
||||
index={indexString}
|
||||
submitCallback={this.submitCallback} />
|
||||
</Col>
|
||||
|
@ -5,23 +5,30 @@ import { PostInput } from './PostInput';
|
||||
import PostItem from './PostItem';
|
||||
import { PostFeed } from './PostFeed';
|
||||
import { Loading } from '~/views/components/Loading';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
|
||||
|
||||
export function PostReplies(props) {
|
||||
export default class PostReplies extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.whyDidYouRender = true;
|
||||
}
|
||||
|
||||
render() {
|
||||
let graph = this.props.graph;
|
||||
const {
|
||||
baseUrl,
|
||||
api,
|
||||
history,
|
||||
association,
|
||||
groups,
|
||||
contacts,
|
||||
graphPath,
|
||||
graphs,
|
||||
pendingSize,
|
||||
graphResource
|
||||
} = props;
|
||||
pendingSize
|
||||
} = this.props;
|
||||
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
const graphId = `${graphResource.ship.slice(1)}/${graphResource.name}`;
|
||||
const shouldRenderFeed = graphId in graphs;
|
||||
const shouldRenderFeed = !!graph;
|
||||
|
||||
if (!shouldRenderFeed) {
|
||||
return (
|
||||
@ -38,7 +45,6 @@ export function PostReplies(props) {
|
||||
});
|
||||
|
||||
let node;
|
||||
let graph = graphs[graphId];
|
||||
nodeIndex.forEach((i) => {
|
||||
if (!graph) {
|
||||
return null;
|
||||
@ -66,8 +72,7 @@ export function PostReplies(props) {
|
||||
<PostItem
|
||||
key={node.post.index}
|
||||
node={node}
|
||||
contacts={contacts}
|
||||
graphResource={graphResource}
|
||||
graphPath={graphPath}
|
||||
association={association}
|
||||
api={api}
|
||||
index={nodeIndex}
|
||||
@ -96,7 +101,7 @@ export function PostReplies(props) {
|
||||
<Box height="calc(100% - 48px)" width="100%" alignItems="center" pl="1" pt="3">
|
||||
<PostFeed
|
||||
key={locationUrl}
|
||||
graphResource={graphResource}
|
||||
graphPath={graphPath}
|
||||
graph={graph}
|
||||
parentNode={node}
|
||||
pendingSize={pendingSize}
|
||||
@ -110,4 +115,5 @@ export function PostReplies(props) {
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,23 +3,27 @@ import { Text, Col, Box } from '@tlon/indigo-react'
|
||||
import { PostInput } from './PostInput';
|
||||
import { PostFeed } from './PostFeed';
|
||||
import { Loading } from '~/views/components/Loading';
|
||||
import { resourceFromPath } from '~/logic/lib/group';
|
||||
|
||||
|
||||
export function PostTimeline(props) {
|
||||
export default class PostTimeline extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.whyDidYouRender = true;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
baseUrl,
|
||||
api,
|
||||
history,
|
||||
association,
|
||||
groups,
|
||||
contacts,
|
||||
graphPath,
|
||||
graphs,
|
||||
graph,
|
||||
pendingSize,
|
||||
graphResource
|
||||
} = props;
|
||||
const graphId = `${graphResource.ship.slice(1)}/${graphResource.name}`;
|
||||
const shouldRenderFeed = graphId in graphs;
|
||||
} = this.props;
|
||||
const graphResource = resourceFromPath(graphPath);
|
||||
const shouldRenderFeed = !!graph;
|
||||
|
||||
if (!shouldRenderFeed) {
|
||||
return (
|
||||
@ -29,7 +33,6 @@ export function PostTimeline(props) {
|
||||
);
|
||||
}
|
||||
|
||||
const graph = graphs[graphId];
|
||||
const first = graph.peekLargest()?.[0];
|
||||
if (!first) {
|
||||
return (
|
||||
@ -48,7 +51,7 @@ export function PostTimeline(props) {
|
||||
alignItems="center">
|
||||
<PostInput
|
||||
api={api}
|
||||
graphResource={graphResource} />
|
||||
graphPath={graphPath} />
|
||||
</Col>
|
||||
<Box
|
||||
pl="2"
|
||||
@ -77,17 +80,15 @@ export function PostTimeline(props) {
|
||||
mb="3"
|
||||
flexDirection="column"
|
||||
alignItems="center">
|
||||
<PostInput api={api} graphResource={graphResource} />
|
||||
<PostInput api={api} graphPath={graphPath} />
|
||||
</Box>
|
||||
<Box height="calc(100% - 176px)" width="100%" alignItems="center" pl="1">
|
||||
<PostFeed
|
||||
key={graphPath}
|
||||
graphResource={graphResource}
|
||||
graph={graphs[graphId]}
|
||||
graphPath={graphPath}
|
||||
graph={graph}
|
||||
pendingSize={pendingSize}
|
||||
association={association}
|
||||
groups={groups}
|
||||
contacts={contacts}
|
||||
api={api}
|
||||
history={history}
|
||||
baseUrl={baseUrl}
|
||||
@ -96,4 +97,5 @@ export function PostTimeline(props) {
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import useGraphState from '~/logic/state/graph';
|
||||
import useHarkState, { withHarkState } from '~/logic/state/hark';
|
||||
import withState from '~/logic/lib/withState';
|
||||
|
||||
|
||||
type LandscapeProps = StoreState & {
|
||||
ship: PatpNoSig;
|
||||
api: GlobalApi;
|
||||
@ -67,14 +68,8 @@ export function DMRedirect(props: LandscapeProps & RouteComponentProps & { ship:
|
||||
);
|
||||
}
|
||||
|
||||
class Landscape extends Component<LandscapeProps, Record<string, never>> {
|
||||
componentDidMount(): void {
|
||||
this.props.subscription.startApp('groups');
|
||||
this.props.subscription.startApp('graph');
|
||||
}
|
||||
|
||||
render(): ReactElement {
|
||||
const { props } = this;
|
||||
export default function Landscape(props) {
|
||||
const notificationsCount = useHarkState(s => s.notificationsCount);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -154,8 +149,4 @@ class Landscape extends Component<LandscapeProps, Record<string, never>> {
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withState(Landscape, [
|
||||
[useHarkState, ['notificationsCount']]
|
||||
]);
|
||||
|
Loading…
Reference in New Issue
Block a user