mirror of
				https://github.com/AppFlowy-IO/AppFlowy.git
				synced 2025-10-31 01:54:37 +00:00 
			
		
		
		
	fix: insert reference page in nested page
This commit is contained in:
		
							parent
							
								
									5e2ed56f5b
								
							
						
					
					
						commit
						f0d2cf7da3
					
				
							
								
								
									
										1
									
								
								.github/workflows/flutter_ci.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/flutter_ci.yaml
									
									
									
									
										vendored
									
									
								
							| @ -134,6 +134,7 @@ jobs: | |||||||
|             fail_ci_if_error: true |             fail_ci_if_error: true | ||||||
|             verbose: true |             verbose: true | ||||||
|             os: ${{ matrix.os }} |             os: ${{ matrix.os }} | ||||||
|  |             token: ${{ secrets.CODECOV_TOKEN }} | ||||||
|           attempt_limit: 20 |           attempt_limit: 20 | ||||||
|           attempt_delay: 10000 |           attempt_delay: 10000 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								.github/workflows/integration_test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/integration_test.yml
									
									
									
									
										vendored
									
									
								
							| @ -136,5 +136,6 @@ jobs: | |||||||
|             fail_ci_if_error: true |             fail_ci_if_error: true | ||||||
|             verbose: true |             verbose: true | ||||||
|             os: ${{ matrix.os }} |             os: ${{ matrix.os }} | ||||||
|  |             token: ${{ secrets.CODECOV_TOKEN }} | ||||||
|           attempt_limit: 20 |           attempt_limit: 20 | ||||||
|           attempt_delay: 10000 |           attempt_delay: 10000 | ||||||
| @ -1,9 +1,12 @@ | |||||||
|  | import 'package:appflowy/generated/locale_keys.g.dart'; | ||||||
| import 'package:appflowy/plugins/database_view/board/presentation/board_page.dart'; | import 'package:appflowy/plugins/database_view/board/presentation/board_page.dart'; | ||||||
| import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_page.dart'; | import 'package:appflowy/plugins/database_view/calendar/presentation/calendar_page.dart'; | ||||||
| import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart'; | import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart'; | ||||||
| import 'package:appflowy/plugins/document/presentation/editor_plugins/base/link_to_page_widget.dart'; | import 'package:appflowy/plugins/document/presentation/editor_plugins/base/link_to_page_widget.dart'; | ||||||
|  | import 'package:appflowy/workspace/presentation/home/menu/view/view_item.dart'; | ||||||
| import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart'; | import 'package:appflowy_backend/protobuf/flowy-folder2/protobuf.dart'; | ||||||
| import 'package:appflowy_editor/appflowy_editor.dart'; | import 'package:appflowy_editor/appflowy_editor.dart'; | ||||||
|  | import 'package:easy_localization/easy_localization.dart'; | ||||||
| import 'package:flowy_infra/uuid.dart'; | import 'package:flowy_infra/uuid.dart'; | ||||||
| import 'package:flutter_test/flutter_test.dart'; | import 'package:flutter_test/flutter_test.dart'; | ||||||
| import 'package:integration_test/integration_test.dart'; | import 'package:integration_test/integration_test.dart'; | ||||||
| @ -61,6 +64,54 @@ void main() { | |||||||
|         findsOneWidget, |         findsOneWidget, | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|  | 
 | ||||||
|  |     testWidgets('create a grid inside a document', (tester) async { | ||||||
|  |       await tester.initializeAppFlowy(); | ||||||
|  |       await tester.tapGoButton(); | ||||||
|  | 
 | ||||||
|  |       await createInlineDatabase(tester, ViewLayoutPB.Grid); | ||||||
|  | 
 | ||||||
|  |       // validate the referenced grid is inserted | ||||||
|  |       expect( | ||||||
|  |         find.descendant( | ||||||
|  |           of: find.byType(AppFlowyEditor), | ||||||
|  |           matching: find.byType(GridPage), | ||||||
|  |         ), | ||||||
|  |         findsOneWidget, | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     testWidgets('create a board inside a document', (tester) async { | ||||||
|  |       await tester.initializeAppFlowy(); | ||||||
|  |       await tester.tapGoButton(); | ||||||
|  | 
 | ||||||
|  |       await createInlineDatabase(tester, ViewLayoutPB.Board); | ||||||
|  | 
 | ||||||
|  |       // validate the referenced grid is inserted | ||||||
|  |       expect( | ||||||
|  |         find.descendant( | ||||||
|  |           of: find.byType(AppFlowyEditor), | ||||||
|  |           matching: find.byType(BoardPage), | ||||||
|  |         ), | ||||||
|  |         findsOneWidget, | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     testWidgets('create a calendar inside a document', (tester) async { | ||||||
|  |       await tester.initializeAppFlowy(); | ||||||
|  |       await tester.tapGoButton(); | ||||||
|  | 
 | ||||||
|  |       await createInlineDatabase(tester, ViewLayoutPB.Calendar); | ||||||
|  | 
 | ||||||
|  |       // validate the referenced grid is inserted | ||||||
|  |       expect( | ||||||
|  |         find.descendant( | ||||||
|  |           of: find.byType(AppFlowyEditor), | ||||||
|  |           matching: find.byType(CalendarPage), | ||||||
|  |         ), | ||||||
|  |         findsOneWidget, | ||||||
|  |       ); | ||||||
|  |     }); | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -75,11 +126,13 @@ Future<void> insertReferenceDatabase( | |||||||
|   await tester.createNewPageWithName( |   await tester.createNewPageWithName( | ||||||
|     name: name, |     name: name, | ||||||
|     layout: layout, |     layout: layout, | ||||||
|  |     openAfterCreated: false, | ||||||
|   ); |   ); | ||||||
|   // create a new document |   // create a new document | ||||||
|   await tester.createNewPageWithName( |   await tester.createNewPageWithName( | ||||||
|     name: 'insert_a_reference_${layout.name}', |     name: 'insert_a_reference_${layout.name}', | ||||||
|     layout: ViewLayoutPB.Document, |     layout: ViewLayoutPB.Document, | ||||||
|  |     openAfterCreated: true, | ||||||
|   ); |   ); | ||||||
|   // tap the first line of the document |   // tap the first line of the document | ||||||
|   await tester.editor.tapLineOfEditorAt(0); |   await tester.editor.tapLineOfEditorAt(0); | ||||||
| @ -98,3 +151,38 @@ Future<void> insertReferenceDatabase( | |||||||
|   expect(referencedDatabase, findsOneWidget); |   expect(referencedDatabase, findsOneWidget); | ||||||
|   await tester.tapButton(referencedDatabase); |   await tester.tapButton(referencedDatabase); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | Future<void> createInlineDatabase( | ||||||
|  |   WidgetTester tester, | ||||||
|  |   ViewLayoutPB layout, | ||||||
|  | ) async { | ||||||
|  |   // create a new document | ||||||
|  |   final documentName = 'insert_a_inline_${layout.name}'; | ||||||
|  |   await tester.createNewPageWithName( | ||||||
|  |     name: documentName, | ||||||
|  |     layout: ViewLayoutPB.Document, | ||||||
|  |     openAfterCreated: true, | ||||||
|  |   ); | ||||||
|  |   // tap the first line of the document | ||||||
|  |   await tester.editor.tapLineOfEditorAt(0); | ||||||
|  |   // insert a referenced view | ||||||
|  |   await tester.editor.showSlashMenu(); | ||||||
|  |   final name = switch (layout) { | ||||||
|  |     ViewLayoutPB.Grid => LocaleKeys.document_slashMenu_grid_createANewGrid.tr(), | ||||||
|  |     ViewLayoutPB.Board => | ||||||
|  |       LocaleKeys.document_slashMenu_board_createANewBoard.tr(), | ||||||
|  |     ViewLayoutPB.Calendar => | ||||||
|  |       LocaleKeys.document_slashMenu_calendar_createANewCalendar.tr(), | ||||||
|  |     _ => '', | ||||||
|  |   }; | ||||||
|  |   await tester.editor.tapSlashMenuItemWithName( | ||||||
|  |     name, | ||||||
|  |   ); | ||||||
|  |   await tester.pumpAndSettle(); | ||||||
|  | 
 | ||||||
|  |   final childViews = tester | ||||||
|  |       .widget<SingleInnerViewItem>(tester.findPageName(documentName)) | ||||||
|  |       .view | ||||||
|  |       .childViews; | ||||||
|  |   expect(childViews.length, 1); | ||||||
|  | } | ||||||
|  | |||||||
| @ -234,13 +234,19 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> { | |||||||
|         ), |         ), | ||||||
|       ), |       ), | ||||||
|       DatabaseBlockKeys.gridType: DatabaseViewBlockComponentBuilder( |       DatabaseBlockKeys.gridType: DatabaseViewBlockComponentBuilder( | ||||||
|         configuration: configuration, |         configuration: configuration.copyWith( | ||||||
|  |           padding: (_) => const EdgeInsets.symmetric(vertical: 10), | ||||||
|  |         ), | ||||||
|       ), |       ), | ||||||
|       DatabaseBlockKeys.boardType: DatabaseViewBlockComponentBuilder( |       DatabaseBlockKeys.boardType: DatabaseViewBlockComponentBuilder( | ||||||
|         configuration: configuration, |         configuration: configuration.copyWith( | ||||||
|  |           padding: (_) => const EdgeInsets.symmetric(vertical: 10), | ||||||
|  |         ), | ||||||
|       ), |       ), | ||||||
|       DatabaseBlockKeys.calendarType: DatabaseViewBlockComponentBuilder( |       DatabaseBlockKeys.calendarType: DatabaseViewBlockComponentBuilder( | ||||||
|         configuration: configuration, |         configuration: configuration.copyWith( | ||||||
|  |           padding: (_) => const EdgeInsets.symmetric(vertical: 10), | ||||||
|  |         ), | ||||||
|       ), |       ), | ||||||
|       CalloutBlockKeys.type: CalloutBlockComponentBuilder( |       CalloutBlockKeys.type: CalloutBlockComponentBuilder( | ||||||
|         configuration: configuration, |         configuration: configuration, | ||||||
|  | |||||||
| @ -82,23 +82,16 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> { | |||||||
|   final _focusNode = FocusNode(debugLabel: 'reference_list_widget'); |   final _focusNode = FocusNode(debugLabel: 'reference_list_widget'); | ||||||
|   EditorStyle get style => widget.editorState.editorStyle; |   EditorStyle get style => widget.editorState.editorStyle; | ||||||
|   int _selectedIndex = 0; |   int _selectedIndex = 0; | ||||||
|   int _totalItems = 0; |   final int _totalItems = 0; | ||||||
|   Future<List<(ViewPB, List<ViewPB>)>>? _availableLayout; |   Future<List<ViewPB>>? _availableLayout; | ||||||
|   final Map<int, (ViewPB, ViewPB)> _items = {}; |   final List<ViewPB> _items = []; | ||||||
| 
 | 
 | ||||||
|   Future<List<(ViewPB, List<ViewPB>)>> fetchItems() async { |   Future<List<ViewPB>> fetchItems() async { | ||||||
|     final items = |     final items = | ||||||
|         await ViewBackendService().fetchViewsWithLayoutType(widget.layoutType); |         await ViewBackendService().fetchViewsWithLayoutType(widget.layoutType); | ||||||
| 
 |     _items | ||||||
|     int index = 0; |       ..clear() | ||||||
|     for (final (app, children) in items) { |       ..addAll(items); | ||||||
|       for (final view in children) { |  | ||||||
|         _items.putIfAbsent(index, () => (app, view)); |  | ||||||
|         index += 1; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     _totalItems = _items.length; |  | ||||||
|     return items; |     return items; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -176,8 +169,8 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> { | |||||||
|       newSelectedIndex %= _totalItems; |       newSelectedIndex %= _totalItems; | ||||||
|     } else if (event.logicalKey == LogicalKeyboardKey.enter) { |     } else if (event.logicalKey == LogicalKeyboardKey.enter) { | ||||||
|       widget.onSelected( |       widget.onSelected( | ||||||
|         _items[_selectedIndex]!.$1, |         _items[_selectedIndex], | ||||||
|         _items[_selectedIndex]!.$2, |         _items[_selectedIndex], | ||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -191,10 +184,10 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> { | |||||||
|   Widget _buildListWidget( |   Widget _buildListWidget( | ||||||
|     BuildContext context, |     BuildContext context, | ||||||
|     int selectedIndex, |     int selectedIndex, | ||||||
|     Future<List<(ViewPB, List<ViewPB>)>>? items, |     Future<List<ViewPB>>? items, | ||||||
|   ) { |   ) { | ||||||
|     int index = 0; |     int index = 0; | ||||||
|     return FutureBuilder<List<(ViewPB, List<ViewPB>)>>( |     return FutureBuilder<List<ViewPB>>( | ||||||
|       builder: (context, snapshot) { |       builder: (context, snapshot) { | ||||||
|         if (snapshot.hasData && |         if (snapshot.hasData && | ||||||
|             snapshot.connectionState == ConnectionState.done) { |             snapshot.connectionState == ConnectionState.done) { | ||||||
| @ -211,35 +204,23 @@ class _LinkToPageMenuState extends State<LinkToPageMenu> { | |||||||
|           ]; |           ]; | ||||||
| 
 | 
 | ||||||
|           if (views != null && views.isNotEmpty) { |           if (views != null && views.isNotEmpty) { | ||||||
|             for (final (view, viewChildren) in views) { |             for (final view in views) { | ||||||
|               if (viewChildren.isNotEmpty) { |  | ||||||
|                 children.add( |  | ||||||
|                   Padding( |  | ||||||
|                     padding: const EdgeInsets.symmetric(vertical: 4), |  | ||||||
|                     child: FlowyText.regular( |  | ||||||
|                       view.name, |  | ||||||
|                     ), |  | ||||||
|                   ), |  | ||||||
|                 ); |  | ||||||
| 
 |  | ||||||
|                 for (final value in viewChildren) { |  | ||||||
|               children.add( |               children.add( | ||||||
|                 FlowyButton( |                 FlowyButton( | ||||||
|                   isSelected: index == _selectedIndex, |                   isSelected: index == _selectedIndex, | ||||||
|                   leftIcon: svgWidget( |                   leftIcon: svgWidget( | ||||||
|                         value.iconName, |                     view.iconName, | ||||||
|                     color: Theme.of(context).iconTheme.color, |                     color: Theme.of(context).iconTheme.color, | ||||||
|                   ), |                   ), | ||||||
|                       text: FlowyText.regular(value.name), |                   text: FlowyText.regular(view.name), | ||||||
|                       onTap: () => widget.onSelected(view, value), |                   onTap: () => widget.onSelected(view, view), | ||||||
|                 ), |                 ), | ||||||
|               ); |               ); | ||||||
| 
 | 
 | ||||||
|               index += 1; |               index += 1; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
|             } | 
 | ||||||
|           } |  | ||||||
|           return Column( |           return Column( | ||||||
|             crossAxisAlignment: CrossAxisAlignment.stretch, |             crossAxisAlignment: CrossAxisAlignment.stretch, | ||||||
|             children: children, |             children: children, | ||||||
|  | |||||||
| @ -82,6 +82,11 @@ class _DatabaseBlockComponentWidgetState | |||||||
|       }, |       }, | ||||||
|     ); |     ); | ||||||
| 
 | 
 | ||||||
|  |     child = Padding( | ||||||
|  |       padding: padding, | ||||||
|  |       child: child, | ||||||
|  |     ); | ||||||
|  | 
 | ||||||
|     if (widget.actionBuilder != null) { |     if (widget.actionBuilder != null) { | ||||||
|       child = BlockComponentActionWrapper( |       child = BlockComponentActionWrapper( | ||||||
|         node: widget.node, |         node: widget.node, | ||||||
|  | |||||||
| @ -17,11 +17,8 @@ SelectionMenuItem inlineGridMenuItem(DocumentBloc documentBloc) => | |||||||
|       ), |       ), | ||||||
|       keywords: ['grid', 'database'], |       keywords: ['grid', 'database'], | ||||||
|       handler: (editorState, menuService, context) async { |       handler: (editorState, menuService, context) async { | ||||||
|         if (!documentBloc.view.hasParentViewId()) { |         // create the view inside current page | ||||||
|           return; |         final parentViewId = documentBloc.view.id; | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         final parentViewId = documentBloc.view.parentViewId; |  | ||||||
|         ViewBackendService.createView( |         ViewBackendService.createView( | ||||||
|           parentViewId: parentViewId, |           parentViewId: parentViewId, | ||||||
|           openAfterCreate: false, |           openAfterCreate: false, | ||||||
| @ -45,11 +42,8 @@ SelectionMenuItem inlineBoardMenuItem(DocumentBloc documentBloc) => | |||||||
|       ), |       ), | ||||||
|       keywords: ['board', 'kanban', 'database'], |       keywords: ['board', 'kanban', 'database'], | ||||||
|       handler: (editorState, menuService, context) async { |       handler: (editorState, menuService, context) async { | ||||||
|         if (!documentBloc.view.hasParentViewId()) { |         // create the view inside current page | ||||||
|           return; |         final parentViewId = documentBloc.view.id; | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         final parentViewId = documentBloc.view.parentViewId; |  | ||||||
|         ViewBackendService.createView( |         ViewBackendService.createView( | ||||||
|           parentViewId: parentViewId, |           parentViewId: parentViewId, | ||||||
|           name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), |           name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), | ||||||
| @ -72,11 +66,8 @@ SelectionMenuItem inlineCalendarMenuItem(DocumentBloc documentBloc) => | |||||||
|       ), |       ), | ||||||
|       keywords: ['calendar', 'database'], |       keywords: ['calendar', 'database'], | ||||||
|       handler: (editorState, menuService, context) async { |       handler: (editorState, menuService, context) async { | ||||||
|         if (!documentBloc.view.hasParentViewId()) { |         // create the view inside current page | ||||||
|           return; |         final parentViewId = documentBloc.view.id; | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         final parentViewId = documentBloc.view.parentViewId; |  | ||||||
|         ViewBackendService.createView( |         ViewBackendService.createView( | ||||||
|           parentViewId: parentViewId, |           parentViewId: parentViewId, | ||||||
|           name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), |           name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), | ||||||
|  | |||||||
| @ -2,7 +2,6 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selec | |||||||
| import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart'; | import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart'; | ||||||
| import 'package:appflowy/workspace/application/view/view_ext.dart'; | import 'package:appflowy/workspace/application/view/view_ext.dart'; | ||||||
| import 'package:appflowy/workspace/application/view/view_service.dart'; | import 'package:appflowy/workspace/application/view/view_service.dart'; | ||||||
| import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; |  | ||||||
| import 'package:appflowy_editor/appflowy_editor.dart'; | import 'package:appflowy_editor/appflowy_editor.dart'; | ||||||
| 
 | 
 | ||||||
| enum MentionType { | enum MentionType { | ||||||
| @ -98,17 +97,11 @@ class InlinePageReferenceService { | |||||||
| 
 | 
 | ||||||
|   Future<List<SelectionMenuItem>> generatePageItems(String character) async { |   Future<List<SelectionMenuItem>> generatePageItems(String character) async { | ||||||
|     final service = ViewBackendService(); |     final service = ViewBackendService(); | ||||||
|     final List<(ViewPB, List<ViewPB>)> pbViews = await service.fetchViews( |     final views = await service.fetchViews(); | ||||||
|       (_, __) => true, |     if (views.isEmpty) { | ||||||
|     ); |  | ||||||
|     if (pbViews.isEmpty) { |  | ||||||
|       return []; |       return []; | ||||||
|     } |     } | ||||||
|     final List<SelectionMenuItem> pages = []; |     final List<SelectionMenuItem> pages = []; | ||||||
|     final List<ViewPB> views = []; |  | ||||||
|     for (final element in pbViews) { |  | ||||||
|       views.addAll(element.$2); |  | ||||||
|     } |  | ||||||
|     views.sort(((a, b) => b.createTime.compareTo(a.createTime))); |     views.sort(((a, b) => b.createTime.compareTo(a.createTime))); | ||||||
| 
 | 
 | ||||||
|     for (final view in views) { |     for (final view in views) { | ||||||
|  | |||||||
| @ -173,41 +173,51 @@ class ViewBackendService { | |||||||
|     return FolderEventMoveNestedView(payload).send(); |     return FolderEventMoveNestedView(payload).send(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<List<(ViewPB, List<ViewPB>)>> fetchViewsWithLayoutType( |   Future<List<ViewPB>> fetchViewsWithLayoutType( | ||||||
|     ViewLayoutPB? layoutType, |     ViewLayoutPB? layoutType, | ||||||
|   ) async { |   ) async { | ||||||
|     return fetchViews((workspace, view) { |     final views = await fetchViews(); | ||||||
|       if (layoutType != null) { |     if (layoutType == null) { | ||||||
|         return view.layout == layoutType; |       return views; | ||||||
|     } |     } | ||||||
|       return true; |     return views | ||||||
|     }); |         .where( | ||||||
|  |           (element) => layoutType == element.layout, | ||||||
|  |         ) | ||||||
|  |         .toList(); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   Future<List<(ViewPB, List<ViewPB>)>> fetchViews( |   Future<List<ViewPB>> fetchViews() async { | ||||||
|     bool Function(WorkspaceSettingPB workspace, ViewPB view) filter, |     final result = <ViewPB>[]; | ||||||
|   ) async { |  | ||||||
|     final result = <(ViewPB, List<ViewPB>)>[]; |  | ||||||
|     return FolderEventGetCurrentWorkspace().send().then((value) async { |     return FolderEventGetCurrentWorkspace().send().then((value) async { | ||||||
|       final workspaces = value.getLeftOrNull<WorkspaceSettingPB>(); |       final workspaces = value.getLeftOrNull<WorkspaceSettingPB>(); | ||||||
|       if (workspaces != null) { |       if (workspaces != null) { | ||||||
|         final views = workspaces.workspace.views; |         final views = workspaces.workspace.views; | ||||||
|         for (final view in views) { |         for (final view in views) { | ||||||
|           final childViews = await getChildViews(viewId: view.id).then( |           result.add(view); | ||||||
|             (value) => value |           final childViews = await getAllViews(view); | ||||||
|                 .getLeftOrNull<List<ViewPB>>() |           result.addAll(childViews); | ||||||
|                 ?.where((e) => filter(workspaces, e)) |  | ||||||
|                 .toList(), |  | ||||||
|           ); |  | ||||||
|           if (childViews != null && childViews.isNotEmpty) { |  | ||||||
|             result.add((view, childViews)); |  | ||||||
|           } |  | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       return result; |       return result; | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   Future<List<ViewPB>> getAllViews(ViewPB view) async { | ||||||
|  |     final result = <ViewPB>[]; | ||||||
|  |     final childViews = await getChildViews(viewId: view.id).then( | ||||||
|  |       (value) => value.getLeftOrNull<List<ViewPB>>()?.toList(), | ||||||
|  |     ); | ||||||
|  |     if (childViews != null && childViews.isNotEmpty) { | ||||||
|  |       result.addAll(childViews); | ||||||
|  |       final views = await Future.wait( | ||||||
|  |         childViews.map((e) async => await getAllViews(e)), | ||||||
|  |       ); | ||||||
|  |       result.addAll(views.expand((element) => element)); | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   static Future<Either<ViewPB, FlowyError>> getView( |   static Future<Either<ViewPB, FlowyError>> getView( | ||||||
|     String viewID, |     String viewID, | ||||||
|   ) async { |   ) async { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Lucas.Xu
						Lucas.Xu