@@ -26,7 +26,9 @@ import { debounce } from "lodash";
26
26
import { React , ReactDOM , Rendered , CSS } from "../../app-framework" ;
27
27
import { use_font_size_scaling } from "../frame-tree/hooks" ;
28
28
import { EditorState } from "../frame-tree/types" ;
29
- import { raw_url } from "../frame-tree/util" ;
29
+ import { useEffect , useRef , useState } from "react" ;
30
+ import { webapp_client } from "@cocalc/frontend/webapp-client" ;
31
+ import { Spin } from "antd" ;
30
32
31
33
interface Props {
32
34
id : string ;
@@ -42,6 +44,7 @@ interface Props {
42
44
mode : "rmd" | undefined ;
43
45
style ?: any ; // style should be static; change does NOT cause update.
44
46
derived_file_types : Set < string > ;
47
+ value ?: string ;
45
48
}
46
49
47
50
function should_memoize ( prev , next ) {
@@ -73,15 +76,56 @@ export const IFrameHTML: React.FC<Props> = React.memo((props: Props) => {
73
76
style,
74
77
derived_file_types,
75
78
tab_is_visible,
79
+ value,
76
80
} = props ;
77
81
78
- const rootEl = React . useRef ( null ) ;
79
- const iframe = React . useRef ( null ) ;
80
- const mounted = React . useRef ( false ) ;
82
+ // during init definitely nothing available to show users; this
83
+ // is only needed for rmd mode where an aux file loaded from server.
84
+ const [ init , setInit ] = useState < boolean > ( mode == "rmd" ) ;
85
+ const [ srcDoc , setSrcDoc ] = useState < string | null > ( null ) ;
86
+
87
+ useEffect ( ( ) => {
88
+ if ( mode != "rmd" ) {
89
+ setInit ( false ) ;
90
+ return ;
91
+ }
92
+ let actual_path = path ;
93
+ if ( mode == "rmd" && derived_file_types != undefined ) {
94
+ if ( derived_file_types . contains ( "html" ) ) {
95
+ // keep path as it is; don't remove this case though because of the else
96
+ } else if ( derived_file_types . contains ( "nb.html" ) ) {
97
+ actual_path = change_filename_extension ( path , "nb.html" ) ;
98
+ } else {
99
+ setSrcDoc ( null ) ;
100
+ }
101
+ }
102
+
103
+ // read actual_path and set srcDoc to it.
104
+ ( async ( ) => {
105
+ let buf ;
106
+ try {
107
+ buf = await webapp_client . project_client . readFile ( {
108
+ project_id,
109
+ path : actual_path ,
110
+ } ) ;
111
+ } catch ( err ) {
112
+ actions . set_error ( `${ err } ` ) ;
113
+ return ;
114
+ } finally {
115
+ // done -- we tried
116
+ setInit ( false ) ;
117
+ }
118
+ setSrcDoc ( buf . toString ( "utf8" ) ) ;
119
+ } ) ( ) ;
120
+ } , [ reload , mode , path , derived_file_types ] ) ;
121
+
122
+ const rootEl = useRef ( null ) ;
123
+ const iframe = useRef ( null ) ;
124
+ const mounted = useRef ( false ) ;
81
125
const scaling = use_font_size_scaling ( font_size ) ;
82
126
83
127
// once after mounting
84
- React . useEffect ( function ( ) {
128
+ useEffect ( function ( ) {
85
129
mounted . current = true ;
86
130
reload_iframe ( ) ;
87
131
set_iframe_style ( scaling ) ;
@@ -90,18 +134,18 @@ export const IFrameHTML: React.FC<Props> = React.memo((props: Props) => {
90
134
} ;
91
135
} , [ ] ) ;
92
136
93
- React . useEffect (
137
+ useEffect (
94
138
function ( ) {
95
139
if ( tab_is_visible ) restore_scroll ( ) ;
96
140
} ,
97
- [ tab_is_visible ]
141
+ [ tab_is_visible ] ,
98
142
) ;
99
143
100
- React . useEffect (
144
+ useEffect (
101
145
function ( ) {
102
146
set_iframe_style ( scaling ) ;
103
147
} ,
104
- [ scaling ]
148
+ [ scaling ] ,
105
149
) ;
106
150
107
151
function click_iframe ( ) : void {
@@ -132,7 +176,7 @@ export const IFrameHTML: React.FC<Props> = React.memo((props: Props) => {
132
176
if ( node != null && node . contentDocument != null ) {
133
177
node . contentDocument . addEventListener (
134
178
"scroll" ,
135
- debounce ( ( ) => on_scroll ( ) , 150 )
179
+ debounce ( ( ) => on_scroll ( ) , 150 ) ,
136
180
) ;
137
181
}
138
182
}
@@ -156,27 +200,25 @@ export const IFrameHTML: React.FC<Props> = React.memo((props: Props) => {
156
200
}
157
201
158
202
function render_iframe ( ) {
159
- let actual_path = path ;
160
- if ( mode == "rmd" && derived_file_types != undefined ) {
161
- if ( derived_file_types . contains ( "html" ) ) {
162
- // keep path as it is; don't remove this case though because of the else
163
- } else if ( derived_file_types . contains ( "nb.html" ) ) {
164
- actual_path = change_filename_extension ( path , "nb.html" ) ;
165
- } else {
166
- return render_no_html ( ) ;
167
- }
203
+ if ( init ) {
204
+ // in the init phase.
205
+ return (
206
+ < div style = { { margin : "15px auto" } } >
207
+ < Spin />
208
+ </ div >
209
+ ) ;
210
+ }
211
+ if ( mode == "rmd" && srcDoc == null ) {
212
+ return render_no_html ( ) ;
168
213
}
169
-
170
- // param below is just to avoid caching.
171
- const src = `${ raw_url ( project_id , actual_path ) } ?param=${ reload } ` ;
172
-
173
214
return (
174
215
< iframe
175
216
ref = { iframe }
176
- src = { src }
217
+ srcDoc = { mode != "rmd" ? value : ( srcDoc ?? "" ) }
218
+ sandbox = "allow-forms allow-scripts allow-presentation"
177
219
width = { "100%" }
178
220
height = { "100%" }
179
- style = { { border : 0 , opacity : 0 , ...style } }
221
+ style = { { border : 0 , ...style } }
180
222
onLoad = { iframe_loaded }
181
223
/>
182
224
) ;
@@ -208,7 +250,7 @@ export const IFrameHTML: React.FC<Props> = React.memo((props: Props) => {
208
250
return (
209
251
< div >
210
252
< p > There is no rendered HTML file available.</ p >
211
- { derived_file_types . size > 0 ? (
253
+ { ( derived_file_types ? .size ?? 0 ) > 0 ? (
212
254
< p >
213
255
Instead, you might want to switch to the{ " " }
214
256
{ list_alternatives ( derived_file_types ) } view by selecting it via the
0 commit comments