Work in progress

This commit is contained in:
Thomas Nordquist
2019-01-08 23:58:24 +01:00
parent b44f352804
commit 269061bdc8
5 changed files with 53 additions and 31 deletions

View File

@@ -118,9 +118,7 @@ class Settings extends React.Component<Props, {}> {
<Select <Select
value={nodeOrder} value={nodeOrder}
onChange={ (e: React.ChangeEvent<HTMLSelectElement>) => { onChange={ (e: React.ChangeEvent<HTMLSelectElement>) => {
window.requestAnimationFrame(() => {
actions.setNodeOrder(e.target.value) actions.setNodeOrder(e.target.value)
})
}} }}
input={<Input name="node-order" id="node-order-label-placeholder" />} input={<Input name="node-order" id="node-order-label-placeholder" />}
displayEmpty={true} displayEmpty={true}

View File

@@ -54,7 +54,6 @@ class Tree extends React.Component<Props, TreeState> {
this.updateTimer = setTimeout(() => { this.updateTimer = setTimeout(() => {
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
console.log('doRender')
this.lastUpdate = performance.now() this.lastUpdate = performance.now()
this.updateTimer && clearTimeout(this.updateTimer) this.updateTimer && clearTimeout(this.updateTimer)
this.updateTimer = undefined this.updateTimer = undefined
@@ -97,12 +96,19 @@ class Tree extends React.Component<Props, TreeState> {
} }
public render() { public render() {
console.log('render called')
const style: React.CSSProperties = { const style: React.CSSProperties = {
lineHeight: '1.1', lineHeight: '1.1',
cursor: 'default', cursor: 'default',
} }
return <Typography style={style}> const performanceCallback = (ms: number) => {
average.push(Date.now(), ms)
}
return (
<Typography style={style}>
<TreeNode <TreeNode
animateChages={true} animateChages={true}
autoExpandLimit={this.props.autoExpandLimit} autoExpandLimit={this.props.autoExpandLimit}
@@ -112,11 +118,11 @@ class Tree extends React.Component<Props, TreeState> {
name="/" name="/"
collapsed={false} collapsed={false}
key="rootNode" key="rootNode"
performanceCallback={(ms: number) => { lastUpdate={0}
average.push(Date.now(), ms) performanceCallback={this.performanceCallback}
}}
/> />
</Typography> </Typography>
)
} }
} }

View File

@@ -29,6 +29,7 @@ const styles = (theme: Theme) => {
} }
interface Props { interface Props {
lastUpdate: number
animateChages: boolean animateChages: boolean
isRoot?: boolean isRoot?: boolean
treeNode: q.TreeNode treeNode: q.TreeNode
@@ -48,6 +49,7 @@ class TreeNode extends React.Component<Props, State> {
private dirtySubnodes: boolean = true private dirtySubnodes: boolean = true
private dirtyEdges: boolean = true private dirtyEdges: boolean = true
private dirtyMessage: boolean = true private dirtyMessage: boolean = true
private animationDirty: boolean = false
private cssAnimationWasSetAt?: number private cssAnimationWasSetAt?: number
@@ -103,6 +105,7 @@ class TreeNode extends React.Component<Props, State> {
|| this.dirtyEdges || this.dirtyEdges
|| this.dirtyMessage || this.dirtyMessage
|| this.dirtySubnodes || this.dirtySubnodes
|| this.animationDirty
|| shouldRenderToRemoveCssAnimation || shouldRenderToRemoveCssAnimation
} }
@@ -111,6 +114,12 @@ class TreeNode extends React.Component<Props, State> {
const renderTime = performance.now() - this.willUpdateTime const renderTime = performance.now() - this.willUpdateTime
this.props.performanceCallback(renderTime) this.props.performanceCallback(renderTime)
} }
// setTimeout(() => {
// this.setState(this.state)
// }, 500)
// this.addCssAnimation()
// setTimeout(this.removeCssAnimation, 500)
} }
public componentWillUpdate() { public componentWillUpdate() {
@@ -131,18 +140,36 @@ class TreeNode extends React.Component<Props, State> {
return this.props.treeNode.edgeCount() > this.props.autoExpandLimit return this.props.treeNode.edgeCount() > this.props.autoExpandLimit
} }
// private addCssAnimation = () => {
// const element = this.titleRef.current
// if ((this.dirtyEdges || this.dirtyMessage || this.dirtySubnodes) && element && isElementInViewport(element)) {
// element.style.animation = 'example 0.5s'
// }
// }
//
// private removeCssAnimation = () => {
// const element = this.titleRef.current
// if (element && element.style.animation) {
// element.style.animation = ''
// }
// }
public render() { public render() {
const animationStyle = this.indicatingChangeAnimationStyle()
const { classes } = this.props const { classes } = this.props
const isDirty = this.dirtyEdges || this.dirtyMessage || this.dirtySubnodes
this.dirtyEdges = this.dirtyMessage = this.dirtySubnodes = false this.dirtyEdges = this.dirtyMessage = this.dirtySubnodes = false
const shouldStartAnimation = (isDirty && !this.animationDirty) && !this.props.isRoot
const animation = shouldStartAnimation ? { animation: 'example 0.5s' } : {}
this.animationDirty = shouldStartAnimation
return ( return (
<div <div
key={this.props.treeNode.hash()} key={this.props.treeNode.hash()}
className={`${classes.node} ${!this.props.isRoot ? classes.hover : ''}`} className={`${classes.node} ${!this.props.isRoot ? classes.hover : ''}`}
onClick={this.didClickNode} onClick={this.didClickNode}
> >
<span ref={this.titleRef} style={animationStyle}> <span ref={this.titleRef} style={animation}>
<TreeNodeTitle <TreeNodeTitle
collapsed={this.collapsed()} collapsed={this.collapsed()}
treeNode={this.props.treeNode} treeNode={this.props.treeNode}
@@ -169,29 +196,10 @@ class TreeNode extends React.Component<Props, State> {
autoExpandLimit={this.props.autoExpandLimit} autoExpandLimit={this.props.autoExpandLimit}
didSelectNode={this.props.didSelectNode} didSelectNode={this.props.didSelectNode}
treeNode={this.props.treeNode} treeNode={this.props.treeNode}
lastUpdate={this.props.treeNode.lastUpdate}
/> />
) )
} }
private indicatingChangeAnimationStyle(): React.CSSProperties {
if (this.props.isRoot) {
return {}
}
if (this.cssAnimationWasSetAt && (performance.now() - this.cssAnimationWasSetAt) > 500) {
this.cssAnimationWasSetAt = undefined
return {}
}
const isInViewPort = this.titleRef.current && isElementInViewport(this.titleRef.current)
const isDirty = this.dirtyMessage || this.dirtyEdges
if (this.props.animateChages && isDirty && isInViewPort) {
if (!this.cssAnimationWasSetAt) {
this.cssAnimationWasSetAt = performance.now()
}
return { animation: 'example 0.5s' }
}
return {}
}
} }
export default withStyles(styles)(TreeNode) export default withStyles(styles)(TreeNode)

View File

@@ -7,6 +7,7 @@ import { AppState, NodeOrder } from '../../reducers'
import TreeNode from './TreeNode' import TreeNode from './TreeNode'
export interface Props { export interface Props {
lastUpdate: number
nodeOrder?: NodeOrder nodeOrder?: NodeOrder
animateChanges: boolean animateChanges: boolean
treeNode: q.TreeNode treeNode: q.TreeNode
@@ -54,6 +55,7 @@ class TreeNodeSubnodes extends React.Component<Props, {}> {
treeNode={node} treeNode={node}
didSelectNode={this.props.didSelectNode} didSelectNode={this.props.didSelectNode}
autoExpandLimit={this.props.autoExpandLimit} autoExpandLimit={this.props.autoExpandLimit}
lastUpdate={node.lastUpdate}
/> />
</div> </div>
)) ))

View File

@@ -7,6 +7,7 @@ export class TreeNode {
public edges: {[s: string]: Edge} = {} public edges: {[s: string]: Edge} = {}
public collapsed = false public collapsed = false
public messages: number = 0 public messages: number = 0
public lastUpdate: number = Date.now()
public onMerge = new EventDispatcher<void, TreeNode>(this) public onMerge = new EventDispatcher<void, TreeNode>(this)
public onEdgesChange = new EventDispatcher<void, TreeNode>(this) public onEdgesChange = new EventDispatcher<void, TreeNode>(this)
@@ -24,6 +25,13 @@ export class TreeNode {
this.onMerge.subscribe(() => { this.onMerge.subscribe(() => {
this.cachedLeafes = undefined this.cachedLeafes = undefined
this.cachedLeafMessageCount = undefined this.cachedLeafMessageCount = undefined
this.lastUpdate = Date.now()
})
this.onEdgesChange.subscribe(() => {
this.lastUpdate = Date.now()
})
this.onMessage.subscribe(() => {
this.lastUpdate = Date.now()
}) })
} }