* init refactor * changes context * wip * logs context * workspaces layout context breakdown * sidebar context * move diffs to workspace context * compress workspaces layout * refactors * types * always show archived
182 lines
5.5 KiB
TypeScript
182 lines
5.5 KiB
TypeScript
import { useMemo } from 'react';
|
|
import { useUiPreferencesStore } from '@/stores/useUiPreferencesStore';
|
|
import { useDiffViewStore, useDiffViewMode } from '@/stores/useDiffViewStore';
|
|
import { useWorkspaceContext } from '@/contexts/WorkspaceContext';
|
|
import { useUserSystem } from '@/components/ConfigProvider';
|
|
import { useDevServer } from '@/hooks/useDevServer';
|
|
import { useBranchStatus } from '@/hooks/useBranchStatus';
|
|
import { useExecutionProcessesContext } from '@/contexts/ExecutionProcessesContext';
|
|
import type { Workspace, Merge } from 'shared/types';
|
|
import type {
|
|
ActionVisibilityContext,
|
|
ActionDefinition,
|
|
ActionIcon,
|
|
DevServerState,
|
|
} from './index';
|
|
import { resolveLabel } from './index';
|
|
import type { CommandBarPage } from './pages';
|
|
|
|
/**
|
|
* Hook that builds the visibility context from stores/context.
|
|
* Used by both NavbarContainer and CommandBarDialog to evaluate
|
|
* action visibility and state conditions.
|
|
*/
|
|
export function useActionVisibilityContext(): ActionVisibilityContext {
|
|
const layout = useUiPreferencesStore();
|
|
const { workspace, workspaceId, isCreateMode, repos } = useWorkspaceContext();
|
|
const diffPaths = useDiffViewStore((s) => s.diffPaths);
|
|
const diffViewMode = useDiffViewMode();
|
|
const expanded = useUiPreferencesStore((s) => s.expanded);
|
|
const { config } = useUserSystem();
|
|
const { isStarting, isStopping, runningDevServers } =
|
|
useDevServer(workspaceId);
|
|
const { data: branchStatus } = useBranchStatus(workspaceId);
|
|
const { isAttemptRunningVisible } = useExecutionProcessesContext();
|
|
|
|
return useMemo(() => {
|
|
// Compute isAllDiffsExpanded
|
|
const diffKeys = diffPaths.map((p) => `diff:${p}`);
|
|
const isAllDiffsExpanded =
|
|
diffKeys.length > 0 && diffKeys.every((k) => expanded[k] !== false);
|
|
|
|
// Compute dev server state
|
|
const devServerState: DevServerState = isStarting
|
|
? 'starting'
|
|
: isStopping
|
|
? 'stopping'
|
|
: runningDevServers.length > 0
|
|
? 'running'
|
|
: 'stopped';
|
|
|
|
// Compute git state from branch status
|
|
const hasOpenPR =
|
|
branchStatus?.some((repo) =>
|
|
repo.merges?.some(
|
|
(m: Merge) => m.type === 'pr' && m.pr_info.status === 'open'
|
|
)
|
|
) ?? false;
|
|
|
|
const hasUnpushedCommits =
|
|
branchStatus?.some((repo) => (repo.remote_commits_ahead ?? 0) > 0) ??
|
|
false;
|
|
|
|
return {
|
|
rightMainPanelMode: layout.rightMainPanelMode,
|
|
isLeftSidebarVisible: layout.isLeftSidebarVisible,
|
|
isLeftMainPanelVisible: layout.isLeftMainPanelVisible,
|
|
isRightSidebarVisible: layout.isRightSidebarVisible,
|
|
isCreateMode,
|
|
hasWorkspace: !!workspace,
|
|
workspaceArchived: workspace?.archived ?? false,
|
|
hasDiffs: diffPaths.length > 0,
|
|
diffViewMode,
|
|
isAllDiffsExpanded,
|
|
editorType: config?.editor?.editor_type ?? null,
|
|
devServerState,
|
|
runningDevServers,
|
|
hasGitRepos: repos.length > 0,
|
|
hasMultipleRepos: repos.length > 1,
|
|
hasOpenPR,
|
|
hasUnpushedCommits,
|
|
isAttemptRunning: isAttemptRunningVisible,
|
|
};
|
|
}, [
|
|
layout.rightMainPanelMode,
|
|
layout.isLeftSidebarVisible,
|
|
layout.isLeftMainPanelVisible,
|
|
layout.isRightSidebarVisible,
|
|
isCreateMode,
|
|
workspace,
|
|
repos,
|
|
diffPaths,
|
|
diffViewMode,
|
|
expanded,
|
|
config?.editor?.editor_type,
|
|
isStarting,
|
|
isStopping,
|
|
runningDevServers,
|
|
branchStatus,
|
|
isAttemptRunningVisible,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Helper to check if an action is visible given the current context.
|
|
* If the action has no isVisible condition, it's always visible.
|
|
*/
|
|
export function isActionVisible(
|
|
action: ActionDefinition,
|
|
ctx: ActionVisibilityContext
|
|
): boolean {
|
|
return action.isVisible ? action.isVisible(ctx) : true;
|
|
}
|
|
|
|
/**
|
|
* Helper to check if a page is visible given the current context.
|
|
* If the page has no isVisible condition, it's always visible.
|
|
*/
|
|
export function isPageVisible(
|
|
page: CommandBarPage,
|
|
ctx: ActionVisibilityContext
|
|
): boolean {
|
|
return page.isVisible ? page.isVisible(ctx) : true;
|
|
}
|
|
|
|
/**
|
|
* Helper to check if an action is active given the current context.
|
|
* If the action has no isActive callback, returns false.
|
|
*/
|
|
export function isActionActive(
|
|
action: ActionDefinition,
|
|
ctx: ActionVisibilityContext
|
|
): boolean {
|
|
return action.isActive ? action.isActive(ctx) : false;
|
|
}
|
|
|
|
/**
|
|
* Helper to check if an action is enabled given the current context.
|
|
* If the action has no isEnabled callback, returns true (enabled by default).
|
|
*/
|
|
export function isActionEnabled(
|
|
action: ActionDefinition,
|
|
ctx: ActionVisibilityContext
|
|
): boolean {
|
|
return action.isEnabled ? action.isEnabled(ctx) : true;
|
|
}
|
|
|
|
/**
|
|
* Get the icon for an action, considering dynamic icon callbacks.
|
|
* Falls back to the static icon property.
|
|
*/
|
|
export function getActionIcon(
|
|
action: ActionDefinition,
|
|
ctx: ActionVisibilityContext
|
|
): ActionIcon {
|
|
return action.getIcon ? action.getIcon(ctx) : action.icon;
|
|
}
|
|
|
|
/**
|
|
* Get the tooltip for an action, considering dynamic tooltip callbacks.
|
|
* Falls back to the resolved label.
|
|
*/
|
|
export function getActionTooltip(
|
|
action: ActionDefinition,
|
|
ctx: ActionVisibilityContext
|
|
): string {
|
|
return action.getTooltip ? action.getTooltip(ctx) : resolveLabel(action);
|
|
}
|
|
|
|
/**
|
|
* Get the label for an action, considering dynamic label callbacks.
|
|
* Falls back to the resolved static label.
|
|
*/
|
|
export function getActionLabel(
|
|
action: ActionDefinition,
|
|
ctx: ActionVisibilityContext,
|
|
workspace?: Workspace
|
|
): string {
|
|
return action.getLabel
|
|
? action.getLabel(ctx)
|
|
: resolveLabel(action, workspace);
|
|
}
|