@@ -21,6 +21,7 @@ import { useThemeMode } from '../../context/theme-provider';
2121import { useTranslation } from 'react-i18next' ;
2222import { useBrowserSteps } from '../../context/browserSteps' ;
2323import { useActionContext } from '../../context/browserActions' ;
24+ import { useSocketStore } from '../../context/socket' ;
2425
2526interface InterpretationLogProps {
2627 isOpen : boolean ;
@@ -57,8 +58,9 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
5758 const previousGetText = useRef < boolean > ( false ) ;
5859 const autoFocusedScreenshotIndices = useRef < Set < number > > ( new Set ( ) ) ;
5960
60- const { browserSteps, updateListTextFieldLabel, removeListTextField, updateListStepName, updateScreenshotStepName, updateBrowserTextStepLabel, deleteBrowserStep, emitForStepId } = useBrowserSteps ( ) ;
61+ const { browserSteps, updateListTextFieldLabel, removeListTextField, updateListStepName, updateScreenshotStepName, updateBrowserTextStepLabel, deleteBrowserStep, deleteStepsByActionId , emitForStepId } = useBrowserSteps ( ) ;
6162 const { captureStage, getText } = useActionContext ( ) ;
63+ const { socket } = useSocketStore ( ) ;
6264
6365 const { browserWidth, outputPreviewHeight, outputPreviewWidth } = useBrowserDimensionsStore ( ) ;
6466 const { currentWorkflowActionsState, shouldResetInterpretationLog, currentTextGroupName, setCurrentTextGroupName, notify } = useGlobalInfoStore ( ) ;
@@ -154,6 +156,76 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
154156 }
155157 } ;
156158
159+ const handleRemoveListAction = ( listId : number , actionId : string | undefined ) => {
160+ if ( ! actionId ) return ;
161+
162+ const listIndex = captureListData . findIndex ( list => list . id === listId ) ;
163+ const listItem = captureListData [ listIndex ] ;
164+ const listName = listItem ?. name || `List Data ${ listIndex + 1 } ` ;
165+ const isActiveList = listIndex === activeListTab ;
166+
167+ deleteStepsByActionId ( actionId ) ;
168+
169+ if ( socket ) {
170+ socket . emit ( 'removeAction' , { actionId } ) ;
171+ }
172+
173+ if ( isActiveList && captureListData . length > 1 ) {
174+ if ( listIndex === captureListData . length - 1 ) {
175+ setActiveListTab ( listIndex - 1 ) ;
176+ }
177+ } else if ( listIndex < activeListTab ) {
178+ setActiveListTab ( activeListTab - 1 ) ;
179+ }
180+
181+ notify ( 'error' , `List "${ listName } " discarded` ) ;
182+ } ;
183+
184+ const handleRemoveScreenshotAction = ( screenshotId : number , actionId : string | undefined ) => {
185+ if ( ! actionId ) return ;
186+
187+ const screenshotSteps = browserSteps . filter ( step => step . type === 'screenshot' && step . screenshotData ) ;
188+ const screenshotIndex = screenshotSteps . findIndex ( step => step . id === screenshotId ) ;
189+ const screenshotStep = screenshotSteps [ screenshotIndex ] ;
190+ const screenshotName = screenshotStep ?. name || `Screenshot ${ screenshotIndex + 1 } ` ;
191+ const isActiveScreenshot = screenshotIndex === activeScreenshotTab ;
192+
193+ deleteStepsByActionId ( actionId ) ;
194+
195+ if ( socket ) {
196+ socket . emit ( 'removeAction' , { actionId } ) ;
197+ }
198+
199+ if ( isActiveScreenshot && screenshotData . length > 1 ) {
200+ if ( screenshotIndex === screenshotData . length - 1 ) {
201+ setActiveScreenshotTab ( screenshotIndex - 1 ) ;
202+ }
203+ } else if ( screenshotIndex < activeScreenshotTab ) {
204+ setActiveScreenshotTab ( activeScreenshotTab - 1 ) ;
205+ }
206+
207+ notify ( 'error' , `Screenshot "${ screenshotName } " discarded` ) ;
208+ } ;
209+
210+ const handleRemoveAllTextActions = ( ) => {
211+ const uniqueActionIds = new Set < string > ( ) ;
212+ captureTextData . forEach ( textStep => {
213+ if ( textStep . actionId ) {
214+ uniqueActionIds . add ( textStep . actionId ) ;
215+ }
216+ } ) ;
217+
218+ uniqueActionIds . forEach ( actionId => {
219+ deleteStepsByActionId ( actionId ) ;
220+
221+ if ( socket ) {
222+ socket . emit ( 'removeAction' , { actionId } ) ;
223+ }
224+ } ) ;
225+
226+ notify ( 'error' , `Text data "${ currentTextGroupName } " discarded` ) ;
227+ } ;
228+
157229 const checkForDuplicateName = ( stepId : number , type : 'list' | 'text' | 'screenshot' , newName : string ) : boolean => {
158230 const trimmedName = newName . trim ( ) ;
159231
@@ -174,7 +246,7 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
174246 }
175247
176248 return false ;
177- } ;
249+ }
178250
179251 const startEdit = ( stepId : number , type : 'list' | 'text' | 'screenshot' , currentValue : string ) => {
180252 setEditing ( { stepId, type, value : currentValue } ) ;
@@ -609,13 +681,17 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
609681 : '2px solid #ffffff'
610682 : '2px solid transparent' ,
611683 transition : 'all 0.2s ease' ,
684+ position : 'relative' ,
612685 '&:hover' : {
613686 backgroundColor : isActive
614687 ? undefined
615688 : darkMode
616689 ? '#161616'
617690 : '#e9ecef' ,
618691 } ,
692+ '&:hover .delete-icon' : {
693+ opacity : 1
694+ } ,
619695 } }
620696 >
621697 { isEditing ? (
@@ -644,7 +720,33 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
644720 } }
645721 />
646722 ) : (
647- listItem . name || `List Data ${ index + 1 } `
723+ < >
724+ { listItem . name || `List Data ${ index + 1 } ` }
725+ < IconButton
726+ className = "delete-icon"
727+ size = "small"
728+ onClick = { ( e ) => {
729+ e . stopPropagation ( ) ;
730+ handleRemoveListAction ( listItem . id , listItem . actionId ) ;
731+ } }
732+ sx = { {
733+ position : 'absolute' ,
734+ right : 4 ,
735+ top : '50%' ,
736+ transform : 'translateY(-50%)' ,
737+ opacity : 0 ,
738+ transition : 'opacity 0.2s' ,
739+ color : darkMode ? '#999' : '#666' ,
740+ padding : '2px' ,
741+ '&:hover' : {
742+ color : '#f44336' ,
743+ backgroundColor : darkMode ? 'rgba(244, 67, 54, 0.1)' : 'rgba(244, 67, 54, 0.05)'
744+ }
745+ } }
746+ >
747+ < CloseIcon sx = { { fontSize : '14px' } } />
748+ </ IconButton >
749+ </ >
648750 ) }
649751 </ Box >
650752 </ Tooltip >
@@ -815,7 +917,7 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
815917 } }
816918 >
817919 { ( ( ) => {
818- const screenshotSteps = browserSteps . filter ( step => step . type === 'screenshot' && step . screenshotData ) as Array < { id : number ; name ?: string ; type : 'screenshot' ; screenshotData ?: string } > ;
920+ const screenshotSteps = browserSteps . filter ( step => step . type === 'screenshot' && step . screenshotData ) as Array < { id : number ; name ?: string ; type : 'screenshot' ; fullPage : boolean ; actionId ?: string ; screenshotData ?: string } > ;
819921 return screenshotData . map ( ( screenshot , index ) => {
820922 const screenshotStep = screenshotSteps [ index ] ;
821923 if ( ! screenshotStep ) return null ;
@@ -861,13 +963,17 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
861963 : '2px solid #ffffff'
862964 : '2px solid transparent' ,
863965 transition : 'all 0.2s ease' ,
966+ position : 'relative' ,
864967 '&:hover' : {
865968 backgroundColor : isActive
866969 ? undefined
867970 : darkMode
868971 ? '#161616'
869972 : '#e9ecef' ,
870973 } ,
974+ '&:hover .delete-icon' : {
975+ opacity : 1
976+ } ,
871977 } }
872978 >
873979 { isEditing ? (
@@ -896,7 +1002,33 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
8961002 } }
8971003 />
8981004 ) : (
899- screenshotName
1005+ < >
1006+ { screenshotName }
1007+ < IconButton
1008+ className = "delete-icon"
1009+ size = "small"
1010+ onClick = { ( e ) => {
1011+ e . stopPropagation ( ) ;
1012+ handleRemoveScreenshotAction ( screenshotStep . id , screenshotStep . actionId ) ;
1013+ } }
1014+ sx = { {
1015+ position : 'absolute' ,
1016+ right : 4 ,
1017+ top : '50%' ,
1018+ transform : 'translateY(-50%)' ,
1019+ opacity : 0 ,
1020+ transition : 'opacity 0.2s' ,
1021+ color : darkMode ? '#999' : '#666' ,
1022+ padding : '2px' ,
1023+ '&:hover' : {
1024+ color : '#f44336' ,
1025+ backgroundColor : darkMode ? 'rgba(244, 67, 54, 0.1)' : 'rgba(244, 67, 54, 0.05)'
1026+ }
1027+ } }
1028+ >
1029+ < CloseIcon sx = { { fontSize : '14px' } } />
1030+ </ IconButton >
1031+ </ >
9001032 ) }
9011033 </ Box >
9021034 </ Tooltip >
@@ -953,6 +1085,10 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
9531085 borderColor : darkMode ? '#2a2a2a' : '#d0d0d0' ,
9541086 borderBottom : darkMode ? '2px solid #1c1c1c' : '2px solid #ffffff' ,
9551087 transition : 'all 0.2s ease' ,
1088+ position : 'relative' ,
1089+ '&:hover .delete-icon' : {
1090+ opacity : 1
1091+ } ,
9561092 } }
9571093 >
9581094 { editingTextGroupName ? (
@@ -984,7 +1120,33 @@ export const InterpretationLog: React.FC<InterpretationLogProps> = ({ isOpen, se
9841120 } }
9851121 />
9861122 ) : (
987- currentTextGroupName
1123+ < >
1124+ { currentTextGroupName }
1125+ < IconButton
1126+ className = "delete-icon"
1127+ size = "small"
1128+ onClick = { ( e ) => {
1129+ e . stopPropagation ( ) ;
1130+ handleRemoveAllTextActions ( ) ;
1131+ } }
1132+ sx = { {
1133+ position : 'absolute' ,
1134+ right : 4 ,
1135+ top : '50%' ,
1136+ transform : 'translateY(-50%)' ,
1137+ opacity : 0 ,
1138+ transition : 'opacity 0.2s' ,
1139+ color : darkMode ? '#999' : '#666' ,
1140+ padding : '2px' ,
1141+ '&:hover' : {
1142+ color : '#f44336' ,
1143+ backgroundColor : darkMode ? 'rgba(244, 67, 54, 0.1)' : 'rgba(244, 67, 54, 0.05)'
1144+ }
1145+ } }
1146+ >
1147+ < CloseIcon sx = { { fontSize : '14px' } } />
1148+ </ IconButton >
1149+ </ >
9881150 ) }
9891151 </ Box >
9901152 </ Tooltip >
0 commit comments