refactor(renderer): consolidate navigateTo into navigation slice (P1-11)

Delete the useUIController.navigateTo duplicate; augment slice version with
task-with-run lookup (via get().snapshot) so notification-click and command
palette share one codepath. App.tsx now reads navigateTo from the store.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-16 22:51:26 -04:00
1 parent 66f5e0923d
commit d42901b86d
3 files changed
+29 -51

No files matched your search

+1 -4
View File
@@ -23,6 +23,7 @@ export function App() {
const setError = useAppStore((s) => s.setError);
const setSelectedRunId = useAppStore((s) => s.setSelectedRunId);
const setConsoleOpen = useAppStore((s) => s.setConsoleOpen);
const navigateTo = useAppStore((s) => s.navigateTo);
const showCustomTitleBar = window.agentCompany.platform !== "darwin";
const isMac = !showCustomTitleBar;
@@ -77,10 +78,6 @@ export function App() {
[paletteActions],
);
const navigateTo = useCallback((targetSection: Parameters<typeof ui.navigateTo>[0], entityId?: string) => {
ui.navigateTo(targetSection, entityId, company.runs, company.tasks);
}, [ui, company.runs, company.tasks]);
useCommandPaletteHotkeys({
commandPaletteOpen: ui.commandPaletteOpen,
setCommandPaletteOpen: ui.setCommandPaletteOpen,
+1 -34
View File
@@ -1,5 +1,6 @@
import { useCallback, useDeferredValue, useMemo } from "react";
import type { AgentRecord, GoalRecord, ProjectRecord, RunRecord, SectionId, TaskRecord } from "@shared/types";
import { createTranslator } from "../i18n";
import { useAppStore } from "../state/store";
import { useFocusTrap, useReducedMotion } from "../components/ui";
@@ -84,15 +85,6 @@ export function useUIController() {
const selectedPaletteIndex = useAppStore((s) => s.selectedPaletteIndex);
const setSelectedPaletteIndex = useAppStore((s) => s.setSelectedPaletteIndex);
const setSelectedAgentId = useAppStore((s) => s.setSelectedAgentId);
const setSelectedConnectorId = useAppStore((s) => s.setSelectedConnectorId);
const setSelectedRunId = useAppStore((s) => s.setSelectedRunId);
const setSelectedTaskId = useAppStore((s) => s.setSelectedTaskId);
const setSelectedApprovalId = useAppStore((s) => s.setSelectedApprovalId);
const setSelectedGoalId = useAppStore((s) => s.setSelectedGoalId);
const setSelectedProjectId = useAppStore((s) => s.setSelectedProjectId);
const setSelectedCommunicationEntityId = useAppStore((s) => s.setSelectedCommunicationEntityId);
const handleLocaleChange = useCallback(async (newLocale: AppLocale) => {
useAppStore.getState().setLocale(newLocale);
try { await window.agentCompany.updateSettings({ locale: newLocale }); } catch { /* local state already updated */ }
@@ -100,32 +92,8 @@ export function useUIController() {
const paletteTrapRef = useFocusTrap(commandPaletteOpen);
// These are passed in from useAppController which has access to entity lists
// For standalone palette search, we expose the query and let consumers compute results
const paletteQuery = useDeferredValue(commandPaletteSearch.trim().toLowerCase());
const navigateTo = useCallback((targetSection: SectionId, entityId?: string, runs?: RunRecord[], tasks?: TaskRecord[]) => {
setSection(targetSection);
if (entityId) {
if (targetSection === "agents") setSelectedAgentId(entityId);
else if (targetSection === "connectors") setSelectedConnectorId(entityId);
else if (targetSection === "runs") { setSelectedRunId(entityId); setConsoleOpen(true); }
else if (targetSection === "tasks") {
const matchingTask = tasks?.find((task) => task.id === entityId) ?? null;
if (matchingTask) { setSelectedTaskId(matchingTask.id); }
else {
const matchingRun = runs?.find((run) => run.id === entityId) ?? null;
if (matchingRun) { setSelectedRunId(matchingRun.id); setSelectedTaskId(matchingRun.taskId); setConsoleOpen(true); }
}
}
else if (targetSection === "approvals") setSelectedApprovalId(entityId);
else if (targetSection === "goals") setSelectedGoalId(entityId);
else if (targetSection === "projects") setSelectedProjectId(entityId);
else if (targetSection === "communication") setSelectedCommunicationEntityId(entityId);
}
// eslint-disable-next-line react-hooks/exhaustive-deps -- Zustand setters are stable references
}, []);
const buildPaletteResults = useCallback((
navItemsList: NavItem[],
companyAgents: AgentRecord[],
@@ -198,7 +166,6 @@ export function useUIController() {
setSelectedPaletteIndex,
paletteQuery,
paletteTrapRef,
navigateTo,
buildPaletteResults,
buildPaletteActions,
};
+27 -13
View File
@@ -29,7 +29,7 @@ export const createNavigationSlice: StateCreator<
[["zustand/immer", never]],
[],
NavigationSlice
> = (set) => ({
> = (set, get) => ({
section: "overview",
commandPaletteOpen: false,
commandPaletteSearch: "",
@@ -93,19 +93,33 @@ export const createNavigationSlice: StateCreator<
navigateTo: (section, entityId) =>
set((state) => {
state.section = section;
if (entityId) {
if (section === "agents") state.selectedAgentId = entityId;
else if (section === "tasks") state.selectedTaskId = entityId;
else if (section === "approvals") state.selectedApprovalId = entityId;
else if (section === "runs") {
state.selectedRunId = entityId;
if (!entityId) return;
if (section === "agents") state.selectedAgentId = entityId;
else if (section === "approvals") state.selectedApprovalId = entityId;
else if (section === "runs") {
state.selectedRunId = entityId;
state.consoleOpen = true;
} else if (section === "goals") state.selectedGoalId = entityId;
else if (section === "projects") state.selectedProjectId = entityId;
else if (section === "connectors") state.selectedConnectorId = entityId;
else if (section === "communication")
state.selectedCommunicationEntityId = entityId;
else if (section === "skills") state.selectedSkillId = entityId;
else if (section === "tasks") {
const snapshot = get().snapshot;
const matchingTask = snapshot?.tasks.find((task) => task.id === entityId) ?? null;
if (matchingTask) {
state.selectedTaskId = matchingTask.id;
return;
}
const matchingRun = snapshot?.runs.find((run) => run.id === entityId) ?? null;
if (matchingRun) {
state.selectedRunId = matchingRun.id;
state.selectedTaskId = matchingRun.taskId;
state.consoleOpen = true;
} else if (section === "goals") state.selectedGoalId = entityId;
else if (section === "projects") state.selectedProjectId = entityId;
else if (section === "connectors") state.selectedConnectorId = entityId;
else if (section === "communication")
state.selectedCommunicationEntityId = entityId;
else if (section === "skills") state.selectedSkillId = entityId;
return;
}
state.selectedTaskId = entityId;
}
}),
});