From 771fb6c428a9f13e89c314e2eda1f30455674ded Mon Sep 17 00:00:00 2001 From: Efra Espada Date: Sat, 5 Oct 2024 00:42:05 +0200 Subject: [PATCH] feature: navigation over real locations working :rocket: --- example/assets/preview_config.json | 129 ++++------ example/lib/catalog/catalog_component.dart | 221 +++++++++--------- example/lib/catalog/widgets/main_screen.dart | 10 +- .../{body_widget => screen}/body_widget.dart | 10 +- .../counter_widget.dart | 10 +- .../catalog/widgets/screen/fab_widget.dart | 10 +- .../catalog/preview/main_screen.preview.dart | 35 +-- example/lib/widgets/screen/body_widget.dart | 2 - .../catalog/preview/body_widget.preview.dart | 35 +-- .../preview/counter_widget.preview.dart | 34 +-- .../catalog/preview/fab_widget.preview.dart | 32 ++- .../lib/widgets/screen/counter_widget.dart | 2 - lib/catalog.dart | 1 + .../bin/catalog_builder/catalog_builder.dart | 78 ++++++- .../bin/preview_builder/preview_builder.dart | 8 + lib/src/bin/tasks/tasks/catalog_task.dart | 132 +++-------- lib/src/bin/tasks/tasks/format_task.dart | 2 +- lib/src/bin/tasks/tasks/preview_task.dart | 1 + lib/src/builders/catalog/built_component.dart | 6 + lib/src/builders/catalog/component_node.dart | 101 ++++---- lib/src/builders/catalog/drawer_preview.dart | 67 ++---- .../builders/catalog/preview_scaffold.dart | 12 +- lib/src/builders/catalog/tree_element.dart | 8 - .../catalog/tree_elements_builder.dart | 59 +++++ .../preview/parent_preview_widget.dart | 7 +- 25 files changed, 516 insertions(+), 496 deletions(-) rename example/lib/catalog/widgets/{body_widget => screen}/body_widget.dart (67%) rename example/lib/catalog/widgets/{counter_widget => screen}/counter_widget.dart (67%) delete mode 100644 lib/src/builders/catalog/tree_element.dart create mode 100644 lib/src/builders/catalog/tree_elements_builder.dart diff --git a/example/assets/preview_config.json b/example/assets/preview_config.json index de912b8..5607fa4 100644 --- a/example/assets/preview_config.json +++ b/example/assets/preview_config.json @@ -1,38 +1,14 @@ { "id": "catalog", "route": "/", - "builtComponent": { - "path": "./lib/catalog/catalog_component.dart", - "route": "", - "package": "package:example/catalog/catalog_component.dart", - "clazzName": "CatalogComponent", - "preview": null - }, "builtComponents": {}, "children": { "widgets": { "id": "widgets", - "route": "/widgets", - "builtComponent": { - "path": "./lib/catalog/widgets/main_screen.dart", - "route": "widgets", - "package": "package:example/catalog/widgets/main_screen.dart", - "clazzName": "MainScreenPreviewPreviewPageDummy", - "preview": { - "id": "main_screen", - "path": "widgets", - "description": "", - "parameters": [ - "title", - "infoText", - "counter", - "incrementCounter" - ] - } - }, + "route": "widgets", "builtComponents": { - "/main_screen.dart": { - "path": "./lib/catalog/widgets/main_screen.dart", + "./example/lib/catalog/widgets/main_screen.dart": { + "path": "./example/lib/catalog/widgets/main_screen.dart", "route": "widgets", "package": "package:example/catalog/widgets/main_screen.dart", "clazzName": "MainScreenPreviewPreviewPageDummy", @@ -50,65 +26,54 @@ } }, "children": { - "body_widget": { - "id": "body_widget", - "route": "/body_widget", - "builtComponent": { - "path": "./lib/catalog/widgets/body_widget/body_widget.dart", - "route": "widgets/body_widget", - "package": "package:example/catalog/widgets/body_widget/body_widget.dart", - "clazzName": "BodyWidgetPreviewPreviewPageDummy", - "preview": { - "id": "BodyWidgetPreview", - "path": "widgets/body_widget", - "description": "", - "parameters": [ - "infoText", - "counter" - ] - } - }, - "builtComponents": {}, - "children": {} - }, "screen": { "id": "screen", - "route": "/screen", - "builtComponent": { - "path": "./lib/catalog/widgets/screen/fab_widget.dart", - "route": "widgets/screen", - "package": "package:example/catalog/widgets/screen/fab_widget.dart", - "clazzName": "FabWidgetPreviewPreviewPageDummy", - "preview": { - "id": "fab_widget", - "path": "widgets/screen", - "description": "Basic fab widget", - "parameters": [ - "incrementCounter" - ] - } - }, - "builtComponents": {}, - "children": {} - }, - "counter_widget": { - "id": "counter_widget", - "route": "/counter_widget", - "builtComponent": { - "path": "./lib/catalog/widgets/counter_widget/counter_widget.dart", - "route": "widgets/counter_widget", - "package": "package:example/catalog/widgets/counter_widget/counter_widget.dart", - "clazzName": "CounterWidgetPreviewPreviewPageDummy", - "preview": { - "id": "CounterWidgetPreview", - "path": "widgets/counter_widget", - "description": "Basic counter widget", - "parameters": [ - "counter" - ] + "route": "widgets/screen", + "builtComponents": { + "./example/lib/catalog/widgets/screen/body_widget.dart": { + "path": "./example/lib/catalog/widgets/screen/body_widget.dart", + "route": "widgets/screen", + "package": "package:example/catalog/widgets/screen/body_widget.dart", + "clazzName": "BodyWidgetPreviewPreviewPageDummy", + "preview": { + "id": "body_widget", + "path": "widgets/screen", + "description": "", + "parameters": [ + "infoText", + "counter" + ] + } + }, + "./example/lib/catalog/widgets/screen/fab_widget.dart": { + "path": "./example/lib/catalog/widgets/screen/fab_widget.dart", + "route": "widgets/screen", + "package": "package:example/catalog/widgets/screen/fab_widget.dart", + "clazzName": "FabWidgetPreviewPreviewPageDummy", + "preview": { + "id": "fab_widget", + "path": "widgets/screen", + "description": "Basic fab widget", + "parameters": [ + "incrementCounter" + ] + } + }, + "./example/lib/catalog/widgets/screen/counter_widget.dart": { + "path": "./example/lib/catalog/widgets/screen/counter_widget.dart", + "route": "widgets/screen", + "package": "package:example/catalog/widgets/screen/counter_widget.dart", + "clazzName": "CounterWidgetPreviewPreviewPageDummy", + "preview": { + "id": "counter_widget", + "path": "widgets/screen", + "description": "Basic counter widget", + "parameters": [ + "counter" + ] + } } }, - "builtComponents": {}, "children": {} } } diff --git a/example/lib/catalog/catalog_component.dart b/example/lib/catalog/catalog_component.dart index 5cd8b22..7911280 100644 --- a/example/lib/catalog/catalog_component.dart +++ b/example/lib/catalog/catalog_component.dart @@ -2,62 +2,95 @@ import 'package:flutter/material.dart'; import 'package:catalog/catalog.dart'; + + +import 'package:example/catalog/widgets/screen/body_widget.dart';import 'package:example/catalog/widgets/screen/fab_widget.dart';import 'package:example/catalog/widgets/screen/counter_widget.dart'; + + + import 'package:example/catalog/widgets/main_screen.dart'; -import 'package:example/catalog/widgets/body_widget/body_widget.dart'; -import 'package:example/catalog/widgets/screen/fab_widget.dart'; -import 'package:example/catalog/widgets/counter_widget/counter_widget.dart'; + + + + + + class CatalogComponent extends StatefulWidget { static String routeName = '/catalog'; - static GoRoute route = GoRoute( - path: CatalogComponent.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const CatalogComponent(), - ), - routes: [ - GoRoute( - path: MainScreenPreviewPreviewPageDummy.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const MainScreenPreviewPreviewPageDummy(), - ), - routes: [ - GoRoute( - path: MainScreenPreviewPreviewPageDummy.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const MainScreenPreviewPreviewPageDummy(), - ), + + static GoRoute route = GoRoute( + path: CatalogComponent.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const CatalogComponent(), + ), + routes: [ + GoRoute( + path: 'widgets', + redirect: (context, state) { + if (state.fullPath != state.matchedLocation) return null; + return CatalogComponent.routeName; + }, + routes: [ + + GoRoute( + path: MainScreenPreviewPreviewPageDummy.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const MainScreenPreviewPreviewPageDummy(), ), - GoRoute( - path: BodyWidgetPreviewPreviewPageDummy.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const BodyWidgetPreviewPreviewPageDummy(), - ), - routes: const [], + ) + + + , + GoRoute( + path: 'screen', + redirect: (context, state) { + if (state.fullPath != state.matchedLocation) return null; + return CatalogComponent.routeName; + }, + routes: [ + + GoRoute( + path: BodyWidgetPreviewPreviewPageDummy.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const BodyWidgetPreviewPreviewPageDummy(), ), - GoRoute( - path: FabWidgetPreviewPreviewPageDummy.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const FabWidgetPreviewPreviewPageDummy(), - ), - routes: const [], + ) + + , + GoRoute( + path: FabWidgetPreviewPreviewPageDummy.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const FabWidgetPreviewPreviewPageDummy(), ), - GoRoute( - path: CounterWidgetPreviewPreviewPageDummy.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const CounterWidgetPreviewPreviewPageDummy(), - ), - routes: const [], - ) - ], + ) + + , + GoRoute( + path: CounterWidgetPreviewPreviewPageDummy.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const CounterWidgetPreviewPreviewPageDummy(), + ), + ) + + + , + + ], + ) + + ], + ) + + ], ) - ], - ); +; + const CatalogComponent({super.key}); @override @@ -65,76 +98,34 @@ class CatalogComponent extends StatefulWidget { } class CatalogComponentState extends State { - TreeController? treeController; @override Widget build(BuildContext context) { - return PreviewScaffold( - onBackPressed: Catalog().onBackPressed, - child: FutureBuilder( - initialData: null, - future: Catalog().get(context), - builder: (context, data) { - if (!data.hasData || data.data == null) { - return Container(); - } - final node = data.data as ComponentNode; - if (treeController == null) { - treeController = TreeController( - roots: [node], - childrenProvider: (ComponentNode node) => node.children.values, - ); - if (treeController!.isTreeCollapsed) { - treeController!.expandAll(); - } - } - return AnimatedTreeView( - treeController: treeController!, - nodeBuilder: - (BuildContext context, TreeEntry entry) { - return InkWell( - onTap: () { - // _nodePressed(node); - }, - child: TreeIndentation( - entry: entry, - child: Row( - children: [ - FolderButton( - color: Colors.black, - isOpen: entry.hasChildren ? entry.isExpanded : null, - onPressed: () => _nodePressed(entry), - ), - Text( - entry.node.id, - style: const TextStyle( - color: Colors.black, - fontSize: 16, - letterSpacing: .3, - ), - ), - ], - ), - ), - ); - }, - ); - }), + return FutureBuilder( + initialData: null, + future: Catalog().get(context), + builder: (context, data) { + if (!data.hasData || data.data == null) { + return Container(); + } + final node = data.data as ComponentNode; + return PreviewScaffold( + basePath: CatalogComponent.routeName, + onBackPressed: Catalog().onBackPressed, + child: ListView( + children: [ + buildTreeWidget( + context, + CatalogComponent.routeName, + node, + 0, + ) + ], + ), + ); + }, ); } - - void _nodePressed(TreeEntry entry) { - if (entry.node.children.isEmpty) { - if (entry.node.builtComponent?.preview?.path != null) { - context.go( - '${CatalogComponent.routeName}/${entry.node.builtComponent!.preview!.path}'); - } - } else { - if (!entry.isExpanded) { - treeController?.toggleExpansion(entry.node); - } else { - treeController?.collapse(entry.node); - } - } - } } + + \ No newline at end of file diff --git a/example/lib/catalog/widgets/main_screen.dart b/example/lib/catalog/widgets/main_screen.dart index 2435fa2..8478f34 100644 --- a/example/lib/catalog/widgets/main_screen.dart +++ b/example/lib/catalog/widgets/main_screen.dart @@ -4,19 +4,19 @@ import 'package:flutter/material.dart'; import 'package:example/widgets/catalog/preview/main_screen.preview.dart'; class MainScreenPreviewPreviewPageDummy extends StatefulWidget { - static String routeName = 'main_screen'; + static String routeName = 'main_screen'; + const MainScreenPreviewPreviewPageDummy({super.key}); @override - MainScreenPreviewPreviewPageDummyState createState() => - MainScreenPreviewPreviewPageDummyState(); + MainScreenPreviewPreviewPageDummyState createState() => MainScreenPreviewPreviewPageDummyState(); } -class MainScreenPreviewPreviewPageDummyState - extends State { +class MainScreenPreviewPreviewPageDummyState extends State { @override Widget build(BuildContext context) { return const MainScreenPreview(); } } + \ No newline at end of file diff --git a/example/lib/catalog/widgets/body_widget/body_widget.dart b/example/lib/catalog/widgets/screen/body_widget.dart similarity index 67% rename from example/lib/catalog/widgets/body_widget/body_widget.dart rename to example/lib/catalog/widgets/screen/body_widget.dart index 57f4c75..54eb25b 100644 --- a/example/lib/catalog/widgets/body_widget/body_widget.dart +++ b/example/lib/catalog/widgets/screen/body_widget.dart @@ -4,19 +4,19 @@ import 'package:flutter/material.dart'; import 'package:example/widgets/screen/catalog/preview/body_widget.preview.dart'; class BodyWidgetPreviewPreviewPageDummy extends StatefulWidget { - static String routeName = 'body_widget'; + static String routeName = 'body_widget'; + const BodyWidgetPreviewPreviewPageDummy({super.key}); @override - BodyWidgetPreviewPreviewPageDummyState createState() => - BodyWidgetPreviewPreviewPageDummyState(); + BodyWidgetPreviewPreviewPageDummyState createState() => BodyWidgetPreviewPreviewPageDummyState(); } -class BodyWidgetPreviewPreviewPageDummyState - extends State { +class BodyWidgetPreviewPreviewPageDummyState extends State { @override Widget build(BuildContext context) { return const BodyWidgetPreview(); } } + \ No newline at end of file diff --git a/example/lib/catalog/widgets/counter_widget/counter_widget.dart b/example/lib/catalog/widgets/screen/counter_widget.dart similarity index 67% rename from example/lib/catalog/widgets/counter_widget/counter_widget.dart rename to example/lib/catalog/widgets/screen/counter_widget.dart index dc4cda2..0d5e240 100644 --- a/example/lib/catalog/widgets/counter_widget/counter_widget.dart +++ b/example/lib/catalog/widgets/screen/counter_widget.dart @@ -4,19 +4,19 @@ import 'package:flutter/material.dart'; import 'package:example/widgets/screen/catalog/preview/counter_widget.preview.dart'; class CounterWidgetPreviewPreviewPageDummy extends StatefulWidget { - static String routeName = 'counter_widget'; + static String routeName = 'counter_widget'; + const CounterWidgetPreviewPreviewPageDummy({super.key}); @override - CounterWidgetPreviewPreviewPageDummyState createState() => - CounterWidgetPreviewPreviewPageDummyState(); + CounterWidgetPreviewPreviewPageDummyState createState() => CounterWidgetPreviewPreviewPageDummyState(); } -class CounterWidgetPreviewPreviewPageDummyState - extends State { +class CounterWidgetPreviewPreviewPageDummyState extends State { @override Widget build(BuildContext context) { return const CounterWidgetPreview(); } } + \ No newline at end of file diff --git a/example/lib/catalog/widgets/screen/fab_widget.dart b/example/lib/catalog/widgets/screen/fab_widget.dart index ec26c1d..23f91ac 100644 --- a/example/lib/catalog/widgets/screen/fab_widget.dart +++ b/example/lib/catalog/widgets/screen/fab_widget.dart @@ -4,19 +4,19 @@ import 'package:flutter/material.dart'; import 'package:example/widgets/screen/catalog/preview/fab_widget.preview.dart'; class FabWidgetPreviewPreviewPageDummy extends StatefulWidget { - static String routeName = 'screen'; + static String routeName = 'fab_widget'; + const FabWidgetPreviewPreviewPageDummy({super.key}); @override - FabWidgetPreviewPreviewPageDummyState createState() => - FabWidgetPreviewPreviewPageDummyState(); + FabWidgetPreviewPreviewPageDummyState createState() => FabWidgetPreviewPreviewPageDummyState(); } -class FabWidgetPreviewPreviewPageDummyState - extends State { +class FabWidgetPreviewPreviewPageDummyState extends State { @override Widget build(BuildContext context) { return const FabWidgetPreview(); } } + \ No newline at end of file diff --git a/example/lib/widgets/catalog/preview/main_screen.preview.dart b/example/lib/widgets/catalog/preview/main_screen.preview.dart index 80e7116..f10f0ac 100644 --- a/example/lib/widgets/catalog/preview/main_screen.preview.dart +++ b/example/lib/widgets/catalog/preview/main_screen.preview.dart @@ -11,11 +11,17 @@ import '../dummy/main_screen.dummy.dart'; 'infoText', 'counter', 'incrementCounter', - ], -) + ],) class MainScreenPreview extends ParentPreviewWidget { + + @override + String get title => 'main_screen'; + + @override + String get basePath => '/catalog'; + const MainScreenPreview({super.key}); - + @override Widget preview(BuildContext context) { Catalog().widgetBasicPreviewMap.clear(); @@ -100,21 +106,20 @@ class MainScreenPreview extends ParentPreviewWidget { ), ), for (int i = 0; i < MainScreenDummy().dummies.length; i++) - PreviewBoundary( - widgetKey: GlobalKey(), - dummyBuilder: () => MainScreenDummy().dummies[i], - builder: (BuildContext context, Dummy dummy) { - return MainScreen( - title: dummy.parameters['title'], - infoText: dummy.parameters['infoText'], - counter: dummy.parameters['counter'], - incrementCounter: dummy.parameters['incrementCounter'], - ); - }, - ), + PreviewBoundary( + widgetKey: GlobalKey(), + dummyBuilder: () => MainScreenDummy().dummies[i], + builder: (BuildContext context, Dummy dummy) { + return MainScreen(title: dummy.parameters['title'],infoText: dummy.parameters['infoText'],counter: dummy.parameters['counter'],incrementCounter: dummy.parameters['incrementCounter'],); + }, + ), + ], ) ], ); } + + } + \ No newline at end of file diff --git a/example/lib/widgets/screen/body_widget.dart b/example/lib/widgets/screen/body_widget.dart index 4236a59..ce78232 100644 --- a/example/lib/widgets/screen/body_widget.dart +++ b/example/lib/widgets/screen/body_widget.dart @@ -4,8 +4,6 @@ import 'package:flutter/material.dart'; import 'counter_widget.dart'; @Preview( - id: 'BodyWidgetPreview', - path: 'widgets/body_widget', parameters: [ 'infoText', 'counter', diff --git a/example/lib/widgets/screen/catalog/preview/body_widget.preview.dart b/example/lib/widgets/screen/catalog/preview/body_widget.preview.dart index 38de8a3..76d3689 100644 --- a/example/lib/widgets/screen/catalog/preview/body_widget.preview.dart +++ b/example/lib/widgets/screen/catalog/preview/body_widget.preview.dart @@ -6,16 +6,20 @@ import 'package:example/widgets/screen/body_widget.dart'; import '../dummy/body_widget.dummy.dart'; @Preview( - id: 'BodyWidgetPreview', - path: 'widgets/body_widget', parameters: [ 'infoText', 'counter', - ], -) + ],) class BodyWidgetPreview extends ParentPreviewWidget { + + @override + String get title => 'body_widget'; + + @override + String get basePath => '/catalog'; + const BodyWidgetPreview({super.key}); - + @override Widget preview(BuildContext context) { Catalog().widgetBasicPreviewMap.clear(); @@ -100,19 +104,20 @@ class BodyWidgetPreview extends ParentPreviewWidget { ), ), for (int i = 0; i < BodyWidgetDummy().dummies.length; i++) - PreviewBoundary( - widgetKey: GlobalKey(), - dummyBuilder: () => BodyWidgetDummy().dummies[i], - builder: (BuildContext context, Dummy dummy) { - return BodyWidget( - infoText: dummy.parameters['infoText'], - counter: dummy.parameters['counter'], - ); - }, - ), + PreviewBoundary( + widgetKey: GlobalKey(), + dummyBuilder: () => BodyWidgetDummy().dummies[i], + builder: (BuildContext context, Dummy dummy) { + return BodyWidget(infoText: dummy.parameters['infoText'],counter: dummy.parameters['counter'],); + }, + ), + ], ) ], ); } + + } + \ No newline at end of file diff --git a/example/lib/widgets/screen/catalog/preview/counter_widget.preview.dart b/example/lib/widgets/screen/catalog/preview/counter_widget.preview.dart index 8faac14..ef8888b 100644 --- a/example/lib/widgets/screen/catalog/preview/counter_widget.preview.dart +++ b/example/lib/widgets/screen/catalog/preview/counter_widget.preview.dart @@ -6,16 +6,20 @@ import 'package:example/widgets/screen/counter_widget.dart'; import '../dummy/counter_widget.dummy.dart'; @Preview( - id: 'CounterWidgetPreview', - path: 'widgets/counter_widget', description: 'Basic counter widget', parameters: [ 'counter', - ], -) + ],) class CounterWidgetPreview extends ParentPreviewWidget { + + @override + String get title => 'counter_widget'; + + @override + String get basePath => '/catalog'; + const CounterWidgetPreview({super.key}); - + @override Widget preview(BuildContext context) { Catalog().widgetBasicPreviewMap.clear(); @@ -100,18 +104,20 @@ class CounterWidgetPreview extends ParentPreviewWidget { ), ), for (int i = 0; i < CounterWidgetDummy().dummies.length; i++) - PreviewBoundary( - widgetKey: GlobalKey(), - dummyBuilder: () => CounterWidgetDummy().dummies[i], - builder: (BuildContext context, Dummy dummy) { - return CounterWidget( - counter: dummy.parameters['counter'], - ); - }, - ), + PreviewBoundary( + widgetKey: GlobalKey(), + dummyBuilder: () => CounterWidgetDummy().dummies[i], + builder: (BuildContext context, Dummy dummy) { + return CounterWidget(counter: dummy.parameters['counter'],); + }, + ), + ], ) ], ); } + + } + \ No newline at end of file diff --git a/example/lib/widgets/screen/catalog/preview/fab_widget.preview.dart b/example/lib/widgets/screen/catalog/preview/fab_widget.preview.dart index 0e863d0..4b97fd2 100644 --- a/example/lib/widgets/screen/catalog/preview/fab_widget.preview.dart +++ b/example/lib/widgets/screen/catalog/preview/fab_widget.preview.dart @@ -7,11 +7,17 @@ import '../dummy/fab_widget.dummy.dart'; @Preview( description: 'Basic fab widget', - parameters: ['incrementCounter'], -) + parameters: ['incrementCounter'],) class FabWidgetPreview extends ParentPreviewWidget { + + @override + String get title => 'fab_widget'; + + @override + String get basePath => '/catalog'; + const FabWidgetPreview({super.key}); - + @override Widget preview(BuildContext context) { Catalog().widgetBasicPreviewMap.clear(); @@ -96,18 +102,20 @@ class FabWidgetPreview extends ParentPreviewWidget { ), ), for (int i = 0; i < FabWidgetDummy().dummies.length; i++) - PreviewBoundary( - widgetKey: GlobalKey(), - dummyBuilder: () => FabWidgetDummy().dummies[i], - builder: (BuildContext context, Dummy dummy) { - return FabWidget( - incrementCounter: dummy.parameters['incrementCounter'], - ); - }, - ), + PreviewBoundary( + widgetKey: GlobalKey(), + dummyBuilder: () => FabWidgetDummy().dummies[i], + builder: (BuildContext context, Dummy dummy) { + return FabWidget(incrementCounter: dummy.parameters['incrementCounter'],); + }, + ), + ], ) ], ); } + + } + \ No newline at end of file diff --git a/example/lib/widgets/screen/counter_widget.dart b/example/lib/widgets/screen/counter_widget.dart index 635e869..16ca3b3 100644 --- a/example/lib/widgets/screen/counter_widget.dart +++ b/example/lib/widgets/screen/counter_widget.dart @@ -2,8 +2,6 @@ import 'package:catalog/catalog.dart'; import 'package:flutter/material.dart'; @Preview( - id: 'CounterWidgetPreview', - path: 'widgets/counter_widget', description: 'Basic counter widget', parameters: [ 'counter', diff --git a/lib/catalog.dart b/lib/catalog.dart index 60f311b..f493228 100644 --- a/lib/catalog.dart +++ b/lib/catalog.dart @@ -18,6 +18,7 @@ export 'package:catalog/src/builders/preview/parent_preview_widget.dart'; export 'package:catalog/src/builders/preview/preview_boundary.dart'; export 'package:catalog/src/builders/dummy/preview_dummy.dart'; export 'package:catalog/src/builders/catalog/preview_scaffold.dart'; +export 'package:catalog/src/builders/catalog/tree_elements_builder.dart'; export 'package:catalog/src/builders/screenshots/background.dart'; export 'package:catalog/src/builders/screenshots/op/screenshot_process.dart'; export 'package:catalog/src/builders/screenshots/screenshot.dart'; diff --git a/lib/src/bin/catalog_builder/catalog_builder.dart b/lib/src/bin/catalog_builder/catalog_builder.dart index bb7ce20..7854507 100644 --- a/lib/src/bin/catalog_builder/catalog_builder.dart +++ b/lib/src/bin/catalog_builder/catalog_builder.dart @@ -29,8 +29,7 @@ Future createPage( try { var directory = Directory(outputPath); await directory.create(recursive: true); - var id = - preview.path.contains('/') ? preview.path.split('/').last : preview.id; + var id = preview.id; File file = File(outputPath + outputFile.replaceAll('.$prefix.', '.')); final clazzName = name.replaceAll('()', ''); @@ -169,6 +168,7 @@ class ${clazzName}State extends State<$clazzName> { } } +/* Future buildChildrenPages( String basePath, dynamic config, @@ -255,21 +255,77 @@ Future buildChildrenPages( return null; } } +*/ +ComponentNode buildTreeFromMap( + String pageRoute, + Map> componentsMap, +) { + // Nodo raíz del árbol + ComponentNode root = ComponentNode(id: pageRoute, route: '/'); + + // Función auxiliar para crear o encontrar un nodo dentro del árbol + ComponentNode findOrCreateNode( + ComponentNode current, + List pathParts, + String fullPath, + ) { + if (pathParts.isEmpty) { + return current; + } + + // Obtener el primer segmento del path y crear el nodo hijo si no existe + String part = pathParts.removeAt(0); + if (!current.children.containsKey(part)) { + current.children[part] = ComponentNode( + id: part, + route: fullPath.substring(0, fullPath.indexOf(part) + part.length), + ); + } + + // Recursivamente buscar o crear el siguiente nodo hijo + return findOrCreateNode(current.children[part]!, pathParts, fullPath); + } + + // Recorrer cada entrada del mapa y asignarla a su nodo correspondiente + componentsMap.forEach((path, builtComponents) { + // Dividir el path en sus partes, excluyendo la raíz '/' + List pathParts = + path.split('/').where((part) => part.isNotEmpty).toList(); + // Encontrar o crear el nodo adecuado para este path + ComponentNode currentNode = findOrCreateNode(root, pathParts, path); + + // Agregar los componentes del directorio actual al nodo correspondiente + for (var component in builtComponents) { + currentNode.builtComponents[component.path] = component; + } + }); + + return root; +} + +/* ComponentNode getNodesFrom( String pageRoute, - Map components, + Map> components, ) { var firstNode = ComponentNode(id: pageRoute, route: '/'); - for (var entity in components.values.toList()) { - print('======================================================='); - print('route: ${entity.route}'); - var parts = entity.route.split('/'); - if (parts.first == '.') { - parts.removeAt(0); + final pathLevels = components.entries.toList(); + + for (var entity in pathLevels) { + final pathLevel = entity.key; + final pagesInThatLevel = entity.value.toList(); + + for (var page in pagesInThatLevel) { + print('======================================================='); + print('route: ${page.route}'); + var parts = page.route.split('/'); + if (parts.first == '.') { + parts.removeAt(0); + } + addNode(firstNode, parts, 0, page); } - addNode(firstNode, parts, 0, entity); } return firstNode; @@ -311,3 +367,5 @@ void addNode( addNode(no, parts, index + 1, component); } } + + */ diff --git a/lib/src/bin/preview_builder/preview_builder.dart b/lib/src/bin/preview_builder/preview_builder.dart index 716fc76..fb2dca8 100644 --- a/lib/src/bin/preview_builder/preview_builder.dart +++ b/lib/src/bin/preview_builder/preview_builder.dart @@ -14,6 +14,7 @@ Future findClassName(String path) async { } Future generatePreview( + dynamic config, String srcPath, String classImport, String previewAnnotation, @@ -38,6 +39,13 @@ import '../dummy/$name.dummy.dart'; $previewAnnotation class ${clazz}Preview extends ParentPreviewWidget { + + @override + String get title => '$name'; + + @override + String get basePath => '/${config['pageRoute']}'; + const ${clazz}Preview({super.key}); @override diff --git a/lib/src/bin/tasks/tasks/catalog_task.dart b/lib/src/bin/tasks/tasks/catalog_task.dart index e1ec6ff..b5e8811 100644 --- a/lib/src/bin/tasks/tasks/catalog_task.dart +++ b/lib/src/bin/tasks/tasks/catalog_task.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:catalog/src/base/serial.dart'; @@ -38,7 +39,7 @@ class CatalogTask extends BaseTask { } } - var map = {}; + var map = >{}; for (FileSystemEntity fileSystemEntity in files) { final File file = File(fileSystemEntity.path); @@ -50,7 +51,6 @@ class CatalogTask extends BaseTask { print('No class name found ${file.path}'); continue; } - //print('- Building preview of $className in $package'); var preview = await previewOnFile( base, @@ -63,8 +63,6 @@ class CatalogTask extends BaseTask { continue; } - // print('Preview: ${jsonEncode(preview.toJson())}'); - var outputFolder = './$base${config['base']}/${config['output']}/${preview.path}/'; @@ -81,37 +79,21 @@ class CatalogTask extends BaseTask { className, ); - if (build?.preview == null) { + if (build == null) { print('No build for $className'); continue; } - // print('Built: ${jsonEncode(build!.toJson())}'); - - print('${build!.preview!.path} with classname $className'); - map[build.preview!.path] = build; - } - ComponentNode? node = getNodesFrom(pageRoute, map); + print('Built: ${jsonEncode(build.toJson())}'); - print('node: ${node.childrenList.map((e) => e.id).join(', ')}'); - - node = await buildChildrenPages( - base, - config, - appId, - node, - '', - pageRoute, - 0, - ); - - if (node == null) { - return; + print('${build.route} with classname $className'); + if (map[build.route] == null) { + map[build.route] = []; + } + (map[build.route] as List).add(build); } - print('node 2: ${node.childrenList.map((e) => e.id).join(', ')}'); - - // print(node.toJson().toPrettyString()); + ComponentNode node = buildTreeFromMap(pageRoute, map); final File assetsConfig = File('./$base${config['runtimeConfigHolder']}'); assetsConfig.writeAsStringSync(node.toJson().toPrettyString()); @@ -130,7 +112,9 @@ ${node.imports} class $pageName extends StatefulWidget { static String routeName = '/$pageRoute'; + static GoRoute route = ${node.routerBuilder}; + const $pageName({super.key}); @override @@ -139,79 +123,33 @@ class $pageName extends StatefulWidget { class ${pageName}State extends State<$pageName> { - TreeController? treeController; - - @override Widget build(BuildContext context) { - return PreviewScaffold( - onBackPressed: Catalog().onBackPressed, - child: FutureBuilder( - initialData: null, - future: Catalog().get(context), - builder: (context, data) { - if (!data.hasData || data.data == null) { - return Container(); - } - final node = data.data as ComponentNode; - if (treeController == null) { - treeController = TreeController( - roots: [node], - childrenProvider: (ComponentNode node) => node.children.values, - ); - if (treeController!.isTreeCollapsed) { - treeController!.expandAll(); - } - } - return AnimatedTreeView( - treeController: treeController!, - nodeBuilder: - (BuildContext context, TreeEntry entry) { - return InkWell( - onTap: () { - // _nodePressed(node); - }, - child: TreeIndentation( - entry: entry, - child: Row( - children: [ - FolderButton( - color: Colors.black, - isOpen: entry.hasChildren ? entry.isExpanded : null, - onPressed: () => _nodePressed(entry), - ), - Text( - entry.node.id, - style: const TextStyle( - color: Colors.black, - fontSize: 16, - letterSpacing: .3, - ), - ), - ], - ), - ), - ); - }, - ); - }), + return FutureBuilder( + initialData: null, + future: Catalog().get(context), + builder: (context, data) { + if (!data.hasData || data.data == null) { + return Container(); + } + final node = data.data as ComponentNode; + return PreviewScaffold( + basePath: CatalogComponent.routeName, + onBackPressed: Catalog().onBackPressed, + child: ListView( + children: [ + buildTreeWidget( + context, + CatalogComponent.routeName, + node, + 0, + ) + ], + ), + ); + }, ); } - - void _nodePressed(TreeEntry entry) { - if (entry.node.children.isEmpty) { - if (entry.node.builtComponent?.preview?.path != null) { - context.go( - '\${$pageName.routeName}/\${entry.node.builtComponent!.preview!.path}'); - } - } else { - if (!entry.isExpanded) { - treeController?.toggleExpansion(entry.node); - } else { - treeController?.collapse(entry.node); - } - } - } } ''' diff --git a/lib/src/bin/tasks/tasks/format_task.dart b/lib/src/bin/tasks/tasks/format_task.dart index 0e336c8..a9d0723 100644 --- a/lib/src/bin/tasks/tasks/format_task.dart +++ b/lib/src/bin/tasks/tasks/format_task.dart @@ -20,5 +20,5 @@ class FormatTask extends BaseTask { ); stdout.write(result.stdout); stderr.write(result.stderr); - } + } } diff --git a/lib/src/bin/tasks/tasks/preview_task.dart b/lib/src/bin/tasks/tasks/preview_task.dart index cbc5a66..76aad6a 100644 --- a/lib/src/bin/tasks/tasks/preview_task.dart +++ b/lib/src/bin/tasks/tasks/preview_task.dart @@ -54,6 +54,7 @@ class PreviewTask extends BaseTask { if (preview == null) continue; await generatePreview( + config, file.path, classImport, previewAnnotation, diff --git a/lib/src/builders/catalog/built_component.dart b/lib/src/builders/catalog/built_component.dart index 64c2a77..8cf9251 100644 --- a/lib/src/builders/catalog/built_component.dart +++ b/lib/src/builders/catalog/built_component.dart @@ -8,6 +8,12 @@ class BuiltComponent extends Serial { String clazzName = ''; Preview? preview; + String get name { + if (!path.contains('/')) return path; + var parts = path.split('/'); + return parts.last; + } + BuiltComponent({ this.path = '', this.route = '', diff --git a/lib/src/builders/catalog/component_node.dart b/lib/src/builders/catalog/component_node.dart index 2b160e2..fc82785 100644 --- a/lib/src/builders/catalog/component_node.dart +++ b/lib/src/builders/catalog/component_node.dart @@ -1,13 +1,18 @@ -import 'dart:convert'; - import 'package:catalog/src/base/serial.dart'; import 'package:catalog/src/builders/catalog/built_component.dart'; class ComponentNode extends Serial { String id = ''; String route = ''; - BuiltComponent? builtComponent; + + String get routePath { + if (!route.contains('/')) return route; + var parts = route.split('/'); + return parts.last; + } + Map builtComponents = {}; + Map children = {}; List get builtComponentList => @@ -18,16 +23,12 @@ class ComponentNode extends Serial { ComponentNode({ this.id = '', this.route = '', - this.builtComponent, }); @override ComponentNode fromJson(Map json) { id = json['id'] ?? ''; route = json['route'] ?? ''; - if (json['builtComponent'] != null) { - builtComponent = BuiltComponent().fromJson(json['builtComponent'] ?? {}); - } builtComponents = Serial.fromComplexMap(json['builtComponents'] ?? {}); children = Serial.fromComplexMap(json['children'] ?? {}); @@ -44,25 +45,35 @@ class ComponentNode extends Serial { Map toJson() => { 'id': id, 'route': route, - 'builtComponent': builtComponent?.toJson(), 'builtComponents': builtComponents.isEmpty ? {} : Serial.toMap(builtComponents), 'children': children.isEmpty ? {} : Serial.toMap(children), }; String get routerBuilder { - for (var o in childrenList) { - print('routes builder: ${jsonEncode(o.toJson())}'); + if (route == '/') { + return ''' + GoRoute( + path: CatalogComponent.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const CatalogComponent(), + ), + routes: [ + ${childrenList.map((e) => e.routerBuilder).toList().join(',')} + ], + ) +'''; } return ''' - GoRoute( - path: ${builtComponent?.clazzName}.routeName, - pageBuilder: (context, state) => NoTransitionPage( - key: state.pageKey, - child: const ${builtComponent?.clazzName}(), - ), - routes: [ - ${builtComponentList.map((e) { + GoRoute( + path: '$routePath', + redirect: (context, state) { + if (state.fullPath != state.matchedLocation) return null; + return CatalogComponent.routeName; + }, + routes: [ + ${builtComponentList.map((e) { return ''' GoRoute( @@ -71,41 +82,41 @@ class ComponentNode extends Serial { key: state.pageKey, child: const ${e.clazzName}(), ), - ), + ) + + '''; + }).toList().join(',')} + ${builtComponentList.isNotEmpty ? ',' : ''} + ${childrenList.map((e) => e.routerBuilder).toList().join(',')} + ], + ) + '''; + } + + String get routerBuilderB { + return ''' + ${builtComponentList.map((e) { + return ''' + + GoRoute( + path: ${e.clazzName}.routeName, + pageBuilder: (context, state) => NoTransitionPage( + key: state.pageKey, + child: const ${e.clazzName}(), + ), + ) '''; }).toList().join(',')} ${childrenList.map((e) => e.routerBuilder).toList().join(',')} - - ], - ) '''; } String get imports { - String value = ''; - if (builtComponent == null) { - return value; - } - if (route == "/") { - value += '''${childrenList.map((e) => e.imports).toList().join('')}\n'''; - } else { - if (childrenList.isEmpty) { - print('adding import (single): ${builtComponent!.package}'); - value += '''import '${builtComponent!.package}';\n'''; - } else { - value += '''import '${builtComponent!.package}'; -${childrenList.map((e) { - print('adding import: ${e.imports}'); - return e.imports; - }).toList().join('')}\n - -${builtComponentList.map((e) { - print('adding import: ${e.package}'); - return 'import \'${e.package}\';'; - }).toList().join('')}\n'''; - } - } + String value = ''' +${childrenList.map((e) => e.imports).toList().join('')}\n +${builtComponentList.map((e) => 'import \'${e.package}\';').toList().join('')}\n + '''; return value; } } diff --git a/lib/src/builders/catalog/drawer_preview.dart b/lib/src/builders/catalog/drawer_preview.dart index 81f4048..d2c4798 100644 --- a/lib/src/builders/catalog/drawer_preview.dart +++ b/lib/src/builders/catalog/drawer_preview.dart @@ -3,10 +3,12 @@ import 'package:flutter/material.dart'; class DrawerPreview extends StatefulWidget { final void Function()? onBackPressed; + final String basePath; const DrawerPreview({ super.key, this.onBackPressed, + required this.basePath, }); @override @@ -15,7 +17,6 @@ class DrawerPreview extends StatefulWidget { class DrawerPreviewState extends State { ComponentNode? node; - TreeController? treeController; @override void initState() { @@ -23,22 +24,14 @@ class DrawerPreviewState extends State { Catalog().get(context).then((value) { if (value == null) return; node = value; - if (treeController == null) { - treeController = TreeController( - roots: [value], - childrenProvider: (ComponentNode node) => node.children.values, - ); - if (treeController!.isTreeCollapsed) { - treeController!.expandAll(); - } - } setState(() {}); }); } @override Widget build(BuildContext context) { - if (node == null || treeController == null) { + final n = node; + if (n == null) { return Container(); } var height = MediaQuery.of(context).size.height; @@ -75,53 +68,19 @@ class DrawerPreviewState extends State { ), SizedBox( height: height - 200, - child: AnimatedTreeView( - treeController: treeController!, - nodeBuilder: - (BuildContext context, TreeEntry entry) { - return InkWell( - onTap: () { - // _nodePressed(node); - }, - child: TreeIndentation( - entry: entry, - child: Row( - children: [ - FolderButton( - isOpen: entry.hasChildren ? entry.isExpanded : null, - onPressed: () => _nodePressed(node!, entry), - ), - Text( - entry.node.id, - style: const TextStyle( - fontSize: 16, - letterSpacing: .3, - ), - ), - ], - ), - ), - ); - }, + child: ListView( + children: [ + buildTreeWidget( + context, + widget.basePath, + n, + 0, + ) + ], ), ), ], ), ); } - - void _nodePressed(ComponentNode baseNode, TreeEntry entry) { - if (entry.node.children.isEmpty) { - if (entry.node.builtComponent?.preview?.path != null) { - context - .go('/${baseNode.id}/${entry.node.builtComponent!.preview!.path}'); - } - } else { - if (!entry.isExpanded) { - treeController?.toggleExpansion(entry.node); - } else { - treeController?.collapse(entry.node); - } - } - } } diff --git a/lib/src/builders/catalog/preview_scaffold.dart b/lib/src/builders/catalog/preview_scaffold.dart index bb45bff..3950baa 100644 --- a/lib/src/builders/catalog/preview_scaffold.dart +++ b/lib/src/builders/catalog/preview_scaffold.dart @@ -9,6 +9,7 @@ class PreviewScaffold extends StatelessWidget { final Widget child; final String? title; final void Function()? onBackPressed; + final String basePath; const PreviewScaffold({ super.key, @@ -16,14 +17,19 @@ class PreviewScaffold extends StatelessWidget { this.title, this.drawer, this.onBackPressed, + required this.basePath, }); @override Widget build(BuildContext context) { return Scaffold( - drawer: Drawer( - child: DrawerPreview( - onBackPressed: onBackPressed ?? Catalog().onBackPressed, + drawer: SizedBox( + width: 600.0, + child: Drawer( + child: DrawerPreview( + basePath: basePath, + onBackPressed: onBackPressed ?? Catalog().onBackPressed, + ), ), ), appBar: AppBar( diff --git a/lib/src/builders/catalog/tree_element.dart b/lib/src/builders/catalog/tree_element.dart deleted file mode 100644 index 2e89ded..0000000 --- a/lib/src/builders/catalog/tree_element.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:catalog/src/builders/catalog/built_component.dart'; - -class TreeElement { - BuiltComponent? component; - List children = []; - - TreeElement(); -} diff --git a/lib/src/builders/catalog/tree_elements_builder.dart b/lib/src/builders/catalog/tree_elements_builder.dart new file mode 100644 index 0000000..1b90227 --- /dev/null +++ b/lib/src/builders/catalog/tree_elements_builder.dart @@ -0,0 +1,59 @@ +import 'package:catalog/src/builders/catalog/component_node.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +Widget buildTreeWidget( + BuildContext context, + String basePath, + ComponentNode node, + int level, +) { + var padding = 32.0; + return Stack( + children: [ + Padding( + padding: EdgeInsets.only(left: level == 0 ? 0 : padding), + child: Theme( + data: Theme.of(context).copyWith( + dividerColor: Colors.transparent, + ), + child: ExpansionTile( + key: PageStorageKey(node.route), + initiallyExpanded: true, + leading: const Icon(Icons.folder), + iconColor: Colors.teal, + collapsedIconColor: Colors.grey, + title: Text(node.id.isNotEmpty ? node.id : 'Root'), + children: [ + ...node.builtComponentList.map( + (builtComponent) => Padding( + padding: EdgeInsets.only(left: padding), + child: ListTile( + title: Text(builtComponent.name), + leading: const Icon( + Icons.insert_drive_file, + ), + onTap: () { + final id = builtComponent.preview?.id; + if (id != null) { + context.go('$basePath/${builtComponent.route}/$id'); + } + }, + ), + ), + ), + ...node.childrenList.map( + (childNode) => buildTreeWidget( + context, + basePath, + childNode, + level + 1, + ), + ), + ], + ), + ), + ), + ], + ); +} diff --git a/lib/src/builders/preview/parent_preview_widget.dart b/lib/src/builders/preview/parent_preview_widget.dart index 55aca93..de9b6f2 100644 --- a/lib/src/builders/preview/parent_preview_widget.dart +++ b/lib/src/builders/preview/parent_preview_widget.dart @@ -6,6 +6,10 @@ abstract class ParentPreviewWidget extends StatelessWidget { bool get center => true; + String get title => 'preview_page'; + + String get basePath => '/catalog'; + const ParentPreviewWidget({super.key}); Widget preview(BuildContext context); @@ -13,7 +17,8 @@ abstract class ParentPreviewWidget extends StatelessWidget { @override Widget build(BuildContext context) { return PreviewScaffold( - title: runtimeType.toString(), + basePath: basePath, + title: title, child: Center( child: preview(context), ),