Files
tolaria/src/hooks/useDiffMode.ts

216 lines
6.5 KiB
TypeScript
Raw Normal View History

import {
useState,
useEffect,
useCallback,
type Dispatch,
type SetStateAction,
} from 'react'
export interface CommitDiffRequest {
requestId: number
path: string
commitHash?: string | null
}
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
interface UseDiffModeParams {
activeTabPath: string | null
onLoadDiff?: (path: string) => Promise<string>
onLoadDiffAtCommit?: (path: string, commitHash: string) => Promise<string>
pendingCommitDiffRequest?: CommitDiffRequest | null
onPendingCommitDiffHandled?: (requestId: number) => void
}
interface DiffStateSetters {
setDiffMode: Dispatch<SetStateAction<boolean>>
setDiffContent: Dispatch<SetStateAction<string | null>>
setDiffLoading: Dispatch<SetStateAction<boolean>>
setDiffPath: Dispatch<SetStateAction<string | null>>
}
async function loadDiffForPath(
path: string,
onLoadDiff: ((path: string) => Promise<string>) | undefined,
{ setDiffMode, setDiffContent, setDiffLoading, setDiffPath }: DiffStateSetters,
) {
if (!onLoadDiff) return
setDiffLoading(true)
try {
const diff = await onLoadDiff(path)
setDiffContent(diff)
setDiffPath(path)
setDiffMode(true)
} catch (err) {
console.warn('Failed to load diff:', err)
} finally {
setDiffLoading(false)
}
}
async function loadCommitDiffForPath(
path: string,
commitHash: string,
onLoadDiffAtCommit: ((path: string, commitHash: string) => Promise<string>) | undefined,
{ setDiffMode, setDiffContent, setDiffLoading, setDiffPath }: DiffStateSetters,
) {
if (!onLoadDiffAtCommit) return
setDiffLoading(true)
try {
const diff = await onLoadDiffAtCommit(path, commitHash)
setDiffContent(diff)
setDiffPath(path)
setDiffMode(true)
} catch (err) {
console.warn('Failed to load commit diff:', err)
} finally {
setDiffLoading(false)
}
}
function shouldHandlePendingCommitDiffRequest(
activeTabPath: string | null,
pendingCommitDiffRequest: CommitDiffRequest | null | undefined,
): pendingCommitDiffRequest is CommitDiffRequest {
return !!pendingCommitDiffRequest && pendingCommitDiffRequest.path === activeTabPath
}
function hasCommitHash(pendingCommitDiffRequest: CommitDiffRequest): pendingCommitDiffRequest is CommitDiffRequest & { commitHash: string } {
return typeof pendingCommitDiffRequest.commitHash === 'string' && pendingCommitDiffRequest.commitHash.length > 0
}
function buildGuardedDiffStateSetters(
cancelledRef: { current: boolean },
{ setDiffMode, setDiffContent, setDiffLoading, setDiffPath }: DiffStateSetters,
): DiffStateSetters {
return {
setDiffMode: (value) => { if (!cancelledRef.current) setDiffMode(value) },
setDiffContent: (value) => { if (!cancelledRef.current) setDiffContent(value) },
setDiffLoading: (value) => { if (!cancelledRef.current) setDiffLoading(value) },
setDiffPath: (value) => { if (!cancelledRef.current) setDiffPath(value) },
}
}
function runPendingCommitDiffRequest(
pendingCommitDiffRequest: CommitDiffRequest,
onLoadDiff: ((path: string) => Promise<string>) | undefined,
onLoadDiffAtCommit: (path: string, commitHash: string) => Promise<string>,
onPendingCommitDiffHandled: ((requestId: number) => void) | undefined,
diffState: DiffStateSetters,
) {
const cancelledRef = { current: false }
const loadDiffPromise = hasCommitHash(pendingCommitDiffRequest)
? loadCommitDiffForPath(
pendingCommitDiffRequest.path,
pendingCommitDiffRequest.commitHash,
onLoadDiffAtCommit,
buildGuardedDiffStateSetters(cancelledRef, diffState),
)
: loadDiffForPath(
pendingCommitDiffRequest.path,
onLoadDiff,
buildGuardedDiffStateSetters(cancelledRef, diffState),
)
void loadDiffPromise.finally(() => {
if (cancelledRef.current) return
onPendingCommitDiffHandled?.(pendingCommitDiffRequest.requestId)
})
return () => {
cancelledRef.current = true
}
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
}
function usePendingCommitDiffRequest({
activeTabPath,
onLoadDiff,
onLoadDiffAtCommit,
pendingCommitDiffRequest,
onPendingCommitDiffHandled,
setDiffMode,
setDiffContent,
setDiffLoading,
setDiffPath,
}: UseDiffModeParams & DiffStateSetters) {
useEffect(() => {
if (!shouldHandlePendingCommitDiffRequest(activeTabPath, pendingCommitDiffRequest)) return
if (hasCommitHash(pendingCommitDiffRequest) && !onLoadDiffAtCommit) {
onPendingCommitDiffHandled?.(pendingCommitDiffRequest.requestId)
return
}
if (!hasCommitHash(pendingCommitDiffRequest) && !onLoadDiff) {
onPendingCommitDiffHandled?.(pendingCommitDiffRequest.requestId)
return
}
return runPendingCommitDiffRequest(
pendingCommitDiffRequest,
onLoadDiff,
onLoadDiffAtCommit,
onPendingCommitDiffHandled,
{ setDiffMode, setDiffContent, setDiffLoading, setDiffPath },
)
}, [activeTabPath, onLoadDiff, onLoadDiffAtCommit, onPendingCommitDiffHandled, pendingCommitDiffRequest, setDiffContent, setDiffLoading, setDiffMode, setDiffPath])
}
export function useDiffMode({
activeTabPath,
onLoadDiff,
onLoadDiffAtCommit,
pendingCommitDiffRequest,
onPendingCommitDiffHandled,
}: UseDiffModeParams) {
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
const [diffMode, setDiffMode] = useState(false)
const [diffContent, setDiffContent] = useState<string | null>(null)
const [diffLoading, setDiffLoading] = useState(false)
const [diffPath, setDiffPath] = useState<string | null>(activeTabPath)
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
usePendingCommitDiffRequest({
activeTabPath,
onLoadDiff,
onLoadDiffAtCommit,
pendingCommitDiffRequest,
onPendingCommitDiffHandled,
setDiffMode,
setDiffContent,
setDiffLoading,
setDiffPath,
})
const isDiffVisible = diffMode && diffPath === activeTabPath
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
const handleToggleDiff = useCallback(async () => {
if (isDiffVisible) {
setDiffPath(activeTabPath)
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
setDiffMode(false)
setDiffContent(null)
return
}
if (!activeTabPath || !onLoadDiff) return
await loadDiffForPath(activeTabPath, onLoadDiff, {
setDiffMode,
setDiffContent,
setDiffLoading,
setDiffPath,
})
}, [activeTabPath, isDiffVisible, onLoadDiff, setDiffContent, setDiffLoading, setDiffMode, setDiffPath])
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
const handleViewCommitDiff = useCallback(async (commitHash: string) => {
if (!activeTabPath) return
await loadCommitDiffForPath(activeTabPath, commitHash, onLoadDiffAtCommit, {
setDiffMode,
setDiffContent,
setDiffLoading,
setDiffPath,
})
}, [activeTabPath, onLoadDiffAtCommit, setDiffContent, setDiffLoading, setDiffMode, setDiffPath])
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
return {
diffMode: isDiffVisible,
diffContent: isDiffVisible ? diffContent : null,
diffLoading,
handleToggleDiff,
handleViewCommitDiff,
}
refactor: decompose Editor.tsx, NoteList.tsx, Sidebar.tsx — CodeScene hotspots (#126) * refactor: decompose Editor.tsx into focused subcomponents and hooks Extract from the monolithic Editor component (cc=35, 213 LoC, score 7.82): - useDiffMode hook: diff state + toggle/commit-diff handlers - useEditorFocus hook: new-note focus event listener - editorSchema: WikiLink spec + BlockNote schema (module-level) - SingleEditorView: BlockNote editor + suggestion menus - EditorContent: breadcrumb bar + diff/editor/loading views - EditorRightPanel: AI chat / Inspector panel switching - suggestionEnrichment util: shared enrichment logic (eliminates duplication) Editor.tsx is now 10.0 code health (was 7.82). All 25 existing tests pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor: extract standalone functions from NoteList and Sidebar to reduce cc NoteList: extract createNoteStatusResolver and toggleSetMember from NoteListInner (cc 13→8, score 9.04→9.38). Sidebar: extract applyCustomization from Sidebar (cc 10→7, score 9.09→10.0). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add tests for useDiffMode, useEditorFocus, and suggestionEnrichment Cover extracted hook/utility logic: diff toggle/reset, editor focus event listener with adaptive timing, and suggestion item enrichment pipeline. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: update architecture for editor decomposition and write .claude-done Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-27 15:27:25 +01:00
}