@@ -9,7 +9,7 @@ use crate::document::importer::define::URL_FIELD;
99use crate :: document:: importer:: md_importer:: { MDImporter , create_image_block} ;
1010use crate :: entity:: CollabType ;
1111use crate :: entity:: uuid_validation:: DatabaseId ;
12- use futures:: stream:: { self , StreamExt } ;
12+ use futures:: stream;
1313
1414use crate :: core:: collab:: default_client_id;
1515use crate :: database:: database_trait:: NoPersistenceDatabaseCollabService ;
@@ -214,75 +214,40 @@ impl NotionPage {
214214 {
215215 let mut document_resources = HashSet :: new ( ) ;
216216 if let Some ( page_id) = document. get_page_id ( ) {
217- // Start the recursive processing with the root block (page_id)
218- self
219- . process_block_and_children (
220- parent_path,
221- document,
222- & page_id,
223- resources,
224- & file_url_builder,
225- & mut document_resources,
226- )
227- . await ;
228- }
229-
230- document_resources. into_iter ( ) . collect ( )
231- }
232-
233- #[ async_recursion:: async_recursion( ?Send ) ]
234- async fn process_block_and_children < ' a , B , O > (
235- & ' a self ,
236- parent_path : & Path ,
237- document : & mut Document ,
238- block_id : & str ,
239- resources : & [ PathBuf ] ,
240- file_url_builder : & B ,
241- document_resources : & mut HashSet < PathBuf > ,
242- ) where
243- B : Fn ( & ' a str , PathBuf ) -> O + Send + Sync + ' a ,
244- O : Future < Output = Option < String > > + Send + ' a ,
245- {
246- // Process the current block
247- if let Some ( ( block_type, mut block_data) ) = document. get_block_data ( block_id) {
248- if matches ! ( block_type, BlockType :: Image ) {
249- if let Some ( image_url) = block_data
250- . get ( URL_FIELD )
251- . and_then ( |v| v. as_str ( ) )
252- . and_then ( |s| percent_decode_str ( s) . decode_utf8 ( ) . ok ( ) )
253- {
254- let full_image_url = parent_path. join ( image_url. to_string ( ) ) ;
255- let pos = resources. iter ( ) . position ( |r| r == & full_image_url) ;
256- if let Some ( pos) = pos {
257- if let Some ( url) = file_url_builder ( & self . view_id , full_image_url) . await {
258- document_resources. insert ( resources[ pos] . clone ( ) ) ;
259- block_data. insert ( URL_FIELD . to_string ( ) , json ! ( url) ) ;
260- if let Err ( err) = document. update_block ( block_id, block_data) {
261- error ! (
262- "Failed to update block when trying to replace image. error:{:?}" ,
263- err
264- ) ;
217+ let mut stack = vec ! [ page_id] ;
218+ while let Some ( block_id) = stack. pop ( ) {
219+ if let Some ( ( block_type, mut block_data) ) = document. get_block_data ( & block_id) {
220+ if matches ! ( block_type, BlockType :: Image ) {
221+ if let Some ( image_url) = block_data
222+ . get ( URL_FIELD )
223+ . and_then ( |v| v. as_str ( ) )
224+ . and_then ( |s| percent_decode_str ( s) . decode_utf8 ( ) . ok ( ) )
225+ {
226+ let full_image_url = parent_path. join ( image_url. to_string ( ) ) ;
227+ if let Some ( pos) = resources. iter ( ) . position ( |r| r == & full_image_url) {
228+ if let Some ( url) = file_url_builder ( & self . view_id , full_image_url) . await {
229+ document_resources. insert ( resources[ pos] . clone ( ) ) ;
230+ block_data. insert ( URL_FIELD . to_string ( ) , json ! ( url) ) ;
231+ if let Err ( err) = document. update_block ( & block_id, block_data) {
232+ error ! (
233+ "Failed to update block when trying to replace image. error:{:?}" ,
234+ err
235+ ) ;
236+ }
237+ }
265238 }
266239 }
267240 }
268241 }
242+
243+ let block_children_ids = document. get_block_children_ids ( & block_id) ;
244+ for child_id in block_children_ids. into_iter ( ) . rev ( ) {
245+ stack. push ( child_id) ;
246+ }
269247 }
270248 }
271249
272- // Recursively process each child block
273- let block_children_ids = document. get_block_children_ids ( block_id) ;
274- for child_id in block_children_ids. iter ( ) {
275- self
276- . process_block_and_children (
277- parent_path,
278- document,
279- child_id,
280- resources,
281- file_url_builder,
282- document_resources,
283- )
284- . await ;
285- }
250+ document_resources. into_iter ( ) . collect ( )
286251 }
287252
288253 async fn replace_link_views < ' a , ' b , B , O > (
@@ -300,94 +265,53 @@ impl NotionPage {
300265 {
301266 let mut delta_resources = HashSet :: new ( ) ;
302267 if let Some ( first_page_id) = document. get_page_id ( ) {
303- // Start the recursive processing with the first page's root block
304- self
305- . process_link_views_recursive (
306- parent_path,
307- document,
308- & first_page_id,
309- resources,
310- & external_link_views,
311- file_url_builder,
312- & mut delta_resources,
313- )
314- . await ;
315- }
268+ let mut stack = vec ! [ first_page_id] ;
269+ while let Some ( block_id) = stack. pop ( ) {
270+ if let Some ( ( block_type, deltas) ) = document. get_block_delta ( & block_id) {
271+ let block_deltas_result = self
272+ . process_block_deltas (
273+ parent_path,
274+ document,
275+ & block_id,
276+ block_type,
277+ deltas,
278+ & external_link_views,
279+ resources,
280+ file_url_builder,
281+ )
282+ . await ;
316283
317- delta_resources. into_iter ( ) . collect ( )
318- }
284+ delta_resources. extend ( block_deltas_result. delta_resources ) ;
319285
320- #[ async_recursion:: async_recursion]
321- #[ allow( clippy:: too_many_arguments) ]
322- async fn process_link_views_recursive < ' a , ' b , B , O > (
323- & ' b self ,
324- parent_path : & Path ,
325- document : & mut Document ,
326- block_id : & str ,
327- resources : & [ PathBuf ] ,
328- external_link_views : & HashMap < String , NotionPage > ,
329- file_url_builder : & ' a B ,
330- delta_resources : & mut HashSet < PathBuf > ,
331- ) where
332- B : Fn ( & ' a str , PathBuf ) -> O + Send + Sync + ' a ,
333- O : Future < Output = Option < String > > + Send + ' a ,
334- ' b : ' a ,
335- {
336- if let Some ( ( block_type, deltas) ) = document. get_block_delta ( block_id) {
337- let block_deltas_result = self
338- . process_block_deltas (
339- parent_path,
340- document,
341- block_id,
342- block_type,
343- deltas,
344- external_link_views,
345- resources,
346- file_url_builder,
347- )
348- . await ;
349-
350- // Collect resources from this block
351- delta_resources. extend ( block_deltas_result. delta_resources ) ;
352-
353- // Update document deltas if new ones are created
354- if let Some ( new_deltas) = block_deltas_result. new_deltas {
355- if let Err ( err) = document. set_block_delta ( block_id, new_deltas) {
356- error ! (
357- "Failed to set block delta when trying to replace ref link. error: {:?}" ,
358- err
359- ) ;
286+ if let Some ( new_deltas) = block_deltas_result. new_deltas {
287+ if let Err ( err) = document. set_block_delta ( & block_id, new_deltas) {
288+ error ! (
289+ "Failed to set block delta when trying to replace ref link. error: {:?}" ,
290+ err
291+ ) ;
292+ }
293+ }
294+
295+ for image_url in block_deltas_result. new_delta_image_blocks {
296+ let new_block_id = crate :: document:: document_data:: generate_id ( ) ;
297+ let image_block = create_image_block ( & new_block_id, image_url, & block_id) ;
298+ if let Err ( err) = document. insert_block ( image_block, Some ( block_id. clone ( ) ) ) {
299+ error ! (
300+ "Failed to insert image block when trying to replace delta link. error: {:?}" ,
301+ err
302+ ) ;
303+ }
304+ }
360305 }
361- }
362306
363- // Insert new image blocks if any are created
364- for image_url in block_deltas_result. new_delta_image_blocks {
365- let new_block_id = crate :: document:: document_data:: generate_id ( ) ;
366- let image_block = create_image_block ( & new_block_id, image_url, block_id) ;
367- if let Err ( err) = document. insert_block ( image_block, Some ( block_id. to_string ( ) ) ) {
368- error ! (
369- "Failed to insert image block when trying to replace delta link. error: {:?}" ,
370- err
371- ) ;
307+ let block_children_ids = document. get_block_children_ids ( & block_id) ;
308+ for child_id in block_children_ids. into_iter ( ) . rev ( ) {
309+ stack. push ( child_id) ;
372310 }
373311 }
374312 }
375313
376- // Recursively process each child block
377- let block_children_ids = document. get_block_children_ids ( block_id) ;
378- for child_id in block_children_ids. iter ( ) {
379- self
380- . process_link_views_recursive (
381- parent_path,
382- document,
383- child_id,
384- resources,
385- external_link_views,
386- file_url_builder,
387- delta_resources,
388- )
389- . await ;
390- }
314+ delta_resources. into_iter ( ) . collect ( )
391315 }
392316
393317 /// Process the deltas for a block, looking for links to replace
@@ -690,23 +614,27 @@ impl NotionPage {
690614pub async fn build_imported_collab_recursively < ' a > (
691615 notion_page : NotionPage ,
692616) -> ImportedCollabInfoStream < ' a > {
693- let imported_collab_info = notion_page. build_imported_collab ( ) . await ;
694- let initial_stream: ImportedCollabInfoStream = match imported_collab_info {
695- Ok ( Some ( info) ) => Box :: pin ( stream:: once ( async { info } ) ) ,
696- Ok ( None ) => Box :: pin ( stream:: empty ( ) ) ,
697- Err ( _) => Box :: pin ( stream:: empty ( ) ) ,
698- } ;
699-
700- let child_streams = notion_page
701- . children
702- . into_iter ( )
703- . map ( |child| async move { build_imported_collab_recursively ( child) . await } ) ;
704-
705- let child_stream = stream:: iter ( child_streams)
706- . then ( |stream_future| stream_future)
707- . flatten ( ) ;
708-
709- Box :: pin ( initial_stream. chain ( child_stream) )
617+ let stack = vec ! [ notion_page] ;
618+ let stream = stream:: unfold ( stack, |mut stack| async move {
619+ while let Some ( page) = stack. pop ( ) {
620+ let result = page. build_imported_collab ( ) . await ;
621+ let children = page. children ;
622+ for child in children. into_iter ( ) . rev ( ) {
623+ stack. push ( child) ;
624+ }
625+ match result {
626+ Ok ( Some ( info) ) => return Some ( ( info, stack) ) ,
627+ Ok ( None ) => continue ,
628+ Err ( err) => {
629+ error ! ( "Failed to build imported collab: {}" , err) ;
630+ continue ;
631+ } ,
632+ }
633+ }
634+ None
635+ } ) ;
636+
637+ Box :: pin ( stream)
710638}
711639
712640pub struct ProcessBlockDeltaResult {
0 commit comments