@@ -4,9 +4,9 @@ import { useAppSelector } from 'app/store/storeHooks';
44import { selectAutoSwitch } from 'features/gallery/store/gallerySelectors' ;
55import type { ProgressImage as ProgressImageType } from 'features/nodes/types/common' ;
66import { LRUCache } from 'lru-cache' ;
7- import { type Atom , atom , computed } from 'nanostores' ;
7+ import { type Atom , atom , computed , type WritableAtom } from 'nanostores' ;
88import type { PropsWithChildren } from 'react' ;
9- import { createContext , memo , useCallback , useContext , useEffect , useMemo , useState } from 'react' ;
9+ import { createContext , memo , useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react' ;
1010import type { S } from 'services/api/types' ;
1111import { $socket } from 'services/events/stores' ;
1212import { assert } from 'tsafe' ;
@@ -16,6 +16,8 @@ type ImageViewerContextValue = {
1616 $progressEvent : Atom < S [ 'InvocationProgressEvent' ] | null > ;
1717 $progressImage : Atom < ProgressImageType | null > ;
1818 $hasProgressImage : Atom < boolean > ;
19+ $isProgressImageResolving : Atom < boolean > ;
20+ $isTemporarilyShowingSelectedImage : WritableAtom < boolean > ;
1921 onLoadImage : ( ) => void ;
2022} ;
2123
@@ -29,6 +31,9 @@ export const ImageViewerContextProvider = memo((props: PropsWithChildren) => {
2931 const $progressEvent = useState ( ( ) => atom < S [ 'InvocationProgressEvent' ] | null > ( null ) ) [ 0 ] ;
3032 const $progressImage = useState ( ( ) => atom < ProgressImageType | null > ( null ) ) [ 0 ] ;
3133 const $hasProgressImage = useState ( ( ) => computed ( $progressImage , ( progressImage ) => progressImage !== null ) ) [ 0 ] ;
34+ const $isProgressImageResolving = useState ( ( ) => atom ( false ) ) [ 0 ] ;
35+ const $isTemporarilyShowingSelectedImage = useState ( ( ) => atom ( false ) ) [ 0 ] ;
36+ const shouldClearProgressImageOnLoadRef = useRef ( false ) ;
3237 // We can have race conditions where we receive a progress event for a queue item that has already finished. Easiest
3338 // way to handle this is to keep track of finished queue items in a cache and ignore progress events for those.
3439 const [ finishedQueueItemIds ] = useState ( ( ) => new LRUCache < number , boolean > ( { max : 200 } ) ) ;
@@ -46,6 +51,8 @@ export const ImageViewerContextProvider = memo((props: PropsWithChildren) => {
4651 ) ;
4752 return ;
4853 }
54+ shouldClearProgressImageOnLoadRef . current = false ;
55+ $isProgressImageResolving . set ( false ) ;
4956 $progressEvent . set ( data ) ;
5057 if ( data . image ) {
5158 $progressImage . set ( data . image ) ;
@@ -57,7 +64,7 @@ export const ImageViewerContextProvider = memo((props: PropsWithChildren) => {
5764 return ( ) => {
5865 socket . off ( 'invocation_progress' , onInvocationProgress ) ;
5966 } ;
60- } , [ $progressEvent , $progressImage , finishedQueueItemIds , socket ] ) ;
67+ } , [ $isProgressImageResolving , $ progressEvent, $progressImage , finishedQueueItemIds , socket ] ) ;
6168
6269 useEffect ( ( ) => {
6370 if ( ! socket ) {
@@ -92,8 +99,13 @@ export const ImageViewerContextProvider = memo((props: PropsWithChildren) => {
9299 // will be stuck on the viewer.
93100 ( data . origin === 'canvas' && data . destination !== 'canvas' )
94101 ) {
102+ shouldClearProgressImageOnLoadRef . current = false ;
103+ $isProgressImageResolving . set ( false ) ;
95104 $progressEvent . set ( null ) ;
96105 $progressImage . set ( null ) ;
106+ } else {
107+ shouldClearProgressImageOnLoadRef . current = true ;
108+ $isProgressImageResolving . set ( true ) ;
97109 }
98110 }
99111 } ;
@@ -103,16 +115,36 @@ export const ImageViewerContextProvider = memo((props: PropsWithChildren) => {
103115 return ( ) => {
104116 socket . off ( 'queue_item_status_changed' , onQueueItemStatusChanged ) ;
105117 } ;
106- } , [ $progressEvent , $progressImage , autoSwitch , finishedQueueItemIds , socket ] ) ;
118+ } , [ $isProgressImageResolving , $ progressEvent, $progressImage , autoSwitch , finishedQueueItemIds , socket ] ) ;
107119
108120 const onLoadImage = useCallback ( ( ) => {
121+ if ( ! shouldClearProgressImageOnLoadRef . current ) {
122+ return ;
123+ }
124+
125+ shouldClearProgressImageOnLoadRef . current = false ;
126+ $isProgressImageResolving . set ( false ) ;
109127 $progressEvent . set ( null ) ;
110128 $progressImage . set ( null ) ;
111- } , [ $progressEvent , $progressImage ] ) ;
129+ } , [ $isProgressImageResolving , $ progressEvent, $progressImage ] ) ;
112130
113131 const value = useMemo (
114- ( ) => ( { $progressEvent, $progressImage, $hasProgressImage, onLoadImage } ) ,
115- [ $hasProgressImage , $progressEvent , $progressImage , onLoadImage ]
132+ ( ) => ( {
133+ $progressEvent,
134+ $progressImage,
135+ $hasProgressImage,
136+ $isProgressImageResolving,
137+ $isTemporarilyShowingSelectedImage,
138+ onLoadImage,
139+ } ) ,
140+ [
141+ $hasProgressImage ,
142+ $isProgressImageResolving ,
143+ $isTemporarilyShowingSelectedImage ,
144+ $progressEvent ,
145+ $progressImage ,
146+ onLoadImage ,
147+ ]
116148 ) ;
117149
118150 return < ImageViewerContext . Provider value = { value } > { props . children } </ ImageViewerContext . Provider > ;
0 commit comments