Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type SetTreeVisibilityAction = ReturnType<typeof setTreeVisibilityAction>;
type SetExpandedTreeGroupsByKeysAction = ReturnType<typeof setExpandedTreeGroupsByKeysAction>;
type SetExpandedTreeGroupsByIdsAction = ReturnType<typeof setExpandedTreeGroupsByIdsAction>;
type ExpandParentGroupsOfTreeAction = ReturnType<typeof expandParentGroupsOfTreeAction>;
type FocusTreeAction = ReturnType<typeof focusTreeAction>;
type ToggleAllTreesAction = ReturnType<typeof toggleAllTreesAction>;
type ToggleInactiveTreesAction = ReturnType<typeof toggleInactiveTreesAction>;
type ToggleTreeGroupAction = ReturnType<typeof toggleTreeGroupAction>;
Expand Down Expand Up @@ -119,6 +120,7 @@ export type SkeletonTracingAction =
| SetExpandedTreeGroupsByKeysAction
| SetExpandedTreeGroupsByIdsAction
| ExpandParentGroupsOfTreeAction
| FocusTreeAction
| ToggleInactiveTreesAction
| ToggleTreeGroupAction
| NoAction
Expand Down Expand Up @@ -401,6 +403,12 @@ export const expandParentGroupsOfTreeAction = (tree: Tree) =>
tree,
}) as const;

export const focusTreeAction = (tree: Tree) =>
({
type: "FOCUS_TREE",
tree,
}) as const;

export const setTreeVisibilityAction = (treeId: number | null | undefined, isVisible: boolean) =>
({
type: "SET_TREE_VISIBILITY",
Expand Down
12 changes: 12 additions & 0 deletions frontend/javascripts/viewer/model/helpers/event_bus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { type Emitter, createNanoEvents } from "nanoevents";

type ActionPayload = {
type: string;
[key: string]: any;
};

type Events = {
[actionType: string]: (action: ActionPayload) => void;
};

export const eventBus: Emitter<Events> = createNanoEvents<Events>();
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { Dispatch } from "redux";
import type { Action } from "viewer/model/actions/actions";
import { eventBus } from "./event_bus";

export const eventEmitterMiddleware =
<A extends Action>() =>
(next: Dispatch<A>) =>
(action: A) => {
eventBus.emit(action.type, action);
return next(action);
};
14 changes: 14 additions & 0 deletions frontend/javascripts/viewer/model/helpers/listener_helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useEffect, useRef } from "react";
import type { WebknossosState } from "viewer/store";
import Store from "viewer/store";
import { eventBus } from "./event_bus";

// Allows to listen on a certain property of the store.
// This function should only be used when listening to the Store
Expand Down Expand Up @@ -41,4 +43,16 @@ export function listenToStoreProperty<T>(
// return the unsubscribe function
return Store.subscribe(handleChange);
}

export function useReduxActionListener(actionType: string, callback: () => void) {
const callbackRef = useRef(callback);
callbackRef.current = callback;
useEffect(() => {
const unsubscribe = eventBus.on(actionType, callbackRef.current);
return () => {
unsubscribe();
};
}, [actionType]);
}

export default {};
8 changes: 7 additions & 1 deletion frontend/javascripts/viewer/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import UiReducer from "viewer/model/reducers/ui_reducer";
import UserReducer from "viewer/model/reducers/user_reducer";
import ViewModeReducer from "viewer/model/reducers/view_mode_reducer";
import VolumeTracingReducer from "viewer/model/reducers/volumetracing_reducer";
import { eventEmitterMiddleware } from "./model/helpers/event_emitter_middleware";
import FlycamInfoCacheReducer from "./model/reducers/flycam_info_cache_reducer";
import OrganizationReducer from "./model/reducers/organization_reducer";
import type { StartAIJobModalState } from "./view/action-bar/starting_job_modals";
Expand Down Expand Up @@ -610,7 +611,12 @@ export const combinedReducer = reduceReducers(
const store = createStore<WebknossosState, Action, unknown, unknown>(
enableBatching(combinedReducer as any),
defaultState,
applyMiddleware(actionLoggerMiddleware, overwriteActionMiddleware, sagaMiddleware as Middleware),
applyMiddleware(
actionLoggerMiddleware,
overwriteActionMiddleware,
sagaMiddleware as Middleware,
eventEmitterMiddleware,
),
);

export function startSaga(saga: Saga<any[]>) {
Expand Down
2 changes: 2 additions & 0 deletions frontend/javascripts/viewer/view/context_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import {
deleteBranchpointByIdAction,
deleteEdgeAction,
expandParentGroupsOfTreeAction,
focusTreeAction,
mergeTreesAction,
setActiveNodeAction,
setTreeVisibilityAction,
Expand Down Expand Up @@ -624,6 +625,7 @@ function getNodeContextMenuOptions({
key: "focus-tree",
onClick: () => {
Store.dispatch(expandParentGroupsOfTreeAction(clickedTree));
Store.dispatch(focusTreeAction(clickedTree));
},
label: "Focus Tree in Skeleton Tab",
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,20 @@ class SkeletonTabView extends React.PureComponent<Props, State> {
});
};

componentDidUpdate(prevProps: Props) {
if (this.props.skeletonTracing?.activeTreeId !== prevProps.skeletonTracing?.activeTreeId) {
if (this.props.skeletonTracing?.activeTreeId != null) {
this.setState({
selectedTreeIds: [this.props.skeletonTracing.activeTreeId],
});
} else {
this.setState({
selectedTreeIds: [],
});
}
}
}

render() {
const { skeletonTracing } = this.props;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
toggleTreeAction,
toggleTreeGroupAction,
} from "viewer/model/actions/skeletontracing_actions";
import { useReduxActionListener } from "viewer/model/helpers/listener_helpers";
import type { Tree, TreeGroup, TreeMap } from "viewer/model/types/tree_types";
import { api } from "viewer/singletons";
import { Store } from "viewer/singletons";
Expand Down Expand Up @@ -98,13 +99,9 @@ function TreeHierarchyView(props: Props) {

useEffect(() => {
// scroll to active tree if it changes
if (treeRef.current && activeTreeId) {
const activeTreeKey = getNodeKey(GroupTypeEnum.TREE, activeTreeId);

if (activeTreeId) {
// For some React rendering/timing reasons, the target element might not be rendered yet. That messes with calculating the offsets for scrolling. Hence delay this a bit
setTimeout(() => {
if (treeRef.current) treeRef.current.scrollTo({ key: activeTreeKey, align: "auto" });
}, 50);
setTimeout(() => scrollToActiveTree(), 50);

// Make sure to select the active tree (for highlighting etc)
// Remember, the active tree can be changed by actions outside of this component
Expand Down Expand Up @@ -278,19 +275,26 @@ function TreeHierarchyView(props: Props) {
);
if (expandedGroups == null) return;
setExpandedGroups(expandedGroups);
setTimeout(() => {
if (treeRef.current && activeTreeId)
treeRef.current.scrollTo({
key: getNodeKey(GroupTypeEnum.TREE, activeTreeId),
align: "auto",
});
}, 300);
}, [activeTreeId]);

useEffect(
() => treeRef.current?.scrollTo({ key: selectedKeys[0], align: "auto" }),
[selectedKeys[0]],
);
const scrollToActiveTree = () => {
if (activeTreeId && treeRef.current) {
treeRef.current.scrollTo({
key: getNodeKey(GroupTypeEnum.TREE, activeTreeId),
align: "auto",
});
}
};

// Scroll to the active key after the component has been rendered.
// This is necessary outside of the useEffect hooks because a longer delay is needed to ensure the active tree has been rendered.
// biome-ignore lint/correctness/useExhaustiveDependencies: This should be equivalent to componentDidMount
useEffect(() => {
setTimeout(scrollToActiveTree, 900);
}, []);

// Allow scrolling to the active tree even if it is not changed
useReduxActionListener("FOCUS_TREE", scrollToActiveTree);

return (
<>
Expand Down
2 changes: 2 additions & 0 deletions unreleased_changes/8689.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Fixed
- Fixed that the skeleton tab was not always reflecting the active tree. This makes it easier to navigate between comments and trees, for example.