Refactor
This commit is contained in:
@@ -22,10 +22,10 @@
|
||||
background-color: none;
|
||||
}
|
||||
25% {
|
||||
background-color: #3f51b5;
|
||||
background-color: #4f5781;
|
||||
}
|
||||
50% {
|
||||
background-color: #3f51b5;
|
||||
background-color: #4f5781;
|
||||
}
|
||||
100% {
|
||||
background-color: none;
|
||||
@@ -38,11 +38,11 @@
|
||||
color: inherit;
|
||||
}
|
||||
25% {
|
||||
background-color: #bfc9c8;
|
||||
background-color: #c0c8c0;
|
||||
color: #000;
|
||||
}
|
||||
50% {
|
||||
background-color: #bfc9c8;
|
||||
background-color: #c0c8c0;
|
||||
color: #000;
|
||||
}
|
||||
100% {
|
||||
|
||||
@@ -2,7 +2,9 @@ import * as q from '../../../backend/src/Model'
|
||||
import { ActionTypes } from '../reducers/Sidebar'
|
||||
import { AppState } from '../reducers'
|
||||
import { Dispatch } from 'redux'
|
||||
import { makePublishEvent, rendererEvents } from '../../../events'
|
||||
import { clearTopic } from './clearTopic'
|
||||
|
||||
export { clearTopic } from './clearTopic'
|
||||
|
||||
export const clearRetainedTopic = () => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
const selectedTopic = getState().tree.get('selectedTopic')
|
||||
@@ -19,38 +21,3 @@ export const setCompareMessage = (message?: q.Message) => (dispatch: Dispatch<an
|
||||
type: ActionTypes.SIDEBAR_SET_COMPARE_MESSAGE,
|
||||
})
|
||||
}
|
||||
|
||||
export const clearTopic = (topic: q.TreeNode<any>, recursive: boolean, subtopicClearLimit = 50) => (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
const { connectionId } = getState().connection
|
||||
if (!connectionId) {
|
||||
return
|
||||
}
|
||||
|
||||
const publishEvent = makePublishEvent(connectionId)
|
||||
const mqttMessage = {
|
||||
topic: topic.path(),
|
||||
payload: null,
|
||||
retain: true,
|
||||
qos: 0 as 0,
|
||||
}
|
||||
rendererEvents.emit(publishEvent, mqttMessage)
|
||||
|
||||
if (recursive) {
|
||||
topic
|
||||
.childTopics()
|
||||
.filter(topic => Boolean(topic.message && topic.message.value))
|
||||
.slice(0, subtopicClearLimit)
|
||||
.forEach(topic => {
|
||||
const mqttMessage = {
|
||||
topic: topic.path(),
|
||||
payload: null,
|
||||
retain: true,
|
||||
qos: 0 as 0,
|
||||
}
|
||||
rendererEvents.emit(publishEvent, mqttMessage)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@ import { globalActions } from './'
|
||||
import { setTopic } from './Publish'
|
||||
import { TopicViewModel } from '../model/TopicViewModel'
|
||||
const debounce = require('lodash.debounce')
|
||||
export { clearTopic } from './clearTopic'
|
||||
|
||||
export { moveSelectionUpOrDownwards, moveInward, moveOutward } from './visibleTreeTraversal'
|
||||
import { moveSelectionUpOrDownwards } from './visibleTreeTraversal'
|
||||
|
||||
export const selectTopic = (topic: q.TreeNode<TopicViewModel>) => (
|
||||
dispatch: Dispatch<any>,
|
||||
|
||||
41
app/src/actions/clearTopic.ts
Normal file
41
app/src/actions/clearTopic.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import * as q from '../../../backend/src/Model'
|
||||
import { AppState } from '../reducers'
|
||||
import { Dispatch } from 'redux'
|
||||
import { makePublishEvent, rendererEvents } from '../../../events'
|
||||
import { moveSelectionUpOrDownwards } from './visibleTreeTraversal'
|
||||
|
||||
export const clearTopic = (topic: q.TreeNode<any>, recursive: boolean, subtopicClearLimit = 50) => (
|
||||
dispatch: Dispatch<any>,
|
||||
getState: () => AppState
|
||||
) => {
|
||||
dispatch(moveSelectionUpOrDownwards('next'))
|
||||
|
||||
const { connectionId } = getState().connection
|
||||
if (!connectionId) {
|
||||
return
|
||||
}
|
||||
const publishEvent = makePublishEvent(connectionId)
|
||||
const mqttMessage = {
|
||||
topic: topic.path(),
|
||||
payload: null,
|
||||
retain: true,
|
||||
qos: 0 as 0,
|
||||
}
|
||||
rendererEvents.emit(publishEvent, mqttMessage)
|
||||
if (recursive) {
|
||||
topic
|
||||
.childTopics()
|
||||
.filter(topic => Boolean(topic.message && topic.message.value))
|
||||
.slice(0, subtopicClearLimit)
|
||||
.forEach((topic, idx) => {
|
||||
const mqttMessage = {
|
||||
topic: topic.path(),
|
||||
payload: null,
|
||||
retain: true,
|
||||
qos: 0 as 0,
|
||||
}
|
||||
// Rate limit deletion
|
||||
setTimeout(() => rendererEvents.emit(publishEvent, mqttMessage), 20 * idx)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ export const moveSelectionUpOrDownwards = (direction: 'next' | 'previous') => (
|
||||
const state = getState()
|
||||
const selected = state.tree.get('selectedTopic')
|
||||
const tree = state.tree.get('tree')
|
||||
|
||||
if (!selected || !tree) {
|
||||
if (tree) {
|
||||
dispatch(selectTopic(tree))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react'
|
||||
import ChartPanel from '../ChartPanel'
|
||||
import ReactSplitPane from 'react-split-pane'
|
||||
import Tree from '../Tree/Tree'
|
||||
import Tree from '../Tree'
|
||||
import { AppState } from '../../reducers'
|
||||
import { ChartParameters } from '../../reducers/Charts'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
@@ -41,7 +41,13 @@ function SearchBar(props: {
|
||||
const tagElementIsNotBlacklisted =
|
||||
document.activeElement && tagNameBlacklist.indexOf(document.activeElement.tagName) === -1
|
||||
|
||||
if ((isCharacter || isAllowedControlCharacter) && !hasFocus && tagElementIsNotBlacklisted && hasConnection) {
|
||||
if (
|
||||
(isCharacter || isAllowedControlCharacter) &&
|
||||
!event.defaultPrevented &&
|
||||
!hasFocus &&
|
||||
tagElementIsNotBlacklisted &&
|
||||
hasConnection
|
||||
) {
|
||||
// Focus input field, no preventDefault the event will reach the input element after it has been focussed
|
||||
inputRef.current && inputRef.current.focus()
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import * as React from 'react'
|
||||
import TreeNode from './TreeNode'
|
||||
import { SettingsState } from '../../reducers/Settings'
|
||||
import { sortedNodes } from '../../sortedNodes'
|
||||
import * as q from '../../../../../backend/src/Model'
|
||||
import React from 'react'
|
||||
import TreeNode from '.'
|
||||
import { SettingsState } from '../../../reducers/Settings'
|
||||
import { sortedNodes } from '../../../sortedNodes'
|
||||
import { Theme, withStyles } from '@material-ui/core'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { TopicViewModel } from '../../../model/TopicViewModel'
|
||||
import { treeActions } from '../../../actions'
|
||||
|
||||
export interface Props {
|
||||
treeNode: q.TreeNode<TopicViewModel>
|
||||
@@ -14,6 +15,7 @@ export interface Props {
|
||||
selectedTopic?: q.TreeNode<TopicViewModel>
|
||||
selectTopicAction: (treeNode: q.TreeNode<any>) => void
|
||||
settings: SettingsState
|
||||
actions: typeof treeActions
|
||||
}
|
||||
|
||||
interface State {
|
||||
@@ -60,6 +62,7 @@ class TreeNodeSubnodes extends React.Component<Props, State> {
|
||||
lastUpdate={node.lastUpdate}
|
||||
selectTopicAction={this.props.selectTopicAction}
|
||||
settings={this.props.settings}
|
||||
actions={this.props.actions}
|
||||
/>
|
||||
)
|
||||
})
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import * as q from '../../../../../backend/src/Model'
|
||||
import { withStyles, Theme } from '@material-ui/core'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { Base64Message } from '../../../../backend/src/Model/Base64Message'
|
||||
import { TopicViewModel } from '../../../model/TopicViewModel'
|
||||
import { Base64Message } from '../../../../../backend/src/Model/Base64Message'
|
||||
|
||||
export interface TreeNodeProps extends React.HTMLAttributes<HTMLElement> {
|
||||
treeNode: q.TreeNode<TopicViewModel>
|
||||
@@ -0,0 +1,22 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
export function useAnimationToIndicateTopicUpdate(
|
||||
lastUpdate: number,
|
||||
selected: boolean,
|
||||
setShowUpdateAnimation: React.Dispatch<React.SetStateAction<boolean>>,
|
||||
showUpdateAnimation: boolean
|
||||
) {
|
||||
useEffect(() => {
|
||||
if (Date.now() - lastUpdate < 3000 && !selected) {
|
||||
setShowUpdateAnimation(true)
|
||||
}
|
||||
}, [lastUpdate, selected])
|
||||
useEffect(() => {
|
||||
if (showUpdateAnimation) {
|
||||
const timeout = setTimeout(() => setShowUpdateAnimation(false), 500)
|
||||
return function cleanup() {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [showUpdateAnimation])
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import * as q from '../../../../../../backend/src/Model'
|
||||
import React, { useCallback } from 'react'
|
||||
import { KeyCodes } from '../../../../utils/KeyCodes'
|
||||
import { treeActions } from '../../../../actions'
|
||||
|
||||
export function useDeleteKeyCallback(topic: q.TreeNode<any>, actions: typeof treeActions) {
|
||||
return useCallback(
|
||||
(event: React.KeyboardEvent) => {
|
||||
if (event.keyCode === KeyCodes.delete || event.keyCode === KeyCodes.backspace) {
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
actions.clearTopic(topic, true, 50)
|
||||
}
|
||||
},
|
||||
[topic]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Props } from '..'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export function useIsAllowedToAutoExpandState(props: Props): boolean {
|
||||
const { settings, treeNode, isRoot } = props
|
||||
const [isAllowedToAutoExpand, setAllowAutoExpand] = useState(false)
|
||||
useEffect(() => {
|
||||
const newIsAllowedToAutoExpand = isRoot || treeNode.edgeCount() <= settings.get('autoExpandLimit')
|
||||
if (newIsAllowedToAutoExpand !== isAllowedToAutoExpand) {
|
||||
setAllowAutoExpand(newIsAllowedToAutoExpand)
|
||||
}
|
||||
}, [treeNode.edgeCount(), settings.get('autoExpandLimit')])
|
||||
return isAllowedToAutoExpand
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import * as q from '../../../../../../backend/src/Model'
|
||||
import React, { useEffect } from 'react'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { TopicViewModel } from '../../../../model/TopicViewModel'
|
||||
|
||||
export function useViewModelSubscriptions(
|
||||
treeNode: q.TreeNode<TopicViewModel>,
|
||||
@@ -11,6 +11,7 @@ export function useViewModelSubscriptions(
|
||||
const selectionDidChange = () => {
|
||||
const selected = treeNode.viewModel && treeNode.viewModel.isSelected()
|
||||
treeNode.viewModel && setSelected(Boolean(selected))
|
||||
|
||||
if (selected && nodeRef && nodeRef.current) {
|
||||
nodeRef.current.focus({ preventScroll: false })
|
||||
}
|
||||
@@ -1,14 +1,16 @@
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import * as q from '../../../../../backend/src/Model'
|
||||
import React, { useState, useRef, useEffect, useMemo, useCallback } from 'react'
|
||||
import TreeNodeSubnodes from './TreeNodeSubnodes'
|
||||
import TreeNodeTitle from './TreeNodeTitle'
|
||||
import { SettingsState } from '../../reducers/Settings'
|
||||
import { SettingsState } from '../../../reducers/Settings'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { useViewModelSubscriptions } from './useViewModelSubscriptions'
|
||||
const debounce = require('lodash.debounce')
|
||||
|
||||
declare var performance: any
|
||||
import { TopicViewModel } from '../../../model/TopicViewModel'
|
||||
import { useViewModelSubscriptions } from './effects/useViewModelSubscriptions'
|
||||
import { treeActions } from '../../../actions'
|
||||
import { lightBlue, teal, amber, green, deepPurple, blueGrey } from '@material-ui/core/colors'
|
||||
import { useAnimationToIndicateTopicUpdate } from './effects/useAnimationToIndicateTopicUpdate'
|
||||
import { useDeleteKeyCallback } from './effects/useDeleteKeyCallback'
|
||||
import { useIsAllowedToAutoExpandState } from './effects/useIsAllowedToAutoExpandState'
|
||||
|
||||
const styles = (theme: Theme) => {
|
||||
return {
|
||||
@@ -21,6 +23,9 @@ const styles = (theme: Theme) => {
|
||||
node: {
|
||||
display: 'block',
|
||||
marginLeft: '10px',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.type === 'light' ? blueGrey[100] : theme.palette.primary.light,
|
||||
},
|
||||
},
|
||||
topicSelect: {
|
||||
float: 'right' as 'right',
|
||||
@@ -32,11 +37,9 @@ const styles = (theme: Theme) => {
|
||||
marginLeft: theme.spacing(1.5),
|
||||
},
|
||||
selected: {
|
||||
backgroundColor: theme.palette.type === 'dark' ? 'rgba(170, 170, 170, 0.55)' : 'rgba(170, 170, 170, 0.55)',
|
||||
},
|
||||
hover: {
|
||||
backgroundColor: theme.palette.type === 'dark' ? 'rgba(100, 100, 100, 0.55)' : 'rgba(200, 200, 200, 0.55)',
|
||||
backgroundColor: (theme.palette.type === 'light' ? blueGrey[300] : theme.palette.primary.main) + ' !important',
|
||||
},
|
||||
hover: {},
|
||||
title: {
|
||||
borderRadius: '4px',
|
||||
lineHeight: '1em',
|
||||
@@ -49,7 +52,7 @@ const styles = (theme: Theme) => {
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
export interface Props {
|
||||
isRoot?: boolean
|
||||
treeNode: q.TreeNode<TopicViewModel>
|
||||
name?: string | undefined
|
||||
@@ -57,44 +60,26 @@ interface Props {
|
||||
classes: any
|
||||
className?: string
|
||||
lastUpdate: number
|
||||
actions: typeof treeActions
|
||||
selectTopicAction: (treeNode: q.TreeNode<any>) => void
|
||||
theme: Theme
|
||||
settings: SettingsState
|
||||
}
|
||||
|
||||
function useIsAllowedToAutoExpandState(props: Props): boolean {
|
||||
const { settings, treeNode, isRoot } = props
|
||||
const [isAllowedToAutoExpand, setAllowAutoExpand] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const newIsAllowedToAutoExpand = isRoot || treeNode.edgeCount() <= settings.get('autoExpandLimit')
|
||||
if (newIsAllowedToAutoExpand !== isAllowedToAutoExpand) {
|
||||
setAllowAutoExpand(newIsAllowedToAutoExpand)
|
||||
}
|
||||
}, [treeNode.edgeCount(), settings.get('autoExpandLimit')])
|
||||
|
||||
return isAllowedToAutoExpand
|
||||
}
|
||||
|
||||
function TreeNodeComponent(props: Props) {
|
||||
const { classes, className, settings, theme, treeNode, lastUpdate, name } = props
|
||||
|
||||
const { actions, classes, className, settings, theme, treeNode, lastUpdate, name } = props
|
||||
const deleteTopicCallback = useDeleteKeyCallback(treeNode, actions)
|
||||
const [showUpdateAnimation, setShowUpdateAnimation] = useState(false)
|
||||
const [collapsedOverride, setCollapsedOverride] = useState<boolean | undefined>(undefined)
|
||||
const [isHovering, setIsHovering] = useState(false)
|
||||
const [selected, setSelected] = useState(false)
|
||||
const nodeRef = useRef<HTMLDivElement>()
|
||||
const isAllowedToAutoExpand = useIsAllowedToAutoExpandState(props)
|
||||
useViewModelSubscriptions(treeNode, nodeRef, setSelected, setCollapsedOverride)
|
||||
useAnimationToIndicateTopicUpdate(lastUpdate, setShowUpdateAnimation, showUpdateAnimation)
|
||||
useAnimationToIndicateTopicUpdate(lastUpdate, selected, setShowUpdateAnimation, showUpdateAnimation)
|
||||
|
||||
const isCollapsed =
|
||||
Boolean(collapsedOverride) === collapsedOverride ? Boolean(collapsedOverride) : !isAllowedToAutoExpand
|
||||
|
||||
const setHover = debounce((hover: boolean) => {
|
||||
setIsHovering(hover)
|
||||
}, 45)
|
||||
|
||||
const toggle = useCallback(() => {
|
||||
setCollapsedOverride(!isCollapsed)
|
||||
}, [isCollapsed])
|
||||
@@ -130,17 +115,11 @@ function TreeNodeComponent(props: Props) {
|
||||
|
||||
const mouseOver = (event: React.MouseEvent) => {
|
||||
event.stopPropagation()
|
||||
setHover(true)
|
||||
if (settings.get('selectTopicWithMouseOver') && treeNode && treeNode.message && treeNode.message.value) {
|
||||
didSelectTopic()
|
||||
}
|
||||
}
|
||||
|
||||
const mouseOut = (event: React.MouseEvent) => {
|
||||
event.stopPropagation()
|
||||
setHover(false)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
treeNode.viewModel && treeNode.viewModel.setExpanded(!isCollapsed, false)
|
||||
}, [isCollapsed])
|
||||
@@ -157,6 +136,7 @@ function TreeNodeComponent(props: Props) {
|
||||
lastUpdate={treeNode.lastUpdate}
|
||||
selectTopicAction={props.selectTopicAction}
|
||||
settings={settings}
|
||||
actions={props.actions}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -167,19 +147,19 @@ function TreeNodeComponent(props: Props) {
|
||||
? { willChange: 'auto', translateZ: 0, animation: `${animationName} 0.5s` }
|
||||
: {}
|
||||
|
||||
const highlightClass = selected ? classes.selected : isHovering ? classes.hover : ''
|
||||
const highlightClass = selected ? classes.selected : ''
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
key={treeNode.hash()}
|
||||
className={`${classes.node} ${className} ${highlightClass} ${classes.title}`}
|
||||
style={animation}
|
||||
onMouseOver={mouseOver}
|
||||
onMouseOut={mouseOut}
|
||||
onMouseEnter={mouseOver}
|
||||
onFocus={didObtainFocus}
|
||||
onClick={didClickTitle}
|
||||
ref={nodeRef as any}
|
||||
tabIndex={-1}
|
||||
onKeyDown={deleteTopicCallback}
|
||||
>
|
||||
<TreeNodeTitle
|
||||
toggleCollapsed={toggleCollapsed}
|
||||
@@ -192,26 +172,7 @@ function TreeNodeComponent(props: Props) {
|
||||
{renderNodes()}
|
||||
</div>
|
||||
)
|
||||
}, [lastUpdate, treeNode, name, isCollapsed, selected, showUpdateAnimation, isHovering])
|
||||
}, [lastUpdate, treeNode, name, isCollapsed, selected, theme, showUpdateAnimation])
|
||||
}
|
||||
|
||||
export default withStyles(styles, { withTheme: true })(TreeNodeComponent)
|
||||
function useAnimationToIndicateTopicUpdate(
|
||||
lastUpdate: number,
|
||||
setShowUpdateAnimation: React.Dispatch<React.SetStateAction<boolean>>,
|
||||
showUpdateAnimation: boolean
|
||||
) {
|
||||
useEffect(() => {
|
||||
if (Date.now() - lastUpdate < 3000) {
|
||||
setShowUpdateAnimation(true)
|
||||
}
|
||||
}, [lastUpdate])
|
||||
useEffect(() => {
|
||||
if (showUpdateAnimation) {
|
||||
const timeout = setTimeout(() => setShowUpdateAnimation(false), 500)
|
||||
return function cleanup() {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [showUpdateAnimation])
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
import React from 'react'
|
||||
import React, { useCallback } from 'react'
|
||||
import TreeNode from './TreeNode'
|
||||
import { AppState } from '../../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
@@ -7,7 +7,6 @@ import { connect } from 'react-redux'
|
||||
import { SettingsState } from '../../reducers/Settings'
|
||||
import { TopicViewModel } from '../../model/TopicViewModel'
|
||||
import { treeActions } from '../../actions'
|
||||
import { useGlobalKeyEventHandler } from '../../effects/useGlobalKeyEventHandler'
|
||||
import { KeyCodes } from '../../utils/KeyCodes'
|
||||
|
||||
const MovingAverage = require('moving-average')
|
||||
@@ -30,16 +29,27 @@ interface State {
|
||||
lastUpdate: number
|
||||
}
|
||||
|
||||
function ArrowKeyHandler(props: {
|
||||
action: (direction: 'next' | 'previous') => any
|
||||
leftAction: () => void
|
||||
rightAction: () => void
|
||||
}) {
|
||||
useGlobalKeyEventHandler(KeyCodes.arrow_down, () => props.action('next'), [props.action])
|
||||
useGlobalKeyEventHandler(KeyCodes.arrow_up, () => props.action('previous'), [props.action])
|
||||
useGlobalKeyEventHandler(KeyCodes.arrow_right, props.rightAction, [props.action])
|
||||
useGlobalKeyEventHandler(KeyCodes.arrow_left, props.leftAction, [props.action])
|
||||
return <div />
|
||||
function useArrowKeyEventHandler(actions: typeof treeActions) {
|
||||
return (event: React.KeyboardEvent) => {
|
||||
switch (event.keyCode) {
|
||||
case KeyCodes.arrow_down:
|
||||
actions.moveSelectionUpOrDownwards('next')
|
||||
event.preventDefault()
|
||||
break
|
||||
case KeyCodes.arrow_up:
|
||||
actions.moveSelectionUpOrDownwards('previous')
|
||||
event.preventDefault()
|
||||
break
|
||||
case KeyCodes.arrow_left:
|
||||
actions.moveOutward()
|
||||
event.preventDefault()
|
||||
break
|
||||
case KeyCodes.arrow_right:
|
||||
actions.moveInward()
|
||||
event.preventDefault()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TreeComponent extends React.PureComponent<Props, State> {
|
||||
@@ -52,6 +62,7 @@ class TreeComponent extends React.PureComponent<Props, State> {
|
||||
this.state = { lastUpdate: 0 }
|
||||
}
|
||||
|
||||
private keyEventHandler = useArrowKeyEventHandler(this.props.actions)
|
||||
private performanceCallback = (ms: number) => {
|
||||
average.push(Date.now(), ms)
|
||||
}
|
||||
@@ -124,16 +135,12 @@ class TreeComponent extends React.PureComponent<Props, State> {
|
||||
overflowX: 'hidden',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
outline: '24px black !important',
|
||||
paddingBottom: '16px', // avoid conflict with chart panel Resizer
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={style}>
|
||||
<ArrowKeyHandler
|
||||
action={this.props.actions.moveSelectionUpOrDownwards}
|
||||
leftAction={this.props.actions.moveOutward}
|
||||
rightAction={this.props.actions.moveInward}
|
||||
/>
|
||||
<div style={style} tabIndex={0} onKeyDown={this.keyEventHandler}>
|
||||
<TreeNode
|
||||
key={tree.hash()}
|
||||
isRoot={true}
|
||||
@@ -142,6 +149,7 @@ class TreeComponent extends React.PureComponent<Props, State> {
|
||||
collapsed={false}
|
||||
settings={this.props.settings}
|
||||
lastUpdate={tree.lastUpdate}
|
||||
actions={this.props.actions}
|
||||
selectTopicAction={this.props.actions.selectTopic}
|
||||
/>
|
||||
</div>
|
||||
@@ -4,8 +4,8 @@ import { EventDispatcher } from '../../../events'
|
||||
export class TopicViewModel implements Destroyable {
|
||||
private selected: boolean
|
||||
private expanded: boolean
|
||||
public selectionChange = new EventDispatcher<void, TopicViewModel>()
|
||||
public expandedChange = new EventDispatcher<void, TopicViewModel>()
|
||||
public selectionChange = new EventDispatcher<void>()
|
||||
public expandedChange = new EventDispatcher<void>()
|
||||
|
||||
public constructor() {
|
||||
this.selected = false
|
||||
|
||||
@@ -44,7 +44,6 @@ export const globalState: Reducer<Record<GlobalStateInterface>, GlobalAction> =
|
||||
action
|
||||
): GlobalState => {
|
||||
trackEvent(action.type)
|
||||
console.log(action.type)
|
||||
|
||||
switch (action.type) {
|
||||
case ActionTypes.showUpdateNotification:
|
||||
|
||||
Reference in New Issue
Block a user