WiP #broken
This commit is contained in:
@@ -9,6 +9,7 @@ import { AppState } from '../../reducers'
|
||||
const MovingAverage = require('moving-average')
|
||||
|
||||
declare const performance: any
|
||||
declare const window: any
|
||||
|
||||
const timeInterval = 10 * 1000
|
||||
const average = MovingAverage(timeInterval)
|
||||
@@ -48,14 +49,17 @@ class Tree extends React.Component<Props, TreeState> {
|
||||
}
|
||||
|
||||
const expectedRenderTime = average.forecast()
|
||||
const updateInterval = Math.max(expectedRenderTime * 5, 300)
|
||||
const updateInterval = Math.max(expectedRenderTime * 20, 300)
|
||||
const timeUntilNextUpdate = updateInterval - (performance.now() - this.lastUpdate)
|
||||
|
||||
this.updateTimer = setTimeout(() => {
|
||||
this.lastUpdate = performance.now()
|
||||
this.updateTimer && clearTimeout(this.updateTimer)
|
||||
this.updateTimer = undefined
|
||||
this.setState(state)
|
||||
window.requestAnimationFrame(() => {
|
||||
console.log('doRender')
|
||||
this.lastUpdate = performance.now()
|
||||
this.updateTimer && clearTimeout(this.updateTimer)
|
||||
this.updateTimer = undefined
|
||||
this.setState(state)
|
||||
})
|
||||
}, Math.max(0, timeUntilNextUpdate))
|
||||
}
|
||||
|
||||
@@ -98,15 +102,15 @@ class Tree extends React.Component<Props, TreeState> {
|
||||
cursor: 'default',
|
||||
}
|
||||
|
||||
return <Typography style={ style }>
|
||||
return <Typography style={style}>
|
||||
<TreeNode
|
||||
animateChages = { true }
|
||||
autoExpandLimit = { this.props.autoExpandLimit }
|
||||
isRoot = { true }
|
||||
didSelectNode = { this.props.didSelectNode }
|
||||
treeNode = { this.state.tree }
|
||||
name = "/"
|
||||
collapsed = { false }
|
||||
animateChages={true}
|
||||
autoExpandLimit={this.props.autoExpandLimit}
|
||||
isRoot={true}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
treeNode={this.state.tree}
|
||||
name="/"
|
||||
collapsed={false}
|
||||
key="rootNode"
|
||||
performanceCallback={(ms: number) => {
|
||||
average.push(Date.now(), ms)
|
||||
|
||||
@@ -136,38 +136,41 @@ class TreeNode extends React.Component<Props, State> {
|
||||
const { classes } = this.props
|
||||
this.dirtyEdges = this.dirtyMessage = this.dirtySubnodes = false
|
||||
|
||||
return <div
|
||||
key={this.props.treeNode.hash()}
|
||||
className={`${classes.node} ${!this.props.isRoot ? classes.hover : ''}`}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
this.toggle()
|
||||
this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)
|
||||
}}
|
||||
>
|
||||
<span ref={this.titleRef} style={animationStyle}>
|
||||
<TreeNodeTitle
|
||||
onClick={() => this.toggle()}
|
||||
collapsed={this.collapsed()}
|
||||
treeNode={this.props.treeNode}
|
||||
name={this.props.name}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
toggleCollapsed={() => this.toggle()}
|
||||
/>
|
||||
</span>
|
||||
{ this.renderNodes() }
|
||||
</div>
|
||||
return (
|
||||
<div
|
||||
key={this.props.treeNode.hash()}
|
||||
className={`${classes.node} ${!this.props.isRoot ? classes.hover : ''}`}
|
||||
onClick={this.didClickNode}
|
||||
>
|
||||
<span ref={this.titleRef} style={animationStyle}>
|
||||
<TreeNodeTitle
|
||||
collapsed={this.collapsed()}
|
||||
treeNode={this.props.treeNode}
|
||||
name={this.props.name}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
/>
|
||||
</span>
|
||||
{this.renderNodes()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private didClickNode = (event: React.MouseEvent) => {
|
||||
event.stopPropagation()
|
||||
this.toggle()
|
||||
this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)
|
||||
}
|
||||
|
||||
private renderNodes() {
|
||||
return <TreeNodeSubnodes
|
||||
animateChanges={this.props.animateChages}
|
||||
collapsed={this.collapsed()}
|
||||
autoExpandLimit={this.props.autoExpandLimit}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
toggleCollapsed={() => this.toggle()}
|
||||
treeNode={this.props.treeNode}
|
||||
/>
|
||||
return (
|
||||
<TreeNodeSubnodes
|
||||
animateChanges={this.props.animateChages}
|
||||
collapsed={this.collapsed()}
|
||||
autoExpandLimit={this.props.autoExpandLimit}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
treeNode={this.props.treeNode}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private indicatingChangeAnimationStyle(): React.CSSProperties {
|
||||
|
||||
@@ -1,52 +1,75 @@
|
||||
import * as React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import { withTheme, Theme } from '@material-ui/core/styles'
|
||||
import { AppState, NodeOrder } from '../../reducers'
|
||||
|
||||
import TreeNode from './TreeNode'
|
||||
|
||||
export interface Props {
|
||||
nodeOrder?: NodeOrder
|
||||
animateChanges: boolean
|
||||
treeNode: q.TreeNode
|
||||
autoExpandLimit: number
|
||||
collapsed?: boolean | undefined
|
||||
didSelectNode?: (node: q.TreeNode) => void
|
||||
toggleCollapsed: () => void
|
||||
theme: Theme
|
||||
}
|
||||
|
||||
class TreeNodeSubnodes extends React.Component<Props, {}> {
|
||||
private sortedNodes(): q.TreeNode[] {
|
||||
const { nodeOrder, treeNode } = this.props
|
||||
|
||||
let edges = Object.values(treeNode.edges)
|
||||
if (nodeOrder === NodeOrder.abc) {
|
||||
edges = edges.sort((a, b) => a.name.localeCompare(b.name))
|
||||
}
|
||||
|
||||
let nodes = edges.map(edge => edge.target)
|
||||
if (nodeOrder === NodeOrder.messages) {
|
||||
nodes = nodes.sort((a, b) => b.leafMessageCount() - a.leafMessageCount())
|
||||
}
|
||||
if (nodeOrder === NodeOrder.topics) {
|
||||
nodes = nodes.sort((a, b) => b.leafCount() - a.leafCount())
|
||||
}
|
||||
|
||||
return nodes
|
||||
}
|
||||
|
||||
public render() {
|
||||
const edges = Object.values(this.props.treeNode.edges)
|
||||
if (edges.length === 0 || this.props.collapsed) {
|
||||
return null
|
||||
}
|
||||
|
||||
const listItemStyle = {
|
||||
padding: '3px 8px 0px 8px',
|
||||
}
|
||||
|
||||
if (edges.length > 0 && !this.props.collapsed) {
|
||||
const listItems = edges
|
||||
.map(edge => edge.target)
|
||||
.map(node => (
|
||||
<div
|
||||
key={node.hash()}
|
||||
style={listItemStyle}
|
||||
>
|
||||
<TreeNode
|
||||
animateChages={this.props.animateChanges}
|
||||
treeNode={node}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
autoExpandLimit={this.props.autoExpandLimit}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
const nodes = this.sortedNodes()
|
||||
const listItems = nodes.map(node => (
|
||||
<div key={node.hash()} style={listItemStyle}>
|
||||
<TreeNode
|
||||
animateChages={this.props.animateChanges}
|
||||
treeNode={node}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
autoExpandLimit={this.props.autoExpandLimit}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
|
||||
return <span
|
||||
style={{ display: 'block', clear: 'both' }}
|
||||
>
|
||||
return (
|
||||
<span style={{ display: 'block', clear: 'both' }} >
|
||||
{this.props.collapsed ? null : listItems}
|
||||
</span>
|
||||
}
|
||||
|
||||
return null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme()(TreeNodeSubnodes)
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
nodeOrder: state.settings.nodeOrder,
|
||||
}
|
||||
}
|
||||
|
||||
export default withTheme()(connect(mapStateToProps)(TreeNodeSubnodes))
|
||||
|
||||
@@ -6,7 +6,6 @@ export interface TreeNodeProps extends React.HTMLAttributes<HTMLElement> {
|
||||
treeNode: q.TreeNode
|
||||
name?: string | undefined
|
||||
collapsed?: boolean | undefined
|
||||
toggleCollapsed: () => void
|
||||
didSelectNode?: (node: q.TreeNode) => void
|
||||
theme: Theme
|
||||
}
|
||||
@@ -24,25 +23,22 @@ class TreeNodeTitle extends React.Component<TreeNodeProps, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
private didSelectNode = () => {
|
||||
if (this.props.treeNode.message) {
|
||||
this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const style: React.CSSProperties = {
|
||||
lineHeight: '1em',
|
||||
whiteSpace: 'nowrap',
|
||||
}
|
||||
return <span
|
||||
style={style}
|
||||
onClick={() => {
|
||||
this.toggle()
|
||||
this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (this.props.treeNode.message) {
|
||||
this.props.didSelectNode && this.props.didSelectNode(this.props.treeNode)
|
||||
}
|
||||
}}
|
||||
>
|
||||
{this.renderExpander()} {this.renderSourceEdge()} {this.renderCollapsedSubnodes()} {this.renderValue()}
|
||||
</span>
|
||||
return (
|
||||
<span style={style} onMouseOver={this.didSelectNode}>
|
||||
{this.renderExpander()} {this.renderSourceEdge()} {this.renderCollapsedSubnodes()} {this.renderValue()}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
private renderSourceEdge() {
|
||||
@@ -67,16 +63,10 @@ class TreeNodeTitle extends React.Component<TreeNodeProps, {}> {
|
||||
display: 'inline-block',
|
||||
}
|
||||
return this.props.treeNode.message
|
||||
? <span
|
||||
style={style}
|
||||
> = {this.props.treeNode.message.value.toString()}</span>
|
||||
? <span style={style}> = {this.props.treeNode.message.value.toString()}</span>
|
||||
: null
|
||||
}
|
||||
|
||||
private toggle() {
|
||||
this.props.toggleCollapsed()
|
||||
}
|
||||
|
||||
private renderExpander() {
|
||||
if (this.props.treeNode.edgeCount() === 0) {
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user