1+ import { getCommonBaseCommitId } from "#ui/domain/RefInfo.ts" ;
12import { type RefInfo , type WorktreeChanges } from "@gitbutler/but-sdk" ;
23import { Match } from "effect" ;
3- import { changesSummaryItem , normalizeItem , type Item } from "../workspace/-Item.ts" ;
4+ import { type Item } from "../workspace/-Item.ts" ;
45
56export type WorkspaceSelectionState = {
67 item : Item | null ;
8+ file : string | null ;
79 hunk : string | null ;
810} ;
911
1012export type WorkspaceSelectionAction =
1113 | { _tag : "SelectItem" ; item : Item | null }
14+ | { _tag : "SelectFile" ; file : string | null }
1215 | { _tag : "SelectHunk" ; hunk : string | null } ;
1316
1417export const initialWorkspaceSelectionState : WorkspaceSelectionState = {
1518 item : null ,
19+ file : null ,
1620 hunk : null ,
1721} ;
1822
@@ -24,6 +28,12 @@ export const workspaceSelectionReducer = (
2428 Match . tagsExhaustive ( {
2529 SelectItem : ( { item } ) : WorkspaceSelectionState => ( {
2630 item,
31+ file : null ,
32+ hunk : null ,
33+ } ) ,
34+ SelectFile : ( { file } ) : WorkspaceSelectionState => ( {
35+ ...state ,
36+ file,
2737 hunk : null ,
2838 } ) ,
2939 SelectHunk : ( { hunk } ) : WorkspaceSelectionState => ( {
@@ -33,15 +43,80 @@ export const workspaceSelectionReducer = (
3343 } ) ,
3444 ) ;
3545
46+ const normalizeSelectedItem = (
47+ item : Item ,
48+ headInfo : RefInfo ,
49+ worktreeChanges : WorktreeChanges ,
50+ ) : Item | null =>
51+ Match . value ( item ) . pipe (
52+ Match . tag ( "Changes" , ( item ) => item ) ,
53+ Match . tag ( "Change" , ( item ) => {
54+ if ( ! worktreeChanges . changes . find ( ( change ) => change . path === item . path ) ) return null ;
55+ if (
56+ ! worktreeChanges . assignments . find (
57+ ( assignment ) => assignment . stackId === item . stackId && assignment . path === item . path ,
58+ )
59+ )
60+ return null ;
61+ return item ;
62+ } ) ,
63+ Match . tag ( "Segment" , ( item ) => {
64+ const stack = headInfo . stacks . find ( ( stack ) => stack . id !== null && stack . id === item . stackId ) ;
65+ if ( ! stack ) return null ;
66+ const segment = stack . segments [ item . segmentIndex ] ;
67+ if ( ! segment ) return null ;
68+ const branchName = segment . refName ?. displayName ?? null ;
69+ if ( branchName !== item . branchName ) return null ;
70+ return item ;
71+ } ) ,
72+ Match . tag ( "Commit" , ( item ) => {
73+ const stack = headInfo . stacks . find ( ( stack ) => stack . id !== null && stack . id === item . stackId ) ;
74+ if ( ! stack ) return null ;
75+ const segment = stack . segments [ item . segmentIndex ] ;
76+ if ( ! segment ) return null ;
77+ if ( ! segment . commits . some ( ( commit ) => commit . id === item . commitId ) ) return null ;
78+ return item ;
79+ } ) ,
80+ Match . tag ( "BaseCommit" , ( item ) => {
81+ const commonBaseCommitId = getCommonBaseCommitId ( headInfo ) ;
82+ return commonBaseCommitId === item . commitId ? item : null ;
83+ } ) ,
84+ Match . exhaustive ,
85+ ) ;
86+
3687export const resolveSelectedWorkspaceItem = ( {
3788 workspaceSelection,
38- headInfo,
3989 worktreeChanges,
90+ headInfo,
91+ defaultItem,
4092} : {
4193 workspaceSelection : WorkspaceSelectionState ;
42- headInfo : RefInfo ;
4394 worktreeChanges : WorktreeChanges ;
95+ headInfo : RefInfo ;
96+ defaultItem : Item ;
4497} ) : Item =>
4598 ( workspaceSelection . item
46- ? normalizeItem ( workspaceSelection . item , headInfo , worktreeChanges )
47- : null ) ?? changesSummaryItem ( null ) ;
99+ ? normalizeSelectedItem ( workspaceSelection . item , headInfo , worktreeChanges )
100+ : null ) ?? defaultItem ;
101+
102+ export const normalizeSelectedFile = ( {
103+ paths,
104+ selectedFile,
105+ } : {
106+ paths : Array < string > ;
107+ selectedFile : string | null | undefined ;
108+ } ) : string | undefined => {
109+ if ( selectedFile != null && paths . includes ( selectedFile ) ) return selectedFile ;
110+ return paths [ 0 ] ;
111+ } ;
112+
113+ export const normalizeSelectedHunk = ( {
114+ hunkKeys,
115+ selectedHunk,
116+ } : {
117+ hunkKeys : Array < string > ;
118+ selectedHunk : string | null ;
119+ } ) : string | undefined => {
120+ if ( selectedHunk !== null && hunkKeys . includes ( selectedHunk ) ) return selectedHunk ;
121+ return hunkKeys [ 0 ] ;
122+ } ;
0 commit comments