@@ -144,6 +144,9 @@ export class Actions extends BaseActions<LatexEditorState> {
144144 // PDF file watcher - watches directory for PDF file changes
145145 private pdf_watcher ?: PDFWatcher ;
146146
147+ // Debounced version - initialized in _init2()
148+ update_pdf : ( time : number , force : boolean ) => void ;
149+
147150 // Auto-sync function for cursor position changes (forward sync: source → PDF)
148151 private async handle_cursor_sync_to_pdf (
149152 line : number ,
@@ -179,6 +182,11 @@ export class Actions extends BaseActions<LatexEditorState> {
179182
180183 _init2 ( ) : void {
181184 this . set_gutter = this . set_gutter . bind ( this ) ;
185+ // Debounce update_pdf with 500ms delay, trailing only, has to work when PDF watcher fires during the build
186+ this . update_pdf = debounce ( this . _update_pdf . bind ( this ) , 500 , {
187+ leading : false ,
188+ trailing : true ,
189+ } ) ;
182190 if ( ! this . is_public ) {
183191 this . init_bad_filename ( ) ;
184192 this . init_ext_filename ( ) ; // safe to set before syncstring init
@@ -210,7 +218,10 @@ export class Actions extends BaseActions<LatexEditorState> {
210218 this . pdf_watcher = new PDFWatcher (
211219 this . project_id ,
212220 pdfPath ,
213- this . update_pdf . bind ( this ) ,
221+ // We ignore the PDFs timestamp (mtime) and use last_save_time for consistency with build-triggered updates
222+ ( _mtime : number , force : boolean ) => {
223+ this . update_pdf ( this . last_save_time ( ) , force ) ;
224+ } ,
214225 ) ;
215226 await this . pdf_watcher . init ( ) ;
216227 }
@@ -882,22 +893,25 @@ export class Actions extends BaseActions<LatexEditorState> {
882893 if ( this . _has_frame_of_type ( "word_count" ) ) {
883894 run_word_count = this . word_count ( time , force ) ;
884895 }
885- await this . run_latex ( time , force ) ;
896+ // update_pdf=false, because it is deferred until the end
897+ await this . run_latex ( time , force , false ) ;
886898 // ... and then patch the synctex file to align the source line numberings
887899 if ( this . knitr ) {
888900 await this . run_patch_synctex ( time , force ) ;
889901 }
890902
891903 const s = this . store . unsafe_getIn ( [ "build_logs" , "latex" , "stdout" ] ) ;
904+ let update_pdf = true ;
892905 if ( typeof s == "string" ) {
893906 const is_sagetex = s . indexOf ( "sagetex.sty" ) != - 1 ;
894907 const is_pythontex =
895908 s . indexOf ( "pythontex.sty" ) != - 1 || s . indexOf ( "PythonTeX" ) != - 1 ;
896909 if ( is_sagetex || is_pythontex ) {
897910 if ( this . ensure_output_directory_disabled ( ) ) {
898911 // rebuild if build command changed
899- await this . run_latex ( time , true ) ;
912+ await this . run_latex ( time , true , false ) ;
900913 }
914+ update_pdf = false ;
901915 if ( is_sagetex ) {
902916 await this . run_sagetex ( time , force ) ;
903917 }
@@ -908,6 +922,12 @@ export class Actions extends BaseActions<LatexEditorState> {
908922 }
909923 }
910924
925+ // we suppress a cycle of loading the PDF if sagetex or pythontex runs above
926+ // because these two trigger a rebuild and update_pdf on their own at the end
927+ if ( update_pdf ) {
928+ this . update_pdf ( time , force ) ;
929+ }
930+
911931 if ( run_word_count != null ) {
912932 // and finally, wait for word count to finish -- to make clear the whole operation is done
913933 await run_word_count ;
@@ -994,7 +1014,11 @@ export class Actions extends BaseActions<LatexEditorState> {
9941014 }
9951015 }
9961016
997- private async run_latex ( time : number , force : boolean ) : Promise < void > {
1017+ private async run_latex (
1018+ time : number ,
1019+ force : boolean ,
1020+ update_pdf : boolean = true ,
1021+ ) : Promise < void > {
9981022 if ( this . is_stopping ) return ;
9991023 let output : BuildLog ;
10001024 let build_command : string | string [ ] ;
@@ -1051,6 +1075,10 @@ export class Actions extends BaseActions<LatexEditorState> {
10511075 this . check_for_fatal_error ( ) ;
10521076 this . update_gutters ( ) ;
10531077 this . update_gutters_soon ( ) ;
1078+ // Explicit PDF reload after latex compilation
1079+ if ( update_pdf ) {
1080+ this . update_pdf ( time , force ) ;
1081+ }
10541082 }
10551083
10561084 // this *merges* errors from log into an eventually already existing this.parsed_output_log
@@ -1186,7 +1214,7 @@ export class Actions extends BaseActions<LatexEditorState> {
11861214 } ) ;
11871215 }
11881216
1189- update_pdf ( time : number , force : boolean ) : void {
1217+ private _update_pdf ( time : number , force : boolean ) : void {
11901218 const timestamp = this . make_timestamp ( time , force ) ;
11911219 // forget currently cached pdf
11921220 this . _forget_pdf_document ( ) ;
@@ -1230,11 +1258,13 @@ export class Actions extends BaseActions<LatexEditorState> {
12301258 this . get_output_directory ( ) ,
12311259 ) ;
12321260 if ( hash === this . _last_sagetex_hash ) {
1233- // no change - nothing to do
1261+ // no change - nothing to do except updating the pdf preview
1262+ this . update_pdf ( time , force ) ;
12341263 return ;
12351264 }
12361265 } catch ( err ) {
12371266 this . set_error ( err ) ;
1267+ this . update_pdf ( time , force ) ;
12381268 return ;
12391269 } finally {
12401270 this . set_status ( "" ) ;
@@ -1264,6 +1294,7 @@ export class Actions extends BaseActions<LatexEditorState> {
12641294 await this . run_latex ( time + 1 , force ) ;
12651295 } catch ( err ) {
12661296 this . set_error ( err ) ;
1297+ this . update_pdf ( time , force ) ;
12671298 } finally {
12681299 this . _last_sagetex_hash = hash ;
12691300 this . set_status ( "" ) ;
@@ -1303,6 +1334,7 @@ export class Actions extends BaseActions<LatexEditorState> {
13031334 } catch ( err ) {
13041335 this . set_error ( err ) ;
13051336 // this.setState({ pythontex_error: true });
1337+ this . update_pdf ( time , force ) ;
13061338 return ;
13071339 } finally {
13081340 this . set_status ( "" ) ;
@@ -1469,15 +1501,15 @@ export class Actions extends BaseActions<LatexEditorState> {
14691501
14701502 _get_most_recent_output_panel ( ) : string | undefined {
14711503 let result = this . _get_most_recent_active_frame_id_of_type ( "output" ) ;
1472- console . log (
1473- "LaTeX: _get_most_recent_output_panel() via active history returning" ,
1474- result ,
1475- ) ;
1504+ // console.log(
1505+ // "LaTeX: _get_most_recent_output_panel() via active history returning",
1506+ // result,
1507+ // );
14761508
14771509 // If no recently active output panel found, look for any output panel
14781510 if ( ! result ) {
14791511 result = this . _get_any_frame_id_of_type ( "output" ) ;
1480- console . log ( "LaTeX: _get_any_frame_id_of_type() returning" , result ) ;
1512+ // console.log("LaTeX: _get_any_frame_id_of_type() returning", result);
14811513 }
14821514
14831515 return result ;
0 commit comments