diff --git a/lib/controllers/interpret.dart b/lib/controllers/interpret.dart index 311270af..87799c87 100644 --- a/lib/controllers/interpret.dart +++ b/lib/controllers/interpret.dart @@ -58,19 +58,26 @@ class Interpret { /// This is a workaround for adding missing information to either the [PBContext] or any of the /// [PBIntermediateNode]s. aitServiceBuilder.addTransformation( - (PBContext context, PBIntermediateNode node, PBIntermediateTree tree) { - elementStorage.treeUUIDs[tree.UUID] = tree; - elementStorage.elementToTree[node.UUID] = tree.UUID; - return Future.value(node); - }, index: 0, id: 'Indexing ${tree.name}').addTransformation( - (PBContext context, PBIntermediateTree tree) async { - // - var baseGroupList = tree.whereType(); - - baseGroupList.forEach((group) => tree.remove(group, keepChildren: true)); - - return Future.value(tree); - }, index: 1, id: 'Removing the $BaseGroup from ${tree.name}'); + (PBContext context, PBIntermediateNode node, PBIntermediateTree tree) { + elementStorage.treeUUIDs[tree.UUID] = tree; + elementStorage.elementToTree[node.UUID] = tree.UUID; + return Future.value(node); + }, + index: 0, + id: 'Indexing ${tree.name}', + ).addTransformation( + (PBContext context, PBIntermediateTree tree) async { + // + var baseGroupList = tree.whereType(); + + baseGroupList + .forEach((group) => tree.remove(group, keepChildren: true)); + + return Future.value(tree); + }, + index: 1, + id: 'Removing the $BaseGroup from ${tree.name}', + ); // TODO: We should dynamically add the [PBPrototypeLinkerService] to `aitHandlers` // somewhere else so that it does not check the configuration every time diff --git a/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/dashbook_generator.dart b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/dashbook_generator.dart new file mode 100644 index 00000000..69cca399 --- /dev/null +++ b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/dashbook_generator.dart @@ -0,0 +1,52 @@ +import 'package:parabeac_core/controllers/main_info.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/import_helper.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/component_isolation_generator.dart'; +import 'package:parabeac_core/generation/generators/import_generator.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_project_data.dart'; +import 'package:parabeac_core/interpret_and_optimize/services/component_isolation/dashbook_service.dart'; + +class DashbookGenerator implements ComponentIsolationGenerator { + @override + String fileName = 'main_dashbook.dart'; + + DashbookGenerator(this.projectData) { + projectData.addDependencies('dashbook', '^0.1.6'); + } + + @override + PBGenerationProjectData projectData; + + @override + String generateCode(ImportHelper helper) { + var book = DashbookService.book; + var treeIds = DashbookService.treeIds; + var generatedCode = book.generate(); + + var imports = treeIds + .map( + (id) => helper + .getFormattedImports( + id, + importMapper: (import) => FlutterImport( + import, + MainInfo().projectName, + ), + ) + .join('\n'), + ) + .join(''); + return ''' + import 'package:flutter/material.dart'; + import 'package:dashbook/dashbook.dart'; + $imports + + void main() { + final dashbook = Dashbook(); + + $generatedCode + + runApp(dashbook); + } + '''; + } +} diff --git a/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_book.dart b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_book.dart new file mode 100644 index 00000000..9d16cc83 --- /dev/null +++ b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_book.dart @@ -0,0 +1,27 @@ +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_story.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/isolation_node.dart'; + +/// Class that represents a group of [DashBookStories]. +/// +/// This class does not actually exist in Dashbook. However, +/// it makes it easier for us to group stories and generate them +/// in a single step. +class DashBookBook extends IsolationNode { + DashBookBook({ + String name = 'Parabeac-Generated', + }) : super(name: name); + + @override + String generate() { + var stories = getType(); + + var storiesGen = ''; + + if (stories != null && stories.isNotEmpty) { + storiesGen = stories.map((s) => s.generate()).join('\n'); + } + return ''' + ${storiesGen.isNotEmpty ? ' $storiesGen\n' : ''} + '''; + } +} diff --git a/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_chapter.dart b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_chapter.dart new file mode 100644 index 00000000..a4dfcfe6 --- /dev/null +++ b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_chapter.dart @@ -0,0 +1,14 @@ +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/isolation_node.dart'; + +class DashBookChapter extends IsolationNode { + String builderCode; + DashBookChapter(String name, this.builderCode) : super(name: name); + + @override + String generate() { + return ''' + .add('$name', + (ctx) => $builderCode) + '''; + } +} diff --git a/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_story.dart b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_story.dart new file mode 100644 index 00000000..1522acb4 --- /dev/null +++ b/lib/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_story.dart @@ -0,0 +1,23 @@ +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_chapter.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/isolation_node.dart'; + +/// Node that represents a Widgetbook component. +class DashBookStory extends IsolationNode { + DashBookStory(String name) : super(name: name); + + @override + String generate() { + var chapters = getType(); + var chaptersGen = ''; + if (chapters != null && chapters.isNotEmpty) { + chaptersGen = chapters.map((chapter) => chapter.generate()).join('\n'); + } + return ''' + dashbook + .storiesOf('$name') + .decorator(CenterDecorator()) + $chaptersGen + ; + '''; + } +} diff --git a/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart b/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart index b3ae872b..6249b7c9 100644 --- a/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart +++ b/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart @@ -7,6 +7,8 @@ import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.d import 'package:parabeac_core/interpret_and_optimize/helpers/override_helper.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import '../import_generator.dart'; + class PBBitmapGenerator extends PBGenerator { var _sizehelper; @@ -21,11 +23,24 @@ class PBBitmapGenerator extends PBGenerator { ) { var buffer = StringBuffer(); var imageOverride = OverrideHelper.getProperty(source.UUID, 'image'); + + var imageFormat = 'Image'; + + if ((source as InheritedBitmap).referenceImage.endsWith('.svg')) { + generatorContext.project.genProjectData + .addDependencies('flutter_svg', '^1.0.3'); + + generatorContext.managerData + .addImport(FlutterImport('flutter_svg.dart', 'flutter_svg')); + + imageFormat = 'SvgPicture'; + } + if (imageOverride != null) { buffer.write(imageOverride.generateOverride()); } - buffer.write('Image.asset('); + buffer.write('$imageFormat.asset('); var styleOverride = OverrideHelper.getProperty(source.UUID, 'layerStyle'); if (styleOverride != null) { diff --git a/lib/generation/generators/writers/pb_flutter_writer.dart b/lib/generation/generators/writers/pb_flutter_writer.dart index 6001e846..28f71f15 100644 --- a/lib/generation/generators/writers/pb_flutter_writer.dart +++ b/lib/generation/generators/writers/pb_flutter_writer.dart @@ -135,7 +135,7 @@ class MyApp extends StatelessWidget { // Return names inside image reference storage return ImageReferenceStorage() .names - .map((imageName) => '${imageName}.png') + .map((imageName) => '${imageName}') .toList(); } catch (e) { return []; diff --git a/lib/interpret_and_optimize/entities/inherited_bitmap.dart b/lib/interpret_and_optimize/entities/inherited_bitmap.dart index bffef89b..0a328992 100644 --- a/lib/interpret_and_optimize/entities/inherited_bitmap.dart +++ b/lib/interpret_and_optimize/entities/inherited_bitmap.dart @@ -47,7 +47,7 @@ class InheritedBitmap extends PBVisualIntermediateNode childrenStrategy = NoChildStrategy(); if (referenceImage != null && referenceImage.isNotEmpty) { ImageReferenceStorage().addReference( - referenceImage.split('.').first.replaceAll('images/', ''), + referenceImage.replaceAll('images/', ''), '${MainInfo().outputPath}assets/images'); } } diff --git a/lib/interpret_and_optimize/helpers/component_isolation_configuration.dart b/lib/interpret_and_optimize/helpers/component_isolation_configuration.dart index 1f48b56c..283f8e03 100644 --- a/lib/interpret_and_optimize/helpers/component_isolation_configuration.dart +++ b/lib/interpret_and_optimize/helpers/component_isolation_configuration.dart @@ -1,7 +1,9 @@ import 'package:parabeac_core/controllers/interpret.dart'; import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/component_isolation_generator.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/dashbook_generator.dart'; import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/widgetbook/widgetbook_generator.dart'; import 'package:parabeac_core/generation/generators/util/pb_generation_project_data.dart'; +import 'package:parabeac_core/interpret_and_optimize/services/component_isolation/dashbook_service.dart'; import 'package:parabeac_core/interpret_and_optimize/services/component_isolation/widgetbook_service.dart'; /// Class that bundles a ComponentIsolationGenerator and an AITHandler @@ -18,6 +20,9 @@ class ComponentIsolationConfiguration { case 'widgetbook': return ComponentIsolationConfiguration._internal( WidgetbookGenerator(projectData), WidgetBookService()); + case 'dashbook': + return ComponentIsolationConfiguration._internal( + DashbookGenerator(projectData), DashbookService()); default: return null; } diff --git a/lib/interpret_and_optimize/services/component_isolation/dashbook_service.dart b/lib/interpret_and_optimize/services/component_isolation/dashbook_service.dart new file mode 100644 index 00000000..57f5c8cb --- /dev/null +++ b/lib/interpret_and_optimize/services/component_isolation/dashbook_service.dart @@ -0,0 +1,70 @@ +import 'package:parabeac_core/controllers/interpret.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_book.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_chapter.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/post_gen_tasks/comp_isolation/dashbook/entities/dashbook_story.dart'; +import 'package:parabeac_core/generation/generators/attribute-helper/pb_size_helper.dart'; +import 'package:parabeac_core/generation/generators/symbols/pb_instancesym_gen.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_instance.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_intermediate_node_tree.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:recase/recase.dart'; + +class DashbookService extends AITHandler { + /// Map that holds the name of the folder as its key, and the folder as its value. + + static Map _dashBookStories; + static DashBookBook book = DashBookBook(); + static final treeIds = []; + + DashbookService() { + _dashBookStories = {}; + } + + @override + Future handleTree( + PBContext context, PBIntermediateTree tree) async { + /// Only process [PBSharedMasterNode]s. + if (tree.rootNode is PBSharedMasterNode) { + treeIds.add(tree.UUID); + + var component = tree.rootNode as PBSharedMasterNode; + var rootName = component.componentSetName ?? tree.rootNode.name; + + /// Create new Widget for this variation if it doesn't exist already + if (!_dashBookStories.containsKey(rootName)) { + _dashBookStories[rootName] = DashBookStory(rootName); + book.addChild(_dashBookStories[rootName]); + } + + /// Create a fake instance in order to generate the Use Case. + // FIXME: Generating the code should happen somewhere in generate, not here. + var dummyInstance = PBSharedInstanceIntermediateNode( + null, + tree.rootNode.frame.copyWith(), + SYMBOL_ID: component.SYMBOL_ID, + name: rootName, + sharedNodeSetID: component.sharedNodeSetID, + ); + var sizeHelper = PBSizeHelper(); + + var generatedCode = ''' + SizedBox( + ${sizeHelper.generate(dummyInstance, context.copyWith(sizingContext: SizingValueContext.PointValue))} + child: ${(dummyInstance.generator as PBSymbolInstanceGenerator).generate( + dummyInstance, + context.copyWith(), + )}, + ), + '''; + + /// Create a use case for the current component and add it to the folder. + var useCase = DashBookChapter( + (tree.rootNode as PBSharedMasterNode).name.pascalCase, + generatedCode, + ); + _dashBookStories[rootName].addChild(useCase); + } + return tree; + } +}