import type { AppMode, SortField, SortDirection, Project, ViewMode, GitHubRepoInfo, UnifiedRepo, QuickFilter, AddDirectoryDialogState, RemoteStatus, OpenModalState, ModalUpdate } from "../types/index.ts"; /** * Action creators for app state * Each returns a specific action type for better type inference in tests */ export const setProjects = (projects: Project[]) => ({ type: "SET_PROJECTS" as const, payload: projects, }); export const setLoading = (loading: boolean) => ({ type: "SET_LOADING" as const, payload: loading, }); export const setError = (error: string | null) => ({ type: "SET_ERROR" as const, payload: error, }); export const setMessage = (message: string | null) => ({ type: "SET_MESSAGE" as const, payload: message, }); export const moveCursor = (index: number, maxIndex: number) => ({ type: "MOVE_CURSOR" as const, payload: { index, maxIndex }, }); export const toggleSelection = (index: number) => ({ type: "TOGGLE_SELECTION" as const, payload: index, }); export const selectAll = (count: number) => ({ type: "SELECT_ALL" as const, payload: { count }, }); export const deselectAll = () => ({ type: "DESELECT_ALL" as const, }); export const setFilter = (text: string) => ({ type: "SET_FILTER" as const, payload: text, }); export const setSort = (by: SortField, direction: SortDirection) => ({ type: "SET_SORT" as const, payload: { by, direction }, }); export const cycleSort = () => ({ type: "CYCLE_SORT" as const, }); export const setMode = (mode: AppMode) => ({ type: "SET_MODE" as const, payload: mode, }); export const startAction = (action: string) => ({ type: "START_ACTION" as const, payload: action, }); export const endAction = () => ({ type: "END_ACTION" as const, }); export const updateProgress = (current: number, total: number) => ({ type: "UPDATE_PROGRESS" as const, payload: { current, total }, }); export const setScrollOffset = (offset: number) => ({ type: "SET_SCROLL_OFFSET" as const, payload: offset, }); export const updateProject = (id: string, updates: Partial) => ({ type: "UPDATE_PROJECT" as const, payload: { id, updates }, }); export const updateProjectRemoteStatus = (path: string, remote: RemoteStatus | null) => ({ type: "UPDATE_PROJECT_REMOTE_STATUS" as const, payload: { path, remote }, }); // Unified view action creators export const setViewMode = (mode: ViewMode) => ({ type: "SET_VIEW_MODE" as const, payload: mode, }); export const setGitHubRepos = (repos: GitHubRepoInfo[]) => ({ type: "SET_GITHUB_REPOS" as const, payload: repos, }); export const setUnifiedRepos = (repos: UnifiedRepo[]) => ({ type: "SET_UNIFIED_REPOS" as const, payload: repos, }); export const setGitHubLoading = (loading: boolean) => ({ type: "SET_GITHUB_LOADING" as const, payload: loading, }); export const setGitHubError = (error: string | null) => ({ type: "SET_GITHUB_ERROR" as const, payload: error, }); export const cloneRepoStart = (repoId: string) => ({ type: "CLONE_REPO_START" as const, payload: repoId, }); export const cloneRepoComplete = (id: string, localPath: string) => ({ type: "CLONE_REPO_COMPLETE" as const, payload: { id, localPath }, }); export const cloneRepoFailed = (id: string, error: string) => ({ type: "CLONE_REPO_FAILED" as const, payload: { id, error }, }); // Quick filter actions export const setQuickFilter = (filter: QuickFilter) => ({ type: "SET_QUICK_FILTER" as const, payload: filter, }); // Refreshing state actions export const setRefreshing = (refreshing: boolean) => ({ type: "SET_REFRESHING" as const, payload: refreshing, }); // Language filter action export const setLanguageFilter = (language: string | null) => ({ type: "SET_LANGUAGE_FILTER" as const, payload: language, }); // Modal actions (ADR-0012). OPEN_MODAL replaces SHOW_*_DIALOG; // CLOSE_MODAL replaces HIDE_*_DIALOG; UPDATE_MODAL replaces UPDATE_*_DIALOG. export const openModal = (modal: OpenModalState) => ({ type: "OPEN_MODAL" as const, payload: modal, }); export const closeModal = () => ({ type: "CLOSE_MODAL" as const, }); export const updateModal = (update: ModalUpdate) => ({ type: "UPDATE_MODAL" as const, payload: update, }); /** * Convenience: open the add-directory dialog. The dialog's step-machine * state lives in the useAddDirectoryFlow hook; this payload carries only * the optional initialPath seed. */ export const showAddDirectoryDialog = (initialPath?: string) => ({ type: "OPEN_MODAL" as const, payload: { kind: "add-directory" as const, data: { initialPath } satisfies AddDirectoryDialogState, }, });