@@ -44,6 +44,7 @@ export interface BodyWidgetProps {
4444 runXircuitSignal : Signal < XircuitsPanel , any > ;
4545 runTypeXircuitSignal : Signal < XircuitsPanel , any > ;
4646 lockNodeSignal : Signal < XircuitsPanel , any > ;
47+ triggerLoadingAnimationSignal : Signal < XircuitsPanel , any > ;
4748 reloadAllNodesSignal : Signal < XircuitsPanel , any > ;
4849 toggleAllLinkAnimationSignal : Signal < XircuitsPanel , any > ;
4950}
@@ -82,6 +83,7 @@ export const commandIDs = {
8283 cutNode : 'Xircuit-editor:cut-node' ,
8384 copyNode : 'Xircuit-editor:copy-node' ,
8485 pasteNode : 'Xircuit-editor:paste-node' ,
86+ triggerLoadingAnimation : 'Xircuit-editor:trigger-loading-animation' ,
8587 reloadNode : 'Xircuit-editor:reload-node' ,
8688 reloadAllNodes : 'Xircuit-editor:reload-all-nodes' ,
8789 toggleAllLinkAnimation : 'Xircuit-editor:toggle-all-link-animation' ,
@@ -111,6 +113,7 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
111113 runXircuitSignal,
112114 runTypeXircuitSignal,
113115 lockNodeSignal,
116+ triggerLoadingAnimationSignal,
114117 reloadAllNodesSignal,
115118 toggleAllLinkAnimationSignal,
116119} ) => {
@@ -126,6 +129,8 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
126129 const [ floatNodes , setFloatNodes ] = useState < string [ ] > ( [ ] ) ;
127130 const [ boolNodes , setBoolNodes ] = useState < string [ ] > ( [ ] ) ;
128131 const [ componentList , setComponentList ] = useState ( [ ] ) ;
132+ const [ isLoading , setIsLoading ] = useState ( false ) ;
133+ const [ loadingMessage , setLoadingMessage ] = useState ( 'Xircuits loading...' ) ;
129134 const [ inDebugMode , setInDebugMode ] = useState < boolean > ( false ) ;
130135 const [ currentIndex , setCurrentIndex ] = useState < number > ( - 1 ) ;
131136 const [ runType , setRunType ] = useState < string > ( "run" ) ;
@@ -506,6 +511,42 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
506511 return true ;
507512 }
508513
514+ const triggerLoadingAnimation = async (
515+ operationPromise ,
516+ { loadingMessage = 'Xircuits loading...' ,
517+ loadingDisplayDuration = 1000 ,
518+ showLoadingAfter = 100 } = { }
519+ ) => {
520+ if ( shell . currentWidget ?. id !== widgetId ) {
521+ return ;
522+ }
523+
524+ let shouldSetLoading = false ;
525+
526+ setLoadingMessage ( loadingMessage ) ;
527+
528+ // Start a timer that will check if the operation exceeds showLoadingAfter
529+ const startTimer = setTimeout ( ( ) => {
530+ shouldSetLoading = true ;
531+ setIsLoading ( true ) ;
532+ } , showLoadingAfter ) ;
533+
534+ await operationPromise ;
535+
536+ // Clear the start timer as the operation has completed
537+ clearTimeout ( startTimer ) ;
538+
539+ if ( shouldSetLoading ) {
540+ // If loading was started, ensure it stays for the minimum loading time
541+ const minTimer = setTimeout ( ( ) => setIsLoading ( false ) , loadingDisplayDuration ) ;
542+ // Clear the minimum timer to prevent memory leaks in case the component unmounts
543+ return ( ) => clearTimeout ( minTimer ) ;
544+ } else {
545+ // If loading was not started, just ensure loading state is set to false
546+ setIsLoading ( false ) ;
547+ }
548+ } ;
549+
509550 const handleSaveClick = async ( ) => {
510551 // Only save xircuit if it is currently in focus
511552 // This must be first to avoid unnecessary complication
@@ -636,17 +677,18 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
636677 } ) ;
637678 }
638679
639- const handleReloadAll = ( ) => {
640- // This must be first to avoid unnecessary complication
680+ const handleReloadAll = async ( ) => {
641681 if ( shell . currentWidget ?. id !== widgetId ) {
642- return ;
682+ return ;
643683 }
644-
645- let allNodes = xircuitsApp . getDiagramEngine ( ) . getModel ( ) . getNodes ( )
646- allNodes . forEach ( node => node . setSelected ( true ) ) ;
647- app . commands . execute ( commandIDs . reloadNode ) ;
648-
649- }
684+
685+ const reloadPromise = app . commands . execute ( commandIDs . reloadNode ) ;
686+
687+ // Trigger loading animation
688+ await triggerLoadingAnimation ( reloadPromise , { loadingMessage : 'Reloading all nodes...' } ) ;
689+
690+ console . log ( "Reload all complete." ) ;
691+ } ;
650692
651693 const handleToggleAllLinkAnimation = ( ) => {
652694 // This must be first to avoid unnecessary complication
@@ -801,6 +843,7 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
801843 [ compileXircuitSignal , handleCompileClick ] ,
802844 [ runXircuitSignal , handleRunClick ] ,
803845 [ lockNodeSignal , handleLockClick ] ,
846+ [ triggerLoadingAnimationSignal , triggerLoadingAnimation ] ,
804847 [ reloadAllNodesSignal , handleReloadAll ] ,
805848 [ toggleAllLinkAnimationSignal , handleToggleAllLinkAnimation ]
806849 ] ;
@@ -1053,6 +1096,12 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
10531096 return (
10541097 < Body >
10551098 < Content >
1099+ { isLoading && (
1100+ < div className = "loading-indicator" >
1101+ < div className = "loading-gif-wrapper" > </ div >
1102+ < div className = "loading-text" > { loadingMessage } </ div >
1103+ </ div >
1104+ ) }
10561105 < Layer
10571106 onDrop = { handleDropEvent }
10581107 onDragOver = { preventDefault }
@@ -1063,15 +1112,15 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
10631112 onClick = { handleClick } >
10641113 < XircuitsCanvasWidget >
10651114 < CanvasWidget engine = { xircuitsApp . getDiagramEngine ( ) } />
1066- { /** Add Component Panel(ctrl + left-click, dropped link)*/ }
1115+ { /* Add Component Panel(ctrl + left-click, dropped link) */ }
10671116 { isComponentPanelShown && (
10681117 < div
10691118 onMouseEnter = { ( ) => setDontHidePanel ( true ) }
10701119 onMouseLeave = { ( ) => setDontHidePanel ( false ) }
10711120 id = 'component-panel'
10721121 style = { {
10731122 top : componentPanelPosition . y ,
1074- left :componentPanelPosition . x
1123+ left : componentPanelPosition . x
10751124 } }
10761125 className = "add-component-panel" >
10771126 < ComponentsPanel
@@ -1081,10 +1130,10 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
10811130 linkData = { looseLinkData }
10821131 isParameter = { isParameterLink }
10831132 key = "component-panel"
1084- > </ ComponentsPanel >
1133+ / >
10851134 </ div >
10861135 ) }
1087- { /** Node Action Panel(left-click)*/ }
1136+ { /* Node Action Panel(left-click) */ }
10881137 { contextMenuShown && (
10891138 < div
10901139 id = 'context-menu'
@@ -1097,12 +1146,12 @@ export const BodyWidget: FC<BodyWidgetProps> = ({
10971146 app = { app }
10981147 engine = { xircuitsApp . getDiagramEngine ( ) }
10991148 nodePosition = { nodePosition }
1100- > </ CanvasContextMenu >
1149+ / >
11011150 </ div >
11021151 ) }
11031152 </ XircuitsCanvasWidget >
11041153 </ Layer >
11051154 </ Content >
11061155 </ Body >
11071156 ) ;
1108- }
1157+ }
0 commit comments