diff --git a/README.md b/README.md index 1c72a315..dcca1598 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,11 @@ Since Figma operates from a cloud native approach we use the Figma File ID and a 3. Scroll Down to the "Create a new Personal Access Token" 4. Create a new Personal Access Token with the name Parabeac, you should then be prompted with your new API Key. Make sure to copy this as you wont be able to access it again after you click confirm. (It should look something like this: ```64522-a0e5509a-d5ce-47a8-880b-c295f9cb27ed``` +<<<<<<< HEAD +======= +## Metrics +Parabeac-core keeps track of how many times it is run. Although we do not collect any personal information, you can turn off metrics at any time by creating the environment variable `PB_METRICS = "false"`. +>>>>>>> dev ## Using State Management Configuration ![State Management](https://kindling-sketch.s3.amazonaws.com/PB_to_Flutter_with_State_management.png) @@ -118,9 +123,13 @@ To set the state management configuration, head over to edit `/Parabeac-Core/lib ``` Here you can replace the `state-management` property to `bloc` or `provider`. Soon you can also set `riverpod`. +<<<<<<< HEAD You can learn how to easily create your own state management configuration in the [wiki](https://github.com/Parabeac/Parabeac-Core/wiki/How-to-Create-a-State-Management-Configuration), let us know if you're thinking about doing this and if you need any help! +======= +>>>>>>> dev +You can learn how to easily create your own state management configuration in the [wiki](https://github.com/Parabeac/Parabeac-Core/wiki/How-to-Create-a-State-Management-Configuration), let us know if you're thinking about doing this and if you need any help! # Running the exported code ### Requirements - Flutter diff --git a/lib/configurations/configurations.json b/lib/configurations/configurations.json index 4114a0a7..b16400a4 100644 --- a/lib/configurations/configurations.json +++ b/lib/configurations/configurations.json @@ -1,13 +1,13 @@ { - "default": { - "widgetStyle": "Material", - "widgetType": "Stateless", - "widgetSpacing": "Expanded", - "layoutPrecedence": [ - "column", - "row", - "stack" - ] - }, - "state-management": "provider" + "default": { + "widgetStyle": "Material", + "widgetType": "Stateless", + "widgetSpacing": "Expanded", + "layoutPrecedence": [ + "column", + "row", + "stack" + ] + }, + "state-management": "none" } \ No newline at end of file diff --git a/lib/controllers/controller.dart b/lib/controllers/controller.dart index 3bd9638a..e1e7c45a 100644 --- a/lib/controllers/controller.dart +++ b/lib/controllers/controller.dart @@ -1,3 +1,12 @@ +import 'package:parabeac_core/controllers/interpret.dart'; +import 'package:parabeac_core/generation/flutter_project_builder/flutter_project_builder.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_view_data.dart'; +import 'package:parabeac_core/generation/generators/writers/pb_flutter_writer.dart'; +import 'package:parabeac_core/generation/generators/writers/pb_traversal_adapter_writer.dart'; +import 'package:parabeac_core/generation/pre-generation/pre_generation_service.dart'; +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; import 'package:quick_log/quick_log.dart'; import 'dart:convert'; import 'dart:io'; @@ -10,7 +19,41 @@ abstract class Controller { Controller(); void convertFile( - var fileAbsPath, var projectPath, var configurationPath, var configType); + var fileAbsPath, + var projectPath, + var configurationPath, + var configType, { + bool jsonOnly = false, + DesignProject designProject, + AssetProcessingService apService, + }) async { + /// IN CASE OF JSON ONLY + if (jsonOnly) { + return stopAndToJson(designProject, apService); + } + + Interpret().init(projectPath); + + var pbProject = await Interpret().interpretAndOptimize(designProject); + + pbProject.forest.forEach((tree) => tree.data = PBGenerationViewData()); + + await PreGenerationService( + projectName: projectPath, + mainTree: pbProject, + pageWriter: PBTraversalAdapterWriter(), + ).convertToFlutterProject(); + + //Making the data immutable for writing into the file + pbProject.forest.forEach((tree) => tree.data.lockData()); + + var fpb = FlutterProjectBuilder( + projectName: projectPath, + mainTree: pbProject, + pageWriter: PBFlutterWriter()); + + await fpb.convertToFlutterProject(); + } void configure(var configurationPath, var configType) async { Map configurations; @@ -34,4 +77,57 @@ abstract class Controller { MainInfo().configurations = configurations; MainInfo().configurationType = configType; } + + /// Method that returns the given path and ensures + /// it ends with a / + String verifyPath(String path) { + if (path.endsWith('/')) { + return path; + } else { + return '${path}/'; + } + } + + Future stopAndToJson( + DesignProject project, AssetProcessingService apService) async { + var uuids = processRootNodeUUIDs(project, apService); + // Process rootnode UUIDs + await apService.processRootElements(uuids); + project.projectName = MainInfo().projectName; + var projectJson = project.toPBDF(); + projectJson['azure_container_uri'] = AzureAssetService().getContainerUri(); + var encodedJson = json.encode(projectJson); + File('${verifyPath(MainInfo().outputPath)}${project.projectName}.json') + .writeAsStringSync(encodedJson); + log.info( + 'Created PBDL JSON file at ${verifyPath(MainInfo().outputPath)}${project.projectName}.json'); + } + + /// Iterates through the [project] and returns a list of the UUIDs of the + /// rootNodes + Map processRootNodeUUIDs( + DesignProject project, AssetProcessingService apService) { + var result = {}; + + for (var page in project.pages) { + for (var screen in page.screens) { + screen.imageURI = AzureAssetService().getImageURI('${screen.id}.png'); + result[screen.id] = { + 'width': screen.designNode.boundaryRectangle.width, + 'height': screen.designNode.boundaryRectangle.height + }; + } + } + + for (var page in project.miscPages) { + for (var screen in page.screens) { + result[screen.id] = { + 'width': screen.designNode.boundaryRectangle.width, + 'height': screen.designNode.boundaryRectangle.height + }; + } + } + + return result; + } } diff --git a/lib/controllers/design_controller.dart b/lib/controllers/design_controller.dart new file mode 100644 index 00000000..f4936101 --- /dev/null +++ b/lib/controllers/design_controller.dart @@ -0,0 +1,42 @@ +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; +import 'package:quick_log/quick_log.dart'; + +import 'controller.dart'; + +class DesignController extends Controller { + @override + var log = Logger('FigmaController'); + + DesignController(); + + @override + void convertFile( + var pbdf, + var outputPath, + var configurationPath, + var configType, { + bool jsonOnly = false, + DesignProject designProject, + AssetProcessingService apService, + }) async { + configure(configurationPath, configType); + + var designProject = await generateDesignProject(pbdf, outputPath); + AzureAssetService().projectUUID = pbdf['id']; + + await super.convertFile( + pbdf, + outputPath, + configurationPath, + configType, + designProject: designProject, + jsonOnly: jsonOnly, + ); + } + + DesignProject generateDesignProject(var pbdf, var proejctName) { + return DesignProject.fromPBDF(pbdf); + } +} diff --git a/lib/controllers/figma_controller.dart b/lib/controllers/figma_controller.dart index e6a70dd2..dc06161d 100644 --- a/lib/controllers/figma_controller.dart +++ b/lib/controllers/figma_controller.dart @@ -1,11 +1,9 @@ import 'package:parabeac_core/controllers/controller.dart'; -import 'package:parabeac_core/generation/flutter_project_builder/flutter_project_builder.dart'; -import 'package:parabeac_core/generation/generators/util/pb_generation_view_data.dart'; -import 'package:parabeac_core/generation/generators/writers/pb_flutter_writer.dart'; -import 'package:parabeac_core/generation/generators/writers/pb_traversal_adapter_writer.dart'; -import 'package:parabeac_core/generation/pre-generation/pre_generation_service.dart'; import 'package:parabeac_core/input/figma/entities/layers/frame.dart'; -import 'package:parabeac_core/input/figma/helper/figma_node_tree.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; +import 'package:parabeac_core/input/figma/helper/figma_project.dart'; +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; import 'package:quick_log/quick_log.dart'; import 'interpret.dart'; @@ -18,40 +16,35 @@ class FigmaController extends Controller { FigmaController(); @override - void convertFile(var jsonFigma, var outputPath, var configurationPath, - var configType) async { + void convertFile( + var jsonFigma, + var outputPath, + var configurationPath, + var configType, { + bool jsonOnly = false, + DesignProject designProject, + AssetProcessingService apService, + }) async { configure(configurationPath, configType); - var figmaNodeTree = await generateFigmaTree(jsonFigma, outputPath); + var figmaProject = await generateFigmaTree(jsonFigma, outputPath); - figmaNodeTree = declareScaffolds(figmaNodeTree); + figmaProject = declareScaffolds(figmaProject); - Interpret().init(outputPath); - - var pbProject = await Interpret().interpretAndOptimize(figmaNodeTree); - - pbProject.forest.forEach((tree) => tree.data = PBGenerationViewData()); - - await PreGenerationService( - projectName: outputPath, - mainTree: pbProject, - pageWriter: PBTraversalAdapterWriter(), - ).convertToFlutterProject(); - - //Making the data immutable for writing into the file - pbProject.forest.forEach((tree) => tree.data.lockData()); - - var fpb = FlutterProjectBuilder( - projectName: outputPath, - mainTree: pbProject, - pageWriter: PBFlutterWriter()); - - await fpb.convertToFlutterProject(); + await super.convertFile( + jsonFigma, + outputPath, + configurationPath, + configType, + designProject: figmaProject, + jsonOnly: jsonOnly, + apService: apService, + ); } - FigmaNodeTree generateFigmaTree(var jsonFigma, var projectname) { + FigmaProject generateFigmaTree(var jsonFigma, var projectname) { try { - return FigmaNodeTree(projectname, jsonFigma); + return FigmaProject(projectname, jsonFigma); } catch (e, stackTrace) { print(e); return null; @@ -60,11 +53,11 @@ class FigmaController extends Controller { /// This method was required for Figma, so we could /// detect which `FigmaFrame` were Scaffolds or Containers - FigmaNodeTree declareScaffolds(FigmaNodeTree tree) { + FigmaProject declareScaffolds(FigmaProject tree) { for (var page in tree.pages) { for (var item in page.getPageItems()) { - if (item.root is FigmaFrame) { - (item.root as FigmaFrame).isScaffold = true; + if (item.designNode is FigmaFrame) { + (item.designNode as FigmaFrame).isScaffold = true; } } } diff --git a/lib/controllers/interpret.dart b/lib/controllers/interpret.dart index 509c62c2..58f13acc 100644 --- a/lib/controllers/interpret.dart +++ b/lib/controllers/interpret.dart @@ -2,9 +2,9 @@ import 'package:parabeac_core/controllers/main_info.dart'; import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/generation/generators/pb_generation_manager.dart'; import 'package:parabeac_core/generation/prototyping/pb_prototype_linker_service.dart'; -import 'package:parabeac_core/input/helper/node_tree.dart'; -import 'package:parabeac_core/input/helper/page.dart'; -import 'package:parabeac_core/input/helper/page_item.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; +import 'package:parabeac_core/input/helper/design_page.dart'; +import 'package:parabeac_core/input/helper/design_screen.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_scaffold.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/layouts/temp_group_layout_node.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart'; @@ -47,7 +47,7 @@ class Interpret { _interpret._pbPrototypeLinkerService = PBPrototypeLinkerService(); } - Future interpretAndOptimize(NodeTree tree) async { + Future interpretAndOptimize(DesignProject tree) async { _pb_project = PBProject(projectName, tree.sharedStyles); ///3rd Party Symbols @@ -67,7 +67,7 @@ class Interpret { return _pb_project; } - Future> _generateGroup(Page group) async { + Future> _generateGroup(DesignPage group) async { var tempForest = []; var pageItems = group.getPageItems(); for (var i = 0; i < pageItems.length; i++) { @@ -96,22 +96,26 @@ class Interpret { return tempForest; } - Future _generateScreen(PageItem item) async { + Future _generateScreen(DesignScreen item) async { var currentContext = PBContext( jsonConfigurations: MainInfo().configurations ?? MainInfo().defaultConfigs); - var parentComponent = item.root; + var parentComponent = item.designNode; var stopwatch = Stopwatch()..start(); /// VisualGenerationService - var intermediateTree = PBIntermediateTree(item.root.name); + var intermediateTree = PBIntermediateTree(item.designNode.name); currentContext.treeRoot = intermediateTree; currentContext.project = _pb_project; intermediateTree.rootNode = await visualGenerationService( parentComponent, currentContext, stopwatch); + if (intermediateTree.rootNode == null) { + return intermediateTree; + } + /// /// pre-layout generation service for plugin nodes. /// NOTE Disabled Plugin Control Service for right now diff --git a/lib/controllers/sketch_controller.dart b/lib/controllers/sketch_controller.dart index c8691e5f..db30f826 100644 --- a/lib/controllers/sketch_controller.dart +++ b/lib/controllers/sketch_controller.dart @@ -1,11 +1,9 @@ import 'package:parabeac_core/controllers/controller.dart'; -import 'package:parabeac_core/controllers/interpret.dart'; -import 'package:parabeac_core/generation/flutter_project_builder/flutter_project_builder.dart'; -import 'package:parabeac_core/generation/generators/util/pb_generation_view_data.dart'; -import 'package:parabeac_core/generation/generators/writers/pb_flutter_writer.dart'; -import 'package:parabeac_core/generation/generators/writers/pb_traversal_adapter_writer.dart'; -import 'package:parabeac_core/generation/pre-generation/pre_generation_service.dart'; -import 'package:parabeac_core/input/sketch/helper/sketch_node_tree.dart'; +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; + +import 'package:parabeac_core/input/helper/design_project.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_project.dart'; import 'package:parabeac_core/input/sketch/services/input_design.dart'; import 'package:quick_log/quick_log.dart'; @@ -18,45 +16,39 @@ class SketchController extends Controller { ///Converting the [fileAbsPath] sketch file to flutter @override - void convertFile(var fileAbsPath, var projectPath, var configurationPath, - var configType) async { + void convertFile( + var fileAbsPath, + var projectPath, + var configurationPath, + var configType, { + bool jsonOnly = false, + DesignProject designProject, + AssetProcessingService apService, + }) async { configure(configurationPath, configType); ///INTAKE - var ids = InputDesignService(fileAbsPath); - var sketchNodeTree = generateSketchNodeTree( + var ids = InputDesignService(fileAbsPath, jsonOnly: jsonOnly); + var sketchProject = generateSketchNodeTree( ids, ids.metaFileJson['pagesAndArtboards'], projectPath); - ///INTERPRETATION - Interpret().init(projectPath); - var pbProject = await Interpret().interpretAndOptimize( - sketchNodeTree, - ); - pbProject.forest.forEach((tree) => tree.data = PBGenerationViewData()); + AzureAssetService().projectUUID = sketchProject.id; - ///PRE-GENERATION SERVICE - var pgs = PreGenerationService( - projectName: projectPath, - mainTree: pbProject, - pageWriter: PBTraversalAdapterWriter(), + await super.convertFile( + fileAbsPath, + projectPath, + configurationPath, + configType, + designProject: sketchProject, + jsonOnly: jsonOnly, + apService: apService, ); - await pgs.convertToFlutterProject(); - - //Making the data immutable for writing into the file - pbProject.forest.forEach((tree) => tree.data.lockData()); - - ///GENERATE FLUTTER CODE - var fpb = FlutterProjectBuilder( - projectName: projectPath, - mainTree: pbProject, - pageWriter: PBFlutterWriter()); - await fpb.convertToFlutterProject(); } - SketchNodeTree generateSketchNodeTree( + SketchProject generateSketchNodeTree( InputDesignService ids, Map pagesAndArtboards, projectName) { try { - return SketchNodeTree(ids, pagesAndArtboards, projectName); + return SketchProject(ids, pagesAndArtboards, projectName); } catch (e, stackTrace) { MainInfo().sentry.captureException( exception: e, diff --git a/lib/design_logic/abstract_design_node_factory.dart b/lib/design_logic/abstract_design_node_factory.dart new file mode 100644 index 00000000..ce0ac314 --- /dev/null +++ b/lib/design_logic/abstract_design_node_factory.dart @@ -0,0 +1,58 @@ +import 'package:parabeac_core/input/helper/design_page.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; +import 'package:parabeac_core/input/helper/design_screen.dart'; + +import 'artboard.dart'; +import 'boolean_operation.dart'; +import 'design_node.dart'; +import 'group_node.dart'; +import 'image.dart'; +import 'oval.dart'; +import 'pb_shared_instance_design_node.dart'; +import 'pb_shared_master_node.dart'; +import 'polygon.dart'; +import 'rectangle.dart'; +import 'star.dart'; +import 'text.dart'; +import 'vector.dart'; + +class AbstractDesignNodeFactory { + static final String DESIGN_CLASS_KEY = 'pbdfType'; + + static final List _designNodes = [ + PBArtboard(), + BooleanOperation(), + GroupNode(), + Image(), + Oval(), + PBSharedInstanceDesignNode(), + PBSharedMasterDesignNode(), + Polygon(), + Rectangle(), + Star(), + Text(), + Vector(), + DesignProject(), + DesignPage(), + DesignScreen(), + ]; + + AbstractDesignNodeFactory(); + + static DesignNode getDesignNode(Map json) { + var className = json[DESIGN_CLASS_KEY]; + if (className != null) { + for (var designNode in _designNodes) { + if (designNode.pbdfType == className) { + return designNode.createDesignNode(json); + } + } + } + return null; + } +} + +abstract class DesignNodeFactory { + String pbdfType; + DesignNode createDesignNode(Map json); +} diff --git a/lib/design_logic/artboard.dart b/lib/design_logic/artboard.dart index b0b08e5e..961d4395 100644 --- a/lib/design_logic/artboard.dart +++ b/lib/design_logic/artboard.dart @@ -2,11 +2,119 @@ import 'package:parabeac_core/design_logic/color.dart'; import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/group_node.dart'; import 'package:parabeac_core/design_logic/rect.dart'; +import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/input/sketch/entities/style/color.dart'; +import 'package:parabeac_core/input/sketch/entities/style/style.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_scaffold.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; -abstract class PBArtboard extends DesignNode implements GroupNode { +import 'abstract_design_node_factory.dart'; + +class PBArtboard extends DesignNode implements GroupNode, DesignNodeFactory { PBColor backgroundColor; - PBArtboard(this.backgroundColor, UUID, String name, bool isVisible, - Rect boundaryRectangle, String type, style, prototypeNode) + @override + var boundaryRectangle; + var isFlowHome; + PBArtboard( + {Color this.backgroundColor, + this.isFlowHome, + hasClickThrough, + groupLayout, + UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + Flow flow, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + isVisible, + layerListExpandedType, + name, + nameIsFixed, + resizingConstraint, + resizingType, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + Style style, + maintainScrollPosition, + prototypeNode, + type}) : super(UUID, name, isVisible, boundaryRectangle, type, style, prototypeNode); + + @override + List children = []; + + @override + String pbdfType = 'artboard'; + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + var node = PBArtboard( + backgroundColor: json['backgroundColor'] == null + ? null + : Color.fromJson(json['backgroundColor'] as Map), + isFlowHome: json['isFlowHome'] as bool, + hasClickThrough: json['hasClickThrough'], + groupLayout: json['groupLayout'], + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + flow: json['flow'] == null + ? null + : Flow.fromJson(json['flow'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + style: json['style'] == null + ? null + : Style.fromJson(json['style'] as Map), + maintainScrollPosition: json['maintainScrollPosition'], + ) + ..prototypeNodeUUID = json['prototypeNodeUUID'] as String + ..type = json['type'] as String; + if (json.containsKey('children')) { + if (json['children'] != null) { + node.children + .add(DesignNode.fromPBDF(json['children'] as Map)); + } + } + return node; + } + + @override + Future interpretNode(PBContext currentContext) { + return Future.value(InheritedScaffold( + this, + currentContext: currentContext, + name: name, + isHomeScreen: isFlowHome, + )); + } } diff --git a/lib/design_logic/boolean_operation.dart b/lib/design_logic/boolean_operation.dart new file mode 100644 index 00000000..26c364d4 --- /dev/null +++ b/lib/design_logic/boolean_operation.dart @@ -0,0 +1,98 @@ +import 'dart:io'; + +import 'package:parabeac_core/controllers/main_info.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; + +import 'abstract_design_node_factory.dart'; + +class BooleanOperation implements DesignNodeFactory, DesignNode { + @override + String pbdfType = 'boolean_operation'; + List children = []; + + @override + var boundaryRectangle; + + BooleanOperation({ + booleanOperation, + type, + Frame this.boundaryRectangle, + String UUID, + String name, + bool isVisible, + pbdfType, + }); + + @override + Future interpretNode(PBContext currentContext) async { + var img = await AzureAssetService().downloadImage(UUID); + var file = + File('${MainInfo().outputPath}pngs/${UUID}.png'.replaceAll(':', '_')) + ..createSync(recursive: true); + file.writeAsBytesSync(img); + + return Future.value(InheritedBitmap( + this, + name, + currentContext: currentContext, + )); + } + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + var node = BooleanOperation( + booleanOperation: json['booleanOperation'], + type: json['type'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + UUID: json['id'] as String, + name: json['name'] as String, + isVisible: json['visible'] as bool ?? true, + pbdfType: json['pbdfType'] as String, + ); + if (json.containsKey('children')) { + if (json['children'] != null) { + node.children + .add(DesignNode.fromPBDF(json['children'] as Map)); + } + } + return node; + } + + @override + String UUID; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + toJson() { + throw UnimplementedError(); + } + + @override + Map toPBDF() { + throw UnimplementedError(); + } + + @override + bool isVisible; +} diff --git a/lib/design_logic/design_node.dart b/lib/design_logic/design_node.dart index 7f1f45bb..a7dcafff 100644 --- a/lib/design_logic/design_node.dart +++ b/lib/design_logic/design_node.dart @@ -2,7 +2,9 @@ import 'package:parabeac_core/design_logic/pb_style.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; -abstract class DesignNode { +import 'abstract_design_node_factory.dart'; + +class DesignNode { DesignNode( this.UUID, this.name, @@ -13,6 +15,7 @@ abstract class DesignNode { this.prototypeNodeUUID, ); + String pbdfType; String UUID; String name; bool isVisible; @@ -21,7 +24,15 @@ abstract class DesignNode { PBStyle style; String prototypeNodeUUID; - toJson(); + toJson() {} + + Future interpretNode(PBContext currentContext) {} + + Map toPBDF() {} + + factory DesignNode.fromPBDF(Map json) => + AbstractDesignNodeFactory.getDesignNode(json); - Future interpretNode(PBContext currentContext); + factory DesignNode.fromJson(Map json) => + AbstractDesignNodeFactory.getDesignNode(json); } diff --git a/lib/design_logic/group_node.dart b/lib/design_logic/group_node.dart index 642f5026..6fa96109 100644 --- a/lib/design_logic/group_node.dart +++ b/lib/design_logic/group_node.dart @@ -1,7 +1,127 @@ -abstract class GroupNode { - GroupNode( - this.children, - ); +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/layouts/temp_group_layout_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; +import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; - List children; +import 'abstract_design_node_factory.dart'; + +class GroupNode implements DesignNodeFactory, DesignNode { + List children = []; + + @override + String pbdfType = 'group'; + + GroupNode({ + bool hasClickThrough, + groupLayout, + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + this.isVisible, + layerListExpandedType, + this.name, + nameIsFixed, + resizingConstraint, + resizingType, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + this.pbdfType = 'group', + }); + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + var node = GroupNode( + hasClickThrough: json['hasClickThrough'] as bool, + groupLayout: json['groupLayout'], + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'], + pbdfType: json['pbdfType'], + ) + ..prototypeNodeUUID = json['prototypeNodeUUID'] as String + ..type = json['type'] as String; + if (json.containsKey('children')) { + if (json['children'] != null) { + node.children + .add(DesignNode.fromPBDF(json['children'] as Map)); + } + } + return node; + } + + @override + String UUID; + + @override + var boundaryRectangle; + + @override + bool isVisible; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + Future interpretNode(PBContext currentContext) => + Future.value(TempGroupLayoutNode(this, currentContext, name, + topLeftCorner: Point(boundaryRectangle.x, boundaryRectangle.y), + bottomRightCorner: Point( + boundaryRectangle.x + boundaryRectangle.width, + boundaryRectangle.y + boundaryRectangle.height))); + + @override + toJson() { + // TODO: implement toJson + throw UnimplementedError(); + } + + @override + Map toPBDF() { + // TODO: implement toPBDF + throw UnimplementedError(); + } } diff --git a/lib/design_logic/image.dart b/lib/design_logic/image.dart index 645d233f..a031f0c3 100644 --- a/lib/design_logic/image.dart +++ b/lib/design_logic/image.dart @@ -1,9 +1,97 @@ +import 'dart:io'; + +import 'package:parabeac_core/controllers/main_info.dart'; import 'package:parabeac_core/design_logic/design_element.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; + +import 'abstract_design_node_factory.dart'; + +class Image extends DesignElement implements DesignNodeFactory, DesignNode { + var boundaryRectangle; + + var UUID; -abstract class Image extends DesignElement { - Image( + Image({ this.imageReference, - ) : super(); + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + isVisible, + layerListExpandedType, + name, + nameIsFixed, + resizingConstraint, + resizingType, + num rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + pbdfType, + }); String imageReference; + + @override + String pbdfType = 'image'; + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return Image( + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'] as num, + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'], + pbdfType: json['pbdfType'], + ) + ..prototypeNodeUUID = json['prototypeNodeUUID'] as String + ..type = json['type'] as String; + } + + @override + Future interpretNode(PBContext currentContext) async { + var img = await AzureAssetService().downloadImage(UUID); + var file = + File('${MainInfo().outputPath}pngs/${UUID}.png'.replaceAll(':', '_')) + ..createSync(recursive: true); + file.writeAsBytesSync(img); + return Future.value(InheritedBitmap( + this, + name, + currentContext: currentContext, + )); + } } diff --git a/lib/design_logic/oval.dart b/lib/design_logic/oval.dart new file mode 100644 index 00000000..336bb098 --- /dev/null +++ b/lib/design_logic/oval.dart @@ -0,0 +1,117 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_oval.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; + +import 'abstract_design_node_factory.dart'; + +class Oval implements DesignNodeFactory, DesignNode { + @override + String pbdfType = 'oval'; + + var boundaryRectangle; + + var UUID; + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + Oval({ + bool edited, + bool isClosed, + pointRadiusBehaviour, + List points, + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + this.isVisible, + layerListExpandedType, + this.name, + nameIsFixed, + resizingConstraint, + resizingType, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + type, + this.pbdfType = 'oval', + }); + DesignNode fromPBDF(Map json) { + return Oval( + edited: json['edited'] as bool, + isClosed: json['isClosed'] as bool, + pointRadiusBehaviour: json['pointRadiusBehaviour'], + points: json['points'] as List, + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'], + type: json['type'] as String, + pbdfType: json['pbdfType'] as String, + ); + } + + @override + bool isVisible; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + Future interpretNode(PBContext currentContext) async { + var img = await AzureAssetService().downloadImage(UUID); + + return Future.value( + InheritedOval(this, name, currentContext: currentContext, image: img)); + } + + @override + toJson() { + throw UnimplementedError(); + } + + @override + Map toPBDF() { + throw UnimplementedError(); + } +} diff --git a/lib/design_logic/pb_shared_instance_design_node.dart b/lib/design_logic/pb_shared_instance_design_node.dart index df8f4cc4..d858287d 100644 --- a/lib/design_logic/pb_shared_instance_design_node.dart +++ b/lib/design_logic/pb_shared_instance_design_node.dart @@ -1,11 +1,126 @@ import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/override_value.dart'; +import 'package:parabeac_core/input/sketch/helper/symbol_node_mixin.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_instance.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; -abstract class PBSharedInstanceDesignNode extends DesignNode { +import 'abstract_design_node_factory.dart'; + +class PBSharedInstanceDesignNode extends DesignNode + with SymbolNodeMixin + implements DesignNodeFactory { String symbolID; List parameters; - PBSharedInstanceDesignNode(String UUID, String name, bool isVisible, - boundaryRectangle, String type, style, prototypeNode) + PBSharedInstanceDesignNode( + {String UUID, + this.overrideValues, + String name, + bool isVisible, + boundaryRectangle, + String type, + style, + prototypeNode, + exportOptions, + booleanOperation, + bool isFixedToViewport, + bool isFlippedVertical, + bool isFlippedHorizontal, + bool isLocked, + layerListExpandedType, + bool nameIsFixed, + resizingConstraint, + resizingType, + num rotation, + sharedStyleID, + bool shouldBreakMaskChain, + bool hasClippingMask, + int clippingMaskMode, + userInfo, + bool maintainScrollPosition, + num scale, + String symbolID, + num verticalSpacing, + num horizontalSpacing, + pbdfType}) : super(UUID, name, isVisible, boundaryRectangle, type, style, prototypeNode); + + @override + String pbdfType = 'symbol_instance'; + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return PBSharedInstanceDesignNode( + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'] as bool, + isFlippedHorizontal: json['isFlippedHorizontal'] as bool, + isFlippedVertical: json['isFlippedVertical'] as bool, + isLocked: json['isLocked'] as bool, + isVisible: json['visible'] as bool, + layerListExpandedType: json['layerListExpandedType'], + name: json['name'] as String, + nameIsFixed: json['nameIsFixed'] as bool, + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'] as num, + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'] as bool, + hasClippingMask: json['hasClippingMask'] as bool, + clippingMaskMode: json['clippingMaskMode'] as int, + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'] as bool, + overrideValues: (json['overrideValues'] as List) + ?.map((e) => e == null + ? null + : OverridableValue.fromJson(e as Map)) + ?.toList(), + scale: (json['scale'] as num)?.toDouble(), + symbolID: json['symbolID'] as String, + verticalSpacing: (json['verticalSpacing'] as num)?.toDouble(), + horizontalSpacing: (json['horizontalSpacing'] as num)?.toDouble(), + type: json['type'] as String, + pbdfType: json['pbdfType'], + ) + ..prototypeNodeUUID = json['prototypeNodeUUID'] as String + ..parameters = json['parameters'] as List; + } + + @override + Future interpretNode(PBContext currentContext) { + var sym = PBSharedInstanceIntermediateNode(this, symbolID, + sharedParamValues: _extractParameters(), + currentContext: currentContext); + return Future.value(sym); + } + + ///Converting the [OverridableValue] into [PBSharedParameterValue] to be processed in intermediate phase. + List _extractParameters() { + Set ovrNames = {}; + List sharedParameters = []; + for (var overrideValue in overrideValues) { + if (!ovrNames.contains(overrideValue.overrideName)) { + var properties = extractParameter(overrideValue.overrideName); + sharedParameters.add(PBSharedParameterValue( + properties['type'], + overrideValue.value, + properties['uuid'], + overrideValue.overrideName)); + ovrNames.add(overrideValue.overrideName); + } + } + + return sharedParameters; + } + + final List overrideValues; } diff --git a/lib/design_logic/pb_shared_master_node.dart b/lib/design_logic/pb_shared_master_node.dart index a146011f..cddd22ce 100644 --- a/lib/design_logic/pb_shared_master_node.dart +++ b/lib/design_logic/pb_shared_master_node.dart @@ -1,11 +1,170 @@ import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/design_logic/group_node.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/override_property.dart'; +import 'package:parabeac_core/input/sketch/helper/symbol_node_mixin.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; -abstract class PBSharedMasterDesignNode extends DesignNode { +import 'abstract_design_node_factory.dart'; + +class PBSharedMasterDesignNode extends DesignNode + with SymbolNodeMixin + implements DesignNodeFactory, GroupNode { String symbolID; List overriadableProperties; - PBSharedMasterDesignNode(String UUID, String name, bool isVisible, - boundaryRectangle, String type, style, prototypeNode) + var overrideProperties; + + PBSharedMasterDesignNode( + {String UUID, + this.overrideProperties, + String name, + bool isVisible, + boundaryRectangle, + String type, + style, + prototypeNode, + bool hasClickThrough, + groupLayout, + booleanOperation, + exportOptions, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + layerListExpandedType, + pbdfType, + presetDictionary, + bool allowsOverrides, + nameIsFixed, + resizingConstraint, + resizingType, + horizontalRulerData, + bool hasBackgroundColor, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + bool includeBackgroundColorInExport, + int changeIdentifier, + String symbolID, + bool includeBackgroundColorInInstance, + verticalRulerData, + bool resizesContent, + bool includeInCloudUpload, + bool isFlowHome, + List parameters}) : super(UUID, name, isVisible, boundaryRectangle, type, style, prototypeNode); + + @override + String pbdfType = 'symbol_master'; + + @override + Future interpretNode(PBContext currentContext) { + var sym_master = PBSharedMasterNode( + this, + symbolID, + name, + Point(boundaryRectangle.x, boundaryRectangle.y), + Point(boundaryRectangle.x + boundaryRectangle.width, + boundaryRectangle.y + boundaryRectangle.height), + overridableProperties: _extractParameters(), + currentContext: currentContext, + ); + return Future.value(sym_master); + } + + ///Converting the [OverridableProperty] into [PBSharedParameterProp] to be processed in intermediate phase. + List _extractParameters() { + Set ovrNames = {}; + List sharedParameters = []; + for (var prop in overrideProperties) { + if (!ovrNames.contains(prop.overrideName)) { + var properties = AddMasterSymbolName(prop.overrideName, children); + sharedParameters.add(PBSharedParameterProp( + properties['name'], + properties['type'], + null, + prop.canOverride, + prop.overrideName, + properties['uuid'], + properties['default_value'])); + ovrNames.add(prop.overrideName); + } + } + return sharedParameters; + } + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + var node = PBSharedMasterDesignNode( + hasClickThrough: json['hasClickThrough'] as bool, + groupLayout: json['groupLayout'], + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'], + hasBackgroundColor: json['hasBackgroundColor'] as bool, + horizontalRulerData: json['horizontalRulerData'], + includeBackgroundColorInExport: + json['includeBackgroundColorInExport'] as bool, + includeInCloudUpload: json['includeInCloudUpload'] as bool, + isFlowHome: json['isFlowHome'] as bool, + resizesContent: json['resizesContent'] as bool, + verticalRulerData: json['verticalRulerData'], + includeBackgroundColorInInstance: + json['includeBackgroundColorInInstance'] as bool, + symbolID: json['symbolID'] as String, + changeIdentifier: json['changeIdentifier'] as int, + allowsOverrides: json['allowsOverrides'] as bool, + overrideProperties: (json['overrideProperties'] as List) + ?.map((e) => e == null + ? null + : OverridableProperty.fromJson(e as Map)) + ?.toList(), + presetDictionary: json['presetDictionary'], + type: json['type'] as String, + pbdfType: json['pbdfType'], + parameters: json['parameters'] as List, + )..prototypeNodeUUID = json['prototypeNodeUUID'] as String; + + if (json.containsKey('children')) { + if (json['children'] != null) { + node.children + .add(DesignNode.fromPBDF(json['children'] as Map)); + } + } + return node; + } + + @override + List children = []; } diff --git a/lib/design_logic/polygon.dart b/lib/design_logic/polygon.dart new file mode 100644 index 00000000..b719c649 --- /dev/null +++ b/lib/design_logic/polygon.dart @@ -0,0 +1,118 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_polygon.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; + +import 'abstract_design_node_factory.dart'; + +class Polygon implements DesignNodeFactory, DesignNode { + @override + String pbdfType = 'polygon'; + + var boundaryRectangle; + + var UUID; + + Polygon({ + bool edited, + bool isClosed, + pointRadiusBehaviour, + List points, + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + isVisible, + layerListExpandedType, + name, + nameIsFixed, + resizingConstraint, + resizingType, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + type, + pbdfType, + }); + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return Polygon( + edited: json['edited'] as bool, + isClosed: json['isClosed'] as bool, + pointRadiusBehaviour: json['pointRadiusBehaviour'], + points: json['points'] as List, + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'], + type: json['type'] as String, + pbdfType: json['pbdfType'] as String, + ); + } + + @override + bool isVisible; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + Future interpretNode(PBContext currentContext) async { + var img = await AzureAssetService().downloadImage(UUID); + + return Future.value(InheritedPolygon(this, name, + currentContext: currentContext, image: img)); + } + + @override + toJson() { + throw UnimplementedError(); + } + + @override + Map toPBDF() { + throw UnimplementedError(); + } +} diff --git a/lib/design_logic/rectangle.dart b/lib/design_logic/rectangle.dart new file mode 100644 index 00000000..b5cb4a47 --- /dev/null +++ b/lib/design_logic/rectangle.dart @@ -0,0 +1,154 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/input/sketch/entities/style/border.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_container.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; +import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; + +import 'abstract_design_node_factory.dart'; +import 'color.dart'; + +class Rectangle with PBColorMixin implements DesignNodeFactory, DesignNode { + @override + String pbdfType = 'rectangle'; + + var hasConvertedToNewRoundCorners; + + var fixedRadius; + + var needsConvertionToNewRoundCorners; + + var points; + + Rectangle({ + this.fixedRadius, + this.hasConvertedToNewRoundCorners, + this.needsConvertionToNewRoundCorners, + bool edited, + bool isClosed, + pointRadiusBehaviour, + List points, + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + isVisible, + layerListExpandedType, + name, + nameIsFixed, + resizingConstraint, + resizingType, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + type, + pbdfType, + }); + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return Rectangle( + fixedRadius: (json['fixedRadius'] as num)?.toDouble(), + hasConvertedToNewRoundCorners: + json['hasConvertedToNewRoundCorners'] as bool, + needsConvertionToNewRoundCorners: + json['needsConvertionToNewRoundCorners'] as bool, + edited: json['edited'] as bool, + isClosed: json['isClosed'] as bool, + pointRadiusBehaviour: json['pointRadiusBehaviour'], + points: json['points'] as List, + UUID: json['do_objectID'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['isVisible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + type: json['type'] as String, + maintainScrollPosition: json['maintainScrollPosition'], + pbdfType: json['pbdfType'], + ); + } + + @override + String UUID; + + @override + var boundaryRectangle; + + @override + bool isVisible; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + Future interpretNode(PBContext currentContext) { + Border border; + for (var b in style.borders.reversed) { + if (b.isEnabled) { + border = b; + } + } + return Future.value(InheritedContainer( + this, + Point(boundaryRectangle.x, boundaryRectangle.y), + Point(boundaryRectangle.x + boundaryRectangle.width, + boundaryRectangle.y + boundaryRectangle.height), + name, + currentContext: currentContext, + borderInfo: { + 'borderRadius': + style.borderOptions.isEnabled ? points[0]['cornerRadius'] : null, + 'borderColorHex': border != null ? toHex(border.color) : null, + 'borderThickness': border != null ? border.thickness : null + }, + )); + } + + @override + toJson() { + throw UnimplementedError(); + } + + @override + Map toPBDF() { + throw UnimplementedError(); + } +} diff --git a/lib/design_logic/star.dart b/lib/design_logic/star.dart new file mode 100644 index 00000000..eaeeb1e5 --- /dev/null +++ b/lib/design_logic/star.dart @@ -0,0 +1,119 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_star.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; + +import 'abstract_design_node_factory.dart'; + +class Star implements DesignNodeFactory, DesignNode { + @override + String pbdfType = 'star'; + + Star({ + bool edited, + bool isClosed, + pointRadiusBehaviour, + List points, + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + isFixedToViewport, + isFlippedHorizontal, + isFlippedVertical, + isLocked, + isVisible, + layerListExpandedType, + name, + nameIsFixed, + resizingConstraint, + resizingType, + rotation, + sharedStyleID, + shouldBreakMaskChain, + hasClippingMask, + clippingMaskMode, + userInfo, + maintainScrollPosition, + type, + pbdfType, + }); + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return Star( + edited: json['edited'] as bool, + isClosed: json['isClosed'] as bool, + pointRadiusBehaviour: json['pointRadiusBehaviour'], + points: json['points'] as List, + UUID: json['do_objectID'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'], + isFlippedHorizontal: json['isFlippedHorizontal'], + isFlippedVertical: json['isFlippedVertical'], + isLocked: json['isLocked'], + isVisible: json['visible'], + layerListExpandedType: json['layerListExpandedType'], + name: json['name'], + nameIsFixed: json['nameIsFixed'], + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: json['rotation'], + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'], + hasClippingMask: json['hasClippingMask'], + clippingMaskMode: json['clippingMaskMode'], + userInfo: json['userInfo'], + maintainScrollPosition: json['maintainScrollPosition'], + type: json['_class'] as String, + pbdfType: json['pbdfType'], + ); + } + + @override + String UUID; + + @override + var boundaryRectangle; + + @override + bool isVisible; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + Future interpretNode(PBContext currentContext) async { + var img = await AzureAssetService().downloadImage(UUID); + return Future.value( + InheritedStar(this, name, currentContext: currentContext, image: img)); + } + + @override + toJson() { + throw UnimplementedError(); + } + + @override + Map toPBDF() { + throw UnimplementedError(); + } +} diff --git a/lib/design_logic/text.dart b/lib/design_logic/text.dart index 6fb14757..9aab729a 100644 --- a/lib/design_logic/text.dart +++ b/lib/design_logic/text.dart @@ -1,7 +1,119 @@ import 'package:parabeac_core/design_logic/design_element.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_text.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/injected_container.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; +import 'package:uuid/uuid.dart'; -abstract class Text extends DesignElement { - Text(this.content) : super(); +import 'abstract_design_node_factory.dart'; + +class Text extends DesignElement implements DesignNodeFactory, DesignNode { + @override + var boundaryRectangle; + + @override + var UUID; + + var attributedString; + + var automaticallyDrawOnUnderlyingPath; + + var dontSynchroniseWithSymbol; + + var lineSpacingBehaviour; + + var textBehaviour; + + var glyphBounds; + + Text({ + this.UUID, + booleanOperation, + exportOptions, + Frame this.boundaryRectangle, + bool isFixedToViewport, + bool isFlippedHorizontal, + bool isFlippedVertical, + bool isLocked, + bool isVisible, + layerListExpandedType, + String name, + bool nameIsFixed, + resizingConstraint, + resizingType, + double rotation, + sharedStyleID, + bool shouldBreakMaskChain, + bool hasClippingMask, + int clippingMaskMode, + bool maintainScrollPosition, + this.attributedString, + this.automaticallyDrawOnUnderlyingPath, + this.dontSynchroniseWithSymbol, + this.lineSpacingBehaviour, + this.textBehaviour, + this.glyphBounds, + type, + pbdfType, + }); String content; + + @override + String pbdfType = 'text'; + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return Text( + UUID: json['id'] as String, + booleanOperation: json['booleanOperation'], + exportOptions: json['exportOptions'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + isFixedToViewport: json['isFixedToViewport'] as bool, + isFlippedHorizontal: json['isFlippedHorizontal'] as bool, + isFlippedVertical: json['isFlippedVertical'] as bool, + isLocked: json['isLocked'] as bool, + isVisible: json['visible'] as bool, + layerListExpandedType: json['layerListExpandedType'], + name: json['name'] as String, + nameIsFixed: json['nameIsFixed'] as bool, + resizingConstraint: json['resizingConstraint'], + resizingType: json['resizingType'], + rotation: (json['rotation'] as num)?.toDouble(), + sharedStyleID: json['sharedStyleID'], + shouldBreakMaskChain: json['shouldBreakMaskChain'] as bool, + hasClippingMask: json['hasClippingMask'] as bool, + clippingMaskMode: json['clippingMaskMode'] as int, + maintainScrollPosition: json['maintainScrollPosition'] as bool, + attributedString: json['attributedString'] as Map, + automaticallyDrawOnUnderlyingPath: + json['automaticallyDrawOnUnderlyingPath'] as bool, + dontSynchroniseWithSymbol: json['dontSynchroniseWithSymbol'] as bool, + lineSpacingBehaviour: json['lineSpacingBehaviour'], + textBehaviour: json['textBehaviour'], + glyphBounds: json['glyphBounds'], + type: json['type'] as String, + pbdfType: json['pbdfType'], + ); + } + + @override + Future interpretNode(PBContext currentContext) => + Future.value(InjectedContainer( + Point(boundaryRectangle.x + boundaryRectangle.width, + boundaryRectangle.y + boundaryRectangle.height), + Point(boundaryRectangle.x, boundaryRectangle.y), + name, + Uuid().v4(), + currentContext: currentContext, + )..addChild( + InheritedText(this, name, currentContext: currentContext), + )); } diff --git a/lib/design_logic/vector.dart b/lib/design_logic/vector.dart new file mode 100644 index 00000000..03a040ab --- /dev/null +++ b/lib/design_logic/vector.dart @@ -0,0 +1,120 @@ +import 'dart:io'; + +import 'package:parabeac_core/controllers/main_info.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/design_logic/pb_style.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; + +import 'abstract_design_node_factory.dart'; + +class Vector implements DesignNodeFactory, DesignNode { + @override + String pbdfType = 'vector'; + + var layoutAlign; + + var constraints; + + var size; + + var strokes; + + var strokeWeight; + + var strokeAlign; + + var styles; + + var fillsList; + + Vector({ + String name, + bool visible, + String type, + pluginData, + sharedPluginData, + this.layoutAlign, + this.constraints, + Frame this.boundaryRectangle, + this.size, + this.strokes, + this.strokeWeight, + this.strokeAlign, + this.styles, + this.fillsList, + String UUID, + pbdfType, + }); + + @override + DesignNode createDesignNode(Map json) => fromPBDF(json); + + DesignNode fromPBDF(Map json) { + return Vector( + name: json['name'] as String, + type: json['type'] as String, + pluginData: json['pluginData'], + sharedPluginData: json['sharedPluginData'], + layoutAlign: json['layoutAlign'] as String, + constraints: json['constraints'], + boundaryRectangle: json['absoluteBoundingBox'] == null + ? null + : Frame.fromJson(json['absoluteBoundingBox'] as Map), + size: json['size'], + strokes: json['strokes'], + strokeWeight: (json['strokeWeight'] as num)?.toDouble(), + strokeAlign: json['strokeAlign'] as String, + styles: json['styles'], + fillsList: json['fills'] as List, + UUID: json['id'] as String, + pbdfType: json['pbdfType'], + )..type = json['type'] as String; + } + + @override + String UUID; + + @override + bool isVisible; + + @override + String name; + + @override + String prototypeNodeUUID; + + @override + PBStyle style; + + @override + String type; + + @override + Future interpretNode(PBContext currentContext) async { + var img = await AzureAssetService().downloadImage(UUID); + + var file = + File('${MainInfo().outputPath}pngs/${UUID}.png'.replaceAll(':', '_')) + ..createSync(recursive: true); + file.writeAsBytesSync(img); + return Future.value( + InheritedBitmap(this, name, currentContext: currentContext)); + } + + @override + toJson() { + throw UnimplementedError(); + } + + @override + Map toPBDF() { + throw UnimplementedError(); + } + + @override + var boundaryRectangle; +} diff --git a/lib/eggs/injected_tab.dart b/lib/eggs/injected_tab.dart index 39a9acb6..e10c3dad 100644 --- a/lib/eggs/injected_tab.dart +++ b/lib/eggs/injected_tab.dart @@ -1,5 +1,6 @@ import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/generation/generators/attribute-helper/pb_generator_context.dart'; +import 'package:parabeac_core/generation/generators/pb_flutter_generator.dart'; import 'package:parabeac_core/generation/generators/pb_generator.dart'; import 'package:parabeac_core/generation/prototyping/pb_prototype_node.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_group_layer.dart'; @@ -13,8 +14,6 @@ import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; import 'package:uuid/uuid.dart'; class Tab extends PBEgg implements PBInjectedIntermediate { - PBContext currentContext; - PrototypeNode prototypeNode; Tab( diff --git a/lib/generation/flutter_project_builder/flutter_project_builder.dart b/lib/generation/flutter_project_builder/flutter_project_builder.dart index 4cb9a36b..c814cde9 100644 --- a/lib/generation/flutter_project_builder/flutter_project_builder.dart +++ b/lib/generation/flutter_project_builder/flutter_project_builder.dart @@ -7,11 +7,10 @@ import 'package:parabeac_core/generation/generators/value_objects/generation_con import 'package:parabeac_core/generation/generators/value_objects/generation_configuration/provider_generation_configuration.dart'; import 'package:parabeac_core/generation/generators/value_objects/generation_configuration/stateful_generation_configuration.dart'; import 'package:parabeac_core/generation/generators/writers/pb_page_writer.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_project.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_state_management_linker.dart'; import 'package:quick_log/quick_log.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; String pathToFlutterProject = '${MainInfo().outputPath}/temp/'; @@ -90,7 +89,7 @@ class FlutterProjectBuilder { if (MainInfo().figmaProjectID != null && MainInfo().figmaProjectID.isNotEmpty) { log.info('Processing remaining images...'); - await image_helper.processImageQueue(); + await FigmaAssetProcessor().processImageQueue(); } Process.runSync( diff --git a/lib/generation/generators/attribute-helper/pb_size_helper.dart b/lib/generation/generators/attribute-helper/pb_size_helper.dart index 258ccecb..9282dc53 100644 --- a/lib/generation/generators/attribute-helper/pb_size_helper.dart +++ b/lib/generation/generators/attribute-helper/pb_size_helper.dart @@ -20,9 +20,6 @@ class PBSizeHelper extends PBAttributesHelper { var body = source.size ?? {}; double height = body['height']; double width = body['width']; - var wString = 'width: '; - var hString = 'height: '; - //Add relative sizing if the widget has context var screenWidth = ((source.currentContext.screenTopLeftCorner.x) - (source.currentContext.screenBottomRightCorner.x)) diff --git a/lib/generation/generators/middleware/middleware.dart b/lib/generation/generators/middleware/middleware.dart index 9dc723d3..4dc6c300 100644 --- a/lib/generation/generators/middleware/middleware.dart +++ b/lib/generation/generators/middleware/middleware.dart @@ -15,7 +15,9 @@ abstract class Middleware { String getName(String name) { var index = name.indexOf('/'); // Remove everything after the /. So if the name is SignUpButton/Default, we end up with SignUpButton as the name we produce. - return name.replaceRange(index, name.length, '').pascalCase; + return index < 0 + ? name + : name.replaceRange(index, name.length, '').pascalCase; } Future applyMiddleware(PBIntermediateNode node) => diff --git a/lib/generation/generators/middleware/state_management/bloc_middleware.dart b/lib/generation/generators/middleware/state_management/bloc_middleware.dart index 380baa71..4467d506 100644 --- a/lib/generation/generators/middleware/state_management/bloc_middleware.dart +++ b/lib/generation/generators/middleware/state_management/bloc_middleware.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/generation/generators/pb_variable.dart'; import 'package:parabeac_core/generation/generators/value_objects/file_structure_strategy.dart/flutter_file_structure_strategy.dart'; import 'package:parabeac_core/generation/generators/value_objects/generator_adapter.dart'; import 'package:parabeac_core/generation/generators/value_objects/template_strategy/bloc_state_template_strategy.dart'; @@ -25,17 +26,23 @@ class BLoCMiddleware extends Middleware { /// Incase of SymbolInstance if (node is PBSharedInstanceIntermediateNode) { - var genericName = node.functionCallName + var generalStateName = node.functionCallName .substring(0, node.functionCallName.lastIndexOf('/')); - var variableName = node.functionCallName.snakeCase; - var generalName = genericName.snakeCase; + var importName = node.functionCallName.snakeCase; + var generalName = generalStateName.snakeCase; var parentDirectory = generalName + '_bloc'; + var globalVariableName = node.name.snakeCase; + managerData.addGlobalVariable(PBVariable(globalVariableName, 'var ', true, + '${generalStateName.pascalCase}Bloc()')); await managerData.replaceImport( - variableName, '${parentDirectory}/${generalName}_bloc.dart'); + importName, '${parentDirectory}/${generalName}_bloc.dart'); + + managerData.addToDispose('${globalVariableName}.close()'); node.generator = StringGeneratorAdapter(''' - BlocBuilder<${genericName.pascalCase}Bloc, ${genericName.pascalCase}State>( - builder: (context, state) => state.widget + BlocBuilder<${generalStateName.pascalCase}Bloc, ${generalStateName.pascalCase}State>( + cubit: ${globalVariableName}, + builder: (context, state) => state.widget ) '''); return node; diff --git a/lib/generation/generators/middleware/state_management/provider_middleware.dart b/lib/generation/generators/middleware/state_management/provider_middleware.dart index e09a7f29..c157e6e6 100644 --- a/lib/generation/generators/middleware/state_management/provider_middleware.dart +++ b/lib/generation/generators/middleware/state_management/provider_middleware.dart @@ -27,8 +27,11 @@ class ProviderMiddleware extends Middleware { .addDependencies(PACKAGE_NAME, PACKAGE_VERSION); managerData.addImport('package:provider/provider.dart'); watcherName = node.functionCallName.snakeCase; - var watcher = PBVariable(watcherName, 'final ', true, 'watch(context)'); + var watcher = PBVariable(watcherName, 'final ', true, + 'context.watch<${getName(node.functionCallName).pascalCase}>().defaultWidget'); managerData.addMethodVariable(watcher); + await managerData.replaceImport( + watcherName, 'models/${watcherName}.dart'); node.generator = StringGeneratorAdapter(watcherName); return node; } @@ -43,18 +46,24 @@ class ProviderMiddleware extends Middleware { stateBuffer.write(_generateProviderVariable(variationNode)); }); - var code = _generateProviderClass( - stateBuffer.toString(), watcherName, generationManager); - fileStrategy.writeProviderModelFile(code, node.name.snakeCase); + var code = _generateProviderClass(stateBuffer.toString(), watcherName, + generationManager, node.name.camelCase); + fileStrategy.writeProviderModelFile(code, getName(node.name).snakeCase); + + return node; } - String _generateProviderClass( - String states, String defaultStateName, PBGenerationManager manager) { + String _generateProviderClass(String states, String defaultStateName, + PBGenerationManager manager, String defaultWidgetName) { return ''' - import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; - class ${defaultStateName} extends ChangeNotifierProvider { + class ${defaultStateName} extends ChangeNotifier { ${states} + + Widget defaultWidget; + ${defaultStateName}(){ + defaultWidget = ${defaultWidgetName}; + } } '''; } diff --git a/lib/generation/generators/pb_flutter_generator.dart b/lib/generation/generators/pb_flutter_generator.dart index f411727b..92fbd078 100644 --- a/lib/generation/generators/pb_flutter_generator.dart +++ b/lib/generation/generators/pb_flutter_generator.dart @@ -81,6 +81,22 @@ class PBFlutterGenerator extends PBGenerationManager { return buffer.toString(); } + /// Generates the dispose method + String generateDispose() { + var buffer = StringBuffer(); + var it = data.toDispose; + while (it.moveNext()) { + buffer.write('${it.current};\n'); + } + return ''' + @override + void dispose() { + ${buffer.toString()} + super.dispose(); + } + '''; + } + @override String generate( PBIntermediateNode rootNode, diff --git a/lib/generation/generators/pb_generation_manager.dart b/lib/generation/generators/pb_generation_manager.dart index 72ce366b..8ecdf42d 100644 --- a/lib/generation/generators/pb_generation_manager.dart +++ b/lib/generation/generators/pb_generation_manager.dart @@ -29,4 +29,6 @@ abstract class PBGenerationManager { String generateGlobalVariables(); String generateConstructor(String name); + + String generateDispose(); } diff --git a/lib/generation/generators/symbols/pb_instancesym_gen.dart b/lib/generation/generators/symbols/pb_instancesym_gen.dart index 6ffddeb2..4c7a7693 100644 --- a/lib/generation/generators/symbols/pb_instancesym_gen.dart +++ b/lib/generation/generators/symbols/pb_instancesym_gen.dart @@ -21,8 +21,8 @@ class PBSymbolInstanceGenerator extends PBGenerator { if (source is PBSharedInstanceIntermediateNode) { var method_signature = source.functionCallName; if (method_signature == null) { - log.error(' Could not find master name on: $source'); - return 'Container(/** This Symbol was not found **/)'; + log.error(' Could not find master name on: $source'); + return 'Container(/** This Symbol was not found **/)'; } method_signature = PBInputFormatter.formatLabel(method_signature, destroy_digits: false, space_to_underscore: false, isTitle: false); diff --git a/lib/generation/generators/util/pb_generation_view_data.dart b/lib/generation/generators/util/pb_generation_view_data.dart index 87c422fb..ef65b354 100644 --- a/lib/generation/generators/util/pb_generation_view_data.dart +++ b/lib/generation/generators/util/pb_generation_view_data.dart @@ -6,10 +6,13 @@ class PBGenerationViewData { final Set _constructorVariables = {}; final Set _methodVariables = {}; final Set _imports = {}; + final Set _toDispose = {}; bool _isDataLocked = false; PBGenerationViewData(); + Iterator get toDispose => _toDispose.iterator; + Iterator get globalVariables => _globalVariables.iterator; Iterator get constructorVariables => @@ -34,6 +37,15 @@ class PBGenerationViewData { void lockData() => _isDataLocked = true; + void addToDispose(String dispose) { + if (!_isDataLocked && + dispose != null && + dispose.isNotEmpty && + !_toDispose.contains(dispose)) { + _toDispose.add(dispose); + } + } + void addImport(String import) { if (!_isDataLocked && import != null && import.isNotEmpty) { _imports.add(import); @@ -47,11 +59,20 @@ class PBGenerationViewData { } void addGlobalVariable(PBVariable variable) { - if (!_isDataLocked && variable != null) { + if (!_isDataLocked && variable != null && globalHas(variable)) { _globalVariables.add(variable); } } + bool globalHas(PBVariable variable) { + for (var v in _globalVariables) { + if (v.variableName == variable.variableName) { + return false; + } + } + return true; + } + void addAllGlobalVariable(Iterable variable) => _globalVariables.addAll(variable); @@ -78,25 +99,31 @@ class PBGenerationViewData { } Future replaceImport(String oldImport, String newImport) async { - var oldVersion = await removeImportThatContains(oldImport); - if (oldVersion == '') { - return null; + if (!_isDataLocked) { + var oldVersion = await removeImportThatContains(oldImport); + if (oldVersion == '') { + return null; + } + var tempList = oldVersion.split('/'); + tempList.removeLast(); + tempList.add(newImport); + var tempList2 = tempList; + _imports.add(await _makeImport(tempList2)); } - var tempList = oldVersion.split('/'); - tempList.removeLast(); - tempList.add(newImport); - var tempList2 = tempList; - _imports.add(await _makeImport(tempList2)); } Future _makeImport(List tempList) async { var tempString = tempList.removeAt(0); for (var item in tempList) { - tempString += '/${item}'; if (item == 'view') { - tempString += '/${tempList.removeLast()}'; + var tempLast = tempList.removeLast(); + if (!tempLast.contains('models')) { + tempString += '/${item}'; + } + tempString += '/${tempLast}'; break; } + tempString += '/${item}'; } return tempString; } diff --git a/lib/generation/generators/util/pb_input_formatter.dart b/lib/generation/generators/util/pb_input_formatter.dart index e151f69f..1986eb2b 100644 --- a/lib/generation/generators/util/pb_input_formatter.dart +++ b/lib/generation/generators/util/pb_input_formatter.dart @@ -20,7 +20,8 @@ class PBInputFormatter { return result; } - static String _removeFirstDigits(String str) => str.startsWith(RegExp(r'\d+')) - ? str.replaceFirstMapped(RegExp(r'\d+'), (e) => '') - : str; + static String _removeFirstDigits(String str) => + str.startsWith(RegExp(r'^[\d]+')) + ? str.replaceFirstMapped(RegExp(r'^[\d]+'), (e) => '') + : str; } diff --git a/lib/generation/generators/value_objects/file_structure_strategy.dart/pb_file_structure_strategy.dart b/lib/generation/generators/value_objects/file_structure_strategy.dart/pb_file_structure_strategy.dart index 73a379f4..c5bd4567 100644 --- a/lib/generation/generators/value_objects/file_structure_strategy.dart/pb_file_structure_strategy.dart +++ b/lib/generation/generators/value_objects/file_structure_strategy.dart/pb_file_structure_strategy.dart @@ -73,7 +73,7 @@ abstract class FileStructureStrategy { if (name != null) { var uuid = node is PBSharedMasterNode ? node.SYMBOL_ID : node.UUID; var path = node is PBSharedMasterNode - ? '${_viewDirectoryPath}${directory.name.snakeCase}/${name}.g.dart' + ? '${_viewDirectoryPath}${directory.name.snakeCase}/${name}.dart' // Removed .g : '${_screenDirectoryPath}${directory.name.snakeCase}/${name}.dart'; PBGenCache().addToCache(uuid, path); } else { @@ -90,7 +90,7 @@ abstract class FileStructureStrategy { if (args is String) { var path = args == 'SCREEN' ? '${_screenDirectoryPath}${fileName}.dart' - : '${_viewDirectoryPath}${fileName}.g.dart'; + : '${_viewDirectoryPath}${fileName}.dart'; // Removed .g pageWriter.write(code, path); } return Future.value(); diff --git a/lib/generation/generators/value_objects/file_structure_strategy.dart/provider_file_structure_strategy.dart b/lib/generation/generators/value_objects/file_structure_strategy.dart/provider_file_structure_strategy.dart index bd80d8ea..b65cd8ba 100644 --- a/lib/generation/generators/value_objects/file_structure_strategy.dart/provider_file_structure_strategy.dart +++ b/lib/generation/generators/value_objects/file_structure_strategy.dart/provider_file_structure_strategy.dart @@ -32,6 +32,8 @@ class ProviderFileStructureStrategy extends FileStructureStrategy { } void writeProviderModelFile(String code, String fileName) { - super.pageWriter.write(code, '${_modelsPath}${fileName}.g.dart'); + super + .pageWriter + .write(code, '${_modelsPath}${fileName}.dart'); // Removed .g } } diff --git a/lib/generation/generators/value_objects/generation_configuration/bloc_generation_configuration.dart b/lib/generation/generators/value_objects/generation_configuration/bloc_generation_configuration.dart index 2ac7c6bd..9e8b0898 100644 --- a/lib/generation/generators/value_objects/generation_configuration/bloc_generation_configuration.dart +++ b/lib/generation/generators/value_objects/generation_configuration/bloc_generation_configuration.dart @@ -10,7 +10,7 @@ class BLoCGenerationConfiguration extends GenerationConfiguration { Future setUpConfiguration() async { logger = Logger('BLoC'); logger.info( - '\nThanks for trying our state management configuration that is now in Beta!\nIf you run into any issues please feel free to post it in Github or in our Discord!\n'); + 'Thanks for trying our state management configuration that is now in Beta!\nIf you run into any issues please feel free to post it in Github or in our Discord!'); fileStructureStrategy = FlutterFileStructureStrategy( pbProject.projectAbsPath, pageWriter, pbProject); registerMiddleware(BLoCMiddleware(generationManager)); diff --git a/lib/generation/generators/value_objects/generation_configuration/pb_generation_configuration.dart b/lib/generation/generators/value_objects/generation_configuration/pb_generation_configuration.dart index 9f0244d9..ed2f8ac4 100644 --- a/lib/generation/generators/value_objects/generation_configuration/pb_generation_configuration.dart +++ b/lib/generation/generators/value_objects/generation_configuration/pb_generation_configuration.dart @@ -106,6 +106,11 @@ abstract class GenerationConfiguration { for (var tree in pbProject.forest) { _generationManager.data = tree.data; var fileName = tree.rootNode?.name?.snakeCase ?? 'no_name_found'; + if (tree.rootNode is InheritedScaffold && + (tree.rootNode as InheritedScaffold).isHomeScreen) { + _setMainScreen( + tree.rootNode, '${tree.name.snakeCase}/${fileName}.dart'); + } _commitImports(tree.rootNode, tree.name.snakeCase, fileName); await _iterateNode(tree.rootNode); @@ -133,7 +138,7 @@ abstract class GenerationConfiguration { var screenFilePath = '${pbProject.projectName}/lib/screens/${directoryName}/${fileName.snakeCase}.dart'; var viewFilePath = - '${pbProject.projectName}/lib/views/${directoryName}/${fileName.snakeCase}.g.dart'; + '${pbProject.projectName}/lib/views/${directoryName}/${fileName.snakeCase}.dart'; // Removed .g var imports = ImportHelper.findImports( node, node is InheritedScaffold ? screenFilePath : viewFilePath); imports.forEach((import) { @@ -148,6 +153,16 @@ abstract class GenerationConfiguration { } } + void _setMainScreen(InheritedScaffold node, String outputMain) { + var writer = _pageWriter; + if (writer is PBFlutterWriter) { + writer.writeMainScreenWithHome( + node.name, + fileStructureStrategy.GENERATED_PROJECT_PATH + 'lib/main.dart', + 'screens/${outputMain}'); + } + } + Future _generateNode(PBIntermediateNode node, String filename) async { if (node?.auxiliaryData?.stateGraph?.states?.isNotEmpty ?? false) { /// Since these nodes are being processed on the middlewares diff --git a/lib/generation/generators/value_objects/generation_configuration/provider_generation_configuration.dart b/lib/generation/generators/value_objects/generation_configuration/provider_generation_configuration.dart index 67c5c48a..a6c2f98a 100644 --- a/lib/generation/generators/value_objects/generation_configuration/provider_generation_configuration.dart +++ b/lib/generation/generators/value_objects/generation_configuration/provider_generation_configuration.dart @@ -10,7 +10,7 @@ class ProviderGenerationConfiguration extends GenerationConfiguration { Future setUpConfiguration() async { logger = Logger('Provider'); logger.info( - '\nThanks for trying our state management configuration that is now in Beta!\nIf you run into any issues please feel free to post it in Github or in our Discord!\n'); + 'Thanks for trying our state management configuration that is now in Beta!\nIf you run into any issues please feel free to post it in Github or in our Discord!'); fileStructureStrategy = ProviderFileStructureStrategy( pbProject.projectAbsPath, pageWriter, pbProject); registerMiddleware(ProviderMiddleware(generationManager)); diff --git a/lib/generation/generators/value_objects/template_strategy/stateful_template_strategy.dart b/lib/generation/generators/value_objects/template_strategy/stateful_template_strategy.dart index d2d6111a..626e482f 100644 --- a/lib/generation/generators/value_objects/template_strategy/stateful_template_strategy.dart +++ b/lib/generation/generators/value_objects/template_strategy/stateful_template_strategy.dart @@ -30,6 +30,10 @@ class _${widgetName} extends State<${widgetName}>{ ${manager.data.methodVariableStr} return ${returnStatement}; } -}'''; + + ${manager.generateDispose()} +} + +'''; } } diff --git a/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart b/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart index 64fc357d..4c875727 100644 --- a/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart +++ b/lib/generation/generators/visual-widgets/pb_bitmap_gen.dart @@ -2,6 +2,7 @@ import 'package:parabeac_core/generation/generators/attribute-helper/pb_generato import 'package:parabeac_core/generation/generators/attribute-helper/pb_size_helper.dart'; import 'package:parabeac_core/generation/generators/pb_generator.dart'; import 'package:parabeac_core/input/sketch/helper/symbol_node_mixin.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; diff --git a/lib/input/figma/entities/layers/boolean_operation.dart b/lib/input/figma/entities/layers/boolean_operation.dart index 98398320..618cb4c7 100644 --- a/lib/input/figma/entities/layers/boolean_operation.dart +++ b/lib/input/figma/entities/layers/boolean_operation.dart @@ -4,20 +4,18 @@ import 'package:parabeac_core/design_logic/image.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; import 'package:parabeac_core/input/figma/entities/style/figma_style.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; import 'package:quick_log/quick_log.dart'; import 'figma_node.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; part 'boolean_operation.g.dart'; @JsonSerializable(nullable: true) class BooleanOperation extends FigmaVector - with image_helper.PBImageHelperMixin implements FigmaNodeFactory, GroupNode, Image { @JsonKey(ignore: true) Logger log; @@ -43,6 +41,7 @@ class BooleanOperation extends FigmaVector UUID: UUID, ) { log = Logger(runtimeType.toString()); + pbdfType = 'boolean_operation'; } @override @@ -55,7 +54,7 @@ class BooleanOperation extends FigmaVector @override Future interpretNode(PBContext currentContext) async { - imageReference = addToImageQueue(UUID); + imageReference = FigmaAssetProcessor().processImage(UUID); return Future.value( InheritedBitmap(this, name, currentContext: currentContext)); @@ -63,4 +62,10 @@ class BooleanOperation extends FigmaVector @override String imageReference; + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'boolean_operation'; } diff --git a/lib/input/figma/entities/layers/boolean_operation.g.dart b/lib/input/figma/entities/layers/boolean_operation.g.dart index 3d264ee5..17247ab4 100644 --- a/lib/input/figma/entities/layers/boolean_operation.g.dart +++ b/lib/input/figma/entities/layers/boolean_operation.g.dart @@ -35,7 +35,8 @@ BooleanOperation _$BooleanOperationFromJson(Map json) { ..strokeAlign = json['strokeAlign'] as String ..styles = json['styles'] ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$BooleanOperationToJson(BooleanOperation instance) => @@ -60,4 +61,5 @@ Map _$BooleanOperationToJson(BooleanOperation instance) => 'type': instance.type, 'absoluteBoundingBox': instance.boundaryRectangle, 'imageReference': instance.imageReference, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/canvas.dart b/lib/input/figma/entities/layers/canvas.dart index 1de30300..47d95dbb 100644 --- a/lib/input/figma/entities/layers/canvas.dart +++ b/lib/input/figma/entities/layers/canvas.dart @@ -1,4 +1,5 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/group_node.dart'; import 'package:parabeac_core/input/figma/entities/layers/figma_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -20,7 +21,9 @@ class Canvas extends FigmaNode implements FigmaNodeFactory, GroupNode { this.prototypeStartNodeID, this.prototypeDevice, this.exportSettings, - }) : super(name, true, type, null, null); + }) : super(name, true, type, null, null) { + pbdfType = 'artboard'; + } // Last two nulls are used for Figma plugins @override @@ -60,4 +63,22 @@ class Canvas extends FigmaNode implements FigmaNodeFactory, GroupNode { assert(false, 'We don\'t product pages as Intermediate Nodes.'); return null; } + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'artboard'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/canvas.g.dart b/lib/input/figma/entities/layers/canvas.g.dart index 363307d5..5fdec3bc 100644 --- a/lib/input/figma/entities/layers/canvas.g.dart +++ b/lib/input/figma/entities/layers/canvas.g.dart @@ -24,7 +24,8 @@ Canvas _$CanvasFromJson(Map json) { ..sharedPluginData = json['sharedPluginData'] ..isVisible = json['visible'] as bool ?? true ..boundaryRectangle = json['boundaryRectangle'] - ..prototypeNodeUUID = json['prototypeNodeUUID'] as String; + ..prototypeNodeUUID = json['prototypeNodeUUID'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$CanvasToJson(Canvas instance) => { @@ -41,4 +42,5 @@ Map _$CanvasToJson(Canvas instance) => { 'exportSettings': instance.exportSettings, 'boundaryRectangle': instance.boundaryRectangle, 'prototypeNodeUUID': instance.prototypeNodeUUID, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/component.dart b/lib/input/figma/entities/layers/component.dart index fc81e2dd..dec71e84 100644 --- a/lib/input/figma/entities/layers/component.dart +++ b/lib/input/figma/entities/layers/component.dart @@ -1,4 +1,5 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/pb_shared_master_node.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/figma_node.dart'; @@ -68,10 +69,13 @@ class Component extends FigmaFrame flow: flow, children: children, backgroundColor: backgroundColor, - ); + ) { + pbdfType = 'symbol_master'; + } // make sure only store unique UUID overrides with Map - List overrideProperties; + @override + var overrideProperties; @override FigmaNode createFigmaNode(Map json) => @@ -122,4 +126,25 @@ class Component extends FigmaFrame @override String symbolID; + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'symbol_master'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } + + @override + var isFlowHome; } diff --git a/lib/input/figma/entities/layers/component.g.dart b/lib/input/figma/entities/layers/component.g.dart index 709e2885..9ece6314 100644 --- a/lib/input/figma/entities/layers/component.g.dart +++ b/lib/input/figma/entities/layers/component.g.dart @@ -44,7 +44,9 @@ Component _$ComponentFromJson(Map json) { ..UUID = json['id'] as String ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String + ..isFlowHome = json['isFlowHome']; } Map _$ComponentToJson(Component instance) => { @@ -73,4 +75,6 @@ Map _$ComponentToJson(Component instance) => { 'overrideProperties': instance.overrideProperties, 'overriadableProperties': instance.overriadableProperties, 'symbolID': instance.symbolID, + 'pbdfType': instance.pbdfType, + 'isFlowHome': instance.isFlowHome, }; diff --git a/lib/input/figma/entities/layers/ellipse.dart b/lib/input/figma/entities/layers/ellipse.dart index ea04393a..d13b8012 100644 --- a/lib/input/figma/entities/layers/ellipse.dart +++ b/lib/input/figma/entities/layers/ellipse.dart @@ -1,21 +1,20 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/image.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:quick_log/quick_log.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; import 'figma_node.dart'; part 'ellipse.g.dart'; @JsonSerializable(nullable: true) class FigmaEllipse extends FigmaVector - with image_helper.PBImageHelperMixin implements AbstractFigmaNodeFactory, Image { @override String imageReference; @@ -59,6 +58,7 @@ class FigmaEllipse extends FigmaVector strokeAlign: strokeAlign, styles: styles, ) { + pbdfType = 'oval'; log = Logger(runtimeType.toString()); } @@ -72,8 +72,26 @@ class FigmaEllipse extends FigmaVector @override Future interpretNode(PBContext currentContext) async { - imageReference = addToImageQueue(UUID); + imageReference = FigmaAssetProcessor().processImage(UUID); return Future.value( InheritedBitmap(this, name, currentContext: currentContext)); } + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'oval'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/ellipse.g.dart b/lib/input/figma/entities/layers/ellipse.g.dart index 4d830496..a5ff352a 100644 --- a/lib/input/figma/entities/layers/ellipse.g.dart +++ b/lib/input/figma/entities/layers/ellipse.g.dart @@ -28,7 +28,8 @@ FigmaEllipse _$FigmaEllipseFromJson(Map json) { ..isVisible = json['visible'] as bool ?? true ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaEllipseToJson(FigmaEllipse instance) => @@ -51,4 +52,5 @@ Map _$FigmaEllipseToJson(FigmaEllipse instance) => 'fills': instance.fillsList, 'imageReference': instance.imageReference, 'type': instance.type, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/frame.dart b/lib/input/figma/entities/layers/frame.dart index b1da284c..47818036 100644 --- a/lib/input/figma/entities/layers/frame.dart +++ b/lib/input/figma/entities/layers/frame.dart @@ -1,6 +1,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:parabeac_core/design_logic/artboard.dart'; import 'package:parabeac_core/design_logic/color.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/group_node.dart'; import 'package:parabeac_core/design_logic/image.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; @@ -13,9 +14,6 @@ import 'package:parabeac_core/interpret_and_optimize/entities/inherited_scaffold import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; -import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; part 'frame.g.dart'; @@ -100,7 +98,9 @@ class FigmaFrame extends FigmaNode pluginData, sharedPluginData, UUID: UUID, - ); + ) { + pbdfType = 'group'; + } @JsonKey(ignore: true) List points; @@ -161,4 +161,25 @@ class FigmaFrame extends FigmaNode @override String imageReference; + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'group'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } + + @override + var isFlowHome; } diff --git a/lib/input/figma/entities/layers/frame.g.dart b/lib/input/figma/entities/layers/frame.g.dart index db0f11c6..fbaa57e4 100644 --- a/lib/input/figma/entities/layers/frame.g.dart +++ b/lib/input/figma/entities/layers/frame.g.dart @@ -37,7 +37,9 @@ FigmaFrame _$FigmaFrameFromJson(Map json) { ) ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String + ..isFlowHome = json['isFlowHome']; } Map _$FigmaFrameToJson(FigmaFrame instance) => @@ -64,4 +66,6 @@ Map _$FigmaFrameToJson(FigmaFrame instance) => 'type': instance.type, 'fills': instance.fillsList, 'imageReference': instance.imageReference, + 'pbdfType': instance.pbdfType, + 'isFlowHome': instance.isFlowHome, }; diff --git a/lib/input/figma/entities/layers/group.dart b/lib/input/figma/entities/layers/group.dart index 62516fd2..afe2bf1b 100644 --- a/lib/input/figma/entities/layers/group.dart +++ b/lib/input/figma/entities/layers/group.dart @@ -1,4 +1,5 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/image.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/figma_node.dart'; @@ -6,8 +7,7 @@ import 'package:parabeac_core/input/figma/entities/layers/frame.dart'; import 'package:parabeac_core/input/figma/entities/layers/text.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; import 'package:parabeac_core/input/figma/entities/style/figma_color.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; @@ -24,9 +24,7 @@ part 'group.g.dart'; /// Class that represents a Figma Group. /// The reason this class implements Image is because Groups can hold multiple vectors /// which we need to convert into images. -class Group extends FigmaFrame - with image_helper.PBImageHelperMixin - implements AbstractFigmaNodeFactory, Image { +class Group extends FigmaFrame implements AbstractFigmaNodeFactory, Image { @JsonKey(ignore: true) Logger log; @override @@ -82,6 +80,11 @@ class Group extends FigmaFrame UUID: UUID, backgroundColor: backgroundColor, ) { + if (areAllVectors()) { + pbdfType = 'image'; + } else { + pbdfType = 'group'; + } log = Logger(runtimeType.toString()); } @@ -94,7 +97,12 @@ class Group extends FigmaFrame @override Future interpretNode(PBContext currentContext) async { if (areAllVectors()) { - imageReference = addToImageQueue(UUID); + imageReference = FigmaAssetProcessor().processImage(UUID); + + var tempPrototypeID = childrenHavePrototypeNode(); + if (tempPrototypeID != null) { + this.prototypeNodeUUID = tempPrototypeID; + } children.clear(); @@ -108,6 +116,9 @@ class Group extends FigmaFrame } bool areAllVectors() { + if (children == null) { + return false; + } for (var child in children) { if (child is! FigmaVector) { return false; @@ -118,4 +129,16 @@ class Group extends FigmaFrame } return true; } + + String childrenHavePrototypeNode() { + for (DesignNode child in children) { + if (child.prototypeNodeUUID != null) { + return child.prototypeNodeUUID; + } + } + return null; + } + + @override + String pbdfType = 'group'; } diff --git a/lib/input/figma/entities/layers/group.g.dart b/lib/input/figma/entities/layers/group.g.dart index a28f1b64..32bed318 100644 --- a/lib/input/figma/entities/layers/group.g.dart +++ b/lib/input/figma/entities/layers/group.g.dart @@ -37,7 +37,9 @@ Group _$GroupFromJson(Map json) { ) ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..isFlowHome = json['isFlowHome'] + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$GroupToJson(Group instance) => { @@ -61,6 +63,8 @@ Map _$GroupToJson(Group instance) => { 'itemSpacing': instance.itemSpacing, 'backgroundColor': instance.backgroundColor, 'fills': instance.fillsList, + 'isFlowHome': instance.isFlowHome, 'type': instance.type, 'imageReference': instance.imageReference, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/instance.dart b/lib/input/figma/entities/layers/instance.dart index e443917d..11064dac 100644 --- a/lib/input/figma/entities/layers/instance.dart +++ b/lib/input/figma/entities/layers/instance.dart @@ -4,8 +4,10 @@ import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.d import 'package:parabeac_core/input/figma/entities/layers/figma_node.dart'; import 'package:parabeac_core/input/figma/entities/layers/frame.dart'; import 'package:parabeac_core/input/figma/entities/style/figma_color.dart'; +import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; +import 'package:parabeac_core/input/sketch/entities/objects/override_value.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_instance.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -73,7 +75,9 @@ class Instance extends FigmaFrame flow: flow, children: children, backgroundColor: backgroundColor, - ); + ) { + pbdfType = 'symbol_instance'; + } String componentId; @@ -96,4 +100,33 @@ class Instance extends FigmaFrame ); return Future.value(sym); } + + @override + String pbdfType = 'symbol_instance'; + + @override + Map AddMasterSymbolName(String overrideName, List children) { + // TODO: implement AddMasterSymbolName + throw UnimplementedError(); + } + + @override + String FindName(String uuid, List children, Type type) { + // TODO: implement FindName + throw UnimplementedError(); + } + + @override + Map extractParameter(String overrideName) { + // TODO: implement extractParameter + throw UnimplementedError(); + } + + @override + // TODO: implement overrideValues + List get overrideValues => throw UnimplementedError(); + + @override + // TODO: implement typeToAbbreviation + Map get typeToAbbreviation => throw UnimplementedError(); } diff --git a/lib/input/figma/entities/layers/instance.g.dart b/lib/input/figma/entities/layers/instance.g.dart index cb9555dd..886f6ce5 100644 --- a/lib/input/figma/entities/layers/instance.g.dart +++ b/lib/input/figma/entities/layers/instance.g.dart @@ -40,7 +40,9 @@ Instance _$InstanceFromJson(Map json) { ..UUID = json['id'] as String ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..isFlowHome = json['isFlowHome'] + ..pbdfType = json['pbdfType'] as String; } Map _$InstanceToJson(Instance instance) => { @@ -64,9 +66,11 @@ Map _$InstanceToJson(Instance instance) => { 'backgroundColor': instance.backgroundColor, 'fills': instance.fillsList, 'imageReference': instance.imageReference, + 'isFlowHome': instance.isFlowHome, 'type': instance.type, 'parameters': instance.parameters, 'symbolID': instance.symbolID, 'children': instance.children, 'componentId': instance.componentId, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/line.dart b/lib/input/figma/entities/layers/line.dart index 1edcb3eb..d1e41105 100644 --- a/lib/input/figma/entities/layers/line.dart +++ b/lib/input/figma/entities/layers/line.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; @@ -44,7 +45,9 @@ class FigmaLine extends FigmaVector implements AbstractFigmaNodeFactory { strokeWeight: strokeWeight, strokeAlign: strokeAlign, styles: styles, - ); + ) { + pbdfType = 'image'; + } @override FigmaNode createFigmaNode(Map json) => @@ -59,4 +62,22 @@ class FigmaLine extends FigmaVector implements AbstractFigmaNodeFactory { // TODO: implement interpretNode throw UnimplementedError(); } + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'image'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/line.g.dart b/lib/input/figma/entities/layers/line.g.dart index 69f0f304..1ef913da 100644 --- a/lib/input/figma/entities/layers/line.g.dart +++ b/lib/input/figma/entities/layers/line.g.dart @@ -28,7 +28,8 @@ FigmaLine _$FigmaLineFromJson(Map json) { ..isVisible = json['visible'] as bool ?? true ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaLineToJson(FigmaLine instance) => { @@ -50,4 +51,5 @@ Map _$FigmaLineToJson(FigmaLine instance) => { 'fills': instance.fillsList, 'imageReference': instance.imageReference, 'type': instance.type, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/rectangle.dart b/lib/input/figma/entities/layers/rectangle.dart index ade34b29..59760be7 100644 --- a/lib/input/figma/entities/layers/rectangle.dart +++ b/lib/input/figma/entities/layers/rectangle.dart @@ -1,7 +1,9 @@ import 'package:parabeac_core/design_logic/color.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/pb_border.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/input/figma/helper/style_extractor.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; @@ -10,8 +12,6 @@ import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_inte import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:parabeac_core/interpret_and_optimize/value_objects/point.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; import 'figma_node.dart'; @@ -19,7 +19,7 @@ part 'rectangle.g.dart'; @JsonSerializable(nullable: true) class FigmaRectangle extends FigmaVector - with PBColorMixin, image_helper.PBImageHelperMixin + with PBColorMixin implements AbstractFigmaNodeFactory { @override String type = 'RECTANGLE'; @@ -58,7 +58,14 @@ class FigmaRectangle extends FigmaVector strokeAlign: strokeAlign, styles: styles, fillsList: fillsList, - ); + ) { + pbdfType = 'rectangle'; + var fillsMap = + (fillsList == null || fillsList.isEmpty) ? {} : fillsList.first; + if (fillsMap != null && fillsMap['type'] == 'IMAGE') { + pbdfType = 'image'; + } + } List points; double cornerRadius; @@ -82,7 +89,7 @@ class FigmaRectangle extends FigmaVector var fillsMap = (fillsList == null || fillsList.isEmpty) ? {} : fillsList.first; if (fillsMap != null && fillsMap['type'] == 'IMAGE') { - imageReference = addToImageQueue(UUID); + imageReference = FigmaAssetProcessor().processImage(UUID); return Future.value( InheritedBitmap(this, name, currentContext: currentContext)); @@ -112,4 +119,22 @@ class FigmaRectangle extends FigmaVector }, )); } + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'rectangle'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/rectangle.g.dart b/lib/input/figma/entities/layers/rectangle.g.dart index 42223b70..ecbf1b36 100644 --- a/lib/input/figma/entities/layers/rectangle.g.dart +++ b/lib/input/figma/entities/layers/rectangle.g.dart @@ -33,7 +33,8 @@ FigmaRectangle _$FigmaRectangleFromJson(Map json) { ) ..UUID = json['id'] as String ..prototypeNodeUUID = json['transitionNodeID'] as String - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaRectangleToJson(FigmaRectangle instance) => @@ -59,4 +60,5 @@ Map _$FigmaRectangleToJson(FigmaRectangle instance) => 'points': instance.points, 'cornerRadius': instance.cornerRadius, 'rectangleCornerRadii': instance.rectangleCornerRadii, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/regular_polygon.dart b/lib/input/figma/entities/layers/regular_polygon.dart index 9e40b05f..f0ccbdea 100644 --- a/lib/input/figma/entities/layers/regular_polygon.dart +++ b/lib/input/figma/entities/layers/regular_polygon.dart @@ -1,5 +1,7 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; @@ -46,7 +48,9 @@ class FigmaRegularPolygon extends FigmaVector strokeWeight: strokeWeight, strokeAlign: strokeAlign, styles: styles, - ); + ) { + pbdfType = 'polygon'; + } @override FigmaNode createFigmaNode(Map json) => @@ -58,7 +62,7 @@ class FigmaRegularPolygon extends FigmaVector @override Future interpretNode(PBContext currentContext) { - imageReference = addToImageQueue(UUID); + imageReference = FigmaAssetProcessor().processImage(UUID); return Future.value( InheritedBitmap(this, name, currentContext: currentContext)); @@ -66,4 +70,22 @@ class FigmaRegularPolygon extends FigmaVector @override String imageReference; + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'polygon'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/regular_polygon.g.dart b/lib/input/figma/entities/layers/regular_polygon.g.dart index cb30639f..e96673a3 100644 --- a/lib/input/figma/entities/layers/regular_polygon.g.dart +++ b/lib/input/figma/entities/layers/regular_polygon.g.dart @@ -28,7 +28,8 @@ FigmaRegularPolygon _$FigmaRegularPolygonFromJson(Map json) { ..isVisible = json['visible'] as bool ?? true ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaRegularPolygonToJson( @@ -50,6 +51,7 @@ Map _$FigmaRegularPolygonToJson( 'strokeAlign': instance.strokeAlign, 'styles': instance.styles, 'fills': instance.fillsList, - 'imageReference': instance.imageReference, 'type': instance.type, + 'imageReference': instance.imageReference, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/slice.dart b/lib/input/figma/entities/layers/slice.dart index 0112767d..58a3a159 100644 --- a/lib/input/figma/entities/layers/slice.dart +++ b/lib/input/figma/entities/layers/slice.dart @@ -50,7 +50,9 @@ class FigmaSlice extends FigmaNode implements FigmaNodeFactory { type, pluginData, sharedPluginData, - ); + ) { + pbdfType = 'image'; + } @override FigmaNode createFigmaNode(Map json) => @@ -77,4 +79,10 @@ class FigmaSlice extends FigmaNode implements FigmaNodeFactory { @override @JsonKey(ignore: true) var style; + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'image'; } diff --git a/lib/input/figma/entities/layers/slice.g.dart b/lib/input/figma/entities/layers/slice.g.dart index c4a72bdf..d2515266 100644 --- a/lib/input/figma/entities/layers/slice.g.dart +++ b/lib/input/figma/entities/layers/slice.g.dart @@ -21,7 +21,8 @@ FigmaSlice _$FigmaSliceFromJson(Map json) { ) ..UUID = json['id'] as String ..prototypeNodeUUID = json['transitionNodeID'] as String - ..isVisible = json['visible'] as bool ?? true; + ..isVisible = json['visible'] as bool ?? true + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaSliceToJson(FigmaSlice instance) => @@ -37,4 +38,5 @@ Map _$FigmaSliceToJson(FigmaSlice instance) => 'absoluteBoundingBox': instance.boundaryRectangle, 'size': instance.size, 'visible': instance.isVisible, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/star.dart b/lib/input/figma/entities/layers/star.dart index f24d55f7..762ea21e 100644 --- a/lib/input/figma/entities/layers/star.dart +++ b/lib/input/figma/entities/layers/star.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/vector.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; @@ -44,7 +45,9 @@ class FigmaStar extends FigmaVector implements AbstractFigmaNodeFactory { strokeWeight: strokeWeight, strokeAlign: strokeAlign, styles: styles, - ); + ) { + pbdfType = 'star'; + } @override FigmaNode createFigmaNode(Map json) => @@ -59,4 +62,22 @@ class FigmaStar extends FigmaVector implements AbstractFigmaNodeFactory { // TODO: implement interpretNode throw UnimplementedError(); } + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'star'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/star.g.dart b/lib/input/figma/entities/layers/star.g.dart index c47b932e..14f439ff 100644 --- a/lib/input/figma/entities/layers/star.g.dart +++ b/lib/input/figma/entities/layers/star.g.dart @@ -28,7 +28,8 @@ FigmaStar _$FigmaStarFromJson(Map json) { ..isVisible = json['visible'] as bool ?? true ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaStarToJson(FigmaStar instance) => { @@ -50,4 +51,5 @@ Map _$FigmaStarToJson(FigmaStar instance) => { 'fills': instance.fillsList, 'imageReference': instance.imageReference, 'type': instance.type, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/text.dart b/lib/input/figma/entities/layers/text.dart index 83e4938f..6e2b06d1 100644 --- a/lib/input/figma/entities/layers/text.dart +++ b/lib/input/figma/entities/layers/text.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/pb_style.dart'; import 'package:parabeac_core/design_logic/text.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; @@ -54,7 +55,9 @@ class FigmaText extends FigmaVector implements AbstractFigmaNodeFactory, Text { strokeWeight: strokeWeight, strokeAlign: strokeAlign, styles: styles, - ); + ) { + pbdfType = 'text'; + } @override @JsonKey(name: 'characters') @@ -93,4 +96,40 @@ class FigmaText extends FigmaVector implements AbstractFigmaNodeFactory, Text { InheritedText(this, name, currentContext: currentContext), )); } + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'text'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } + + @override + var attributedString; + + @override + var automaticallyDrawOnUnderlyingPath; + + @override + var dontSynchroniseWithSymbol; + + @override + var glyphBounds; + + @override + var lineSpacingBehaviour; + + @override + var textBehaviour; } diff --git a/lib/input/figma/entities/layers/text.g.dart b/lib/input/figma/entities/layers/text.g.dart index 01986fd2..e814e2e7 100644 --- a/lib/input/figma/entities/layers/text.g.dart +++ b/lib/input/figma/entities/layers/text.g.dart @@ -35,7 +35,8 @@ FigmaText _$FigmaTextFromJson(Map json) { ..isVisible = json['visible'] as bool ?? true ..prototypeNodeUUID = json['transitionNodeID'] as String ..fillsList = json['fills'] as List - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaTextToJson(FigmaText instance) => { @@ -60,4 +61,5 @@ Map _$FigmaTextToJson(FigmaText instance) => { 'style': instance.style, 'characterStyleOverrides': instance.characterStyleOverrides, 'styleOverrideTable': instance.styleOverrideTable, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/entities/layers/vector.dart b/lib/input/figma/entities/layers/vector.dart index 4337d287..dbeb3502 100644 --- a/lib/input/figma/entities/layers/vector.dart +++ b/lib/input/figma/entities/layers/vector.dart @@ -1,23 +1,22 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/image.dart'; import 'package:parabeac_core/design_logic/pb_style.dart'; import 'package:parabeac_core/input/figma/entities/abstract_figma_node_factory.dart'; import 'package:parabeac_core/input/figma/entities/layers/figma_node.dart'; import 'package:parabeac_core/input/figma/entities/style/figma_style.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_bitmap.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart' - as image_helper; + import 'package:quick_log/quick_log.dart'; part 'vector.g.dart'; @JsonSerializable(nullable: true) -class FigmaVector extends FigmaNode - with image_helper.PBImageHelperMixin - implements FigmaNodeFactory, Image { +class FigmaVector extends FigmaNode implements FigmaNodeFactory, Image { @JsonKey(ignore: true) Logger log; @override @@ -75,6 +74,7 @@ class FigmaVector extends FigmaNode sharedPluginData, UUID: UUID, ) { + pbdfType = 'vector'; log = Logger(runtimeType.toString()); } @@ -88,11 +88,30 @@ class FigmaVector extends FigmaNode @override Future interpretNode(PBContext currentContext) async { - imageReference = addToImageQueue(UUID); + imageReference = FigmaAssetProcessor().processImage(UUID); - return Future.value(InheritedBitmap(this, name, currentContext: currentContext)); + return Future.value( + InheritedBitmap(this, name, currentContext: currentContext)); } @override String imageReference; + + @override + Map toPBDF() => toJson(); + + @override + String pbdfType = 'vector'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/figma/entities/layers/vector.g.dart b/lib/input/figma/entities/layers/vector.g.dart index f3469c91..4882a58f 100644 --- a/lib/input/figma/entities/layers/vector.g.dart +++ b/lib/input/figma/entities/layers/vector.g.dart @@ -30,7 +30,8 @@ FigmaVector _$FigmaVectorFromJson(Map json) { ) ..isVisible = json['visible'] as bool ?? true ..prototypeNodeUUID = json['transitionNodeID'] as String - ..imageReference = json['imageReference'] as String; + ..imageReference = json['imageReference'] as String + ..pbdfType = json['pbdfType'] as String; } Map _$FigmaVectorToJson(FigmaVector instance) => @@ -53,4 +54,5 @@ Map _$FigmaVectorToJson(FigmaVector instance) => 'type': instance.type, 'fills': instance.fillsList, 'imageReference': instance.imageReference, + 'pbdfType': instance.pbdfType, }; diff --git a/lib/input/figma/helper/figma_asset_processor.dart b/lib/input/figma/helper/figma_asset_processor.dart new file mode 100644 index 00000000..12e9a32a --- /dev/null +++ b/lib/input/figma/helper/figma_asset_processor.dart @@ -0,0 +1,113 @@ +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:parabeac_core/APICaller/api_call_service.dart'; +import 'package:parabeac_core/controllers/main_info.dart'; +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; +import 'package:quick_log/quick_log.dart'; + +class FigmaAssetProcessor extends AssetProcessingService { + FigmaAssetProcessor._internal(); + + static final FigmaAssetProcessor _instance = FigmaAssetProcessor._internal(); + + factory FigmaAssetProcessor() => _instance; + + final List _uuidQueue = []; + + List get uuidQueue => _uuidQueue; + + Logger log = Logger('Figma Image helper'); + + String _getImageName(String uuid) => + ('images/' + uuid + '.png').replaceAll(':', '_'); + + /// Adds [uuid] to queue to be processed as an image. + /// Returns the formatted name of the image reference. + @override + String processImage(String uuid) { + _uuidQueue.add(uuid); + return _getImageName(uuid); + } + + /// Adds [uuids] to queue to be processed as an image. + /// Does NOT return image names when finished. + void _addImagesToQueue(List uuids) => _uuidQueue.addAll(uuids); + + /// Creates separate API requests from `uuidQueue` to speed up + /// the image downloading process. + Future processImageQueue({bool writeAsFile = true}) async { + List> uuidLists; + if (_uuidQueue.length >= 8) { + // Split uuids into 8 lists to create separate API requests to figma + uuidLists = List.generate(8, (_) => []); + for (var i = 0; i < _uuidQueue.length; i++) { + uuidLists[i % 8].add(_uuidQueue[i]); + } + } else { + uuidLists = [_uuidQueue]; + } + + // Process images in separate queues + var futures = []; + for (var uuidList in uuidLists) { + futures.add(_processImages(uuidList, writeAsFile: writeAsFile)); + } + + // Wait for the images to complete writing process + await Future.wait(futures, eagerError: true); + } + + /// Downloads the image with the given `UUID` + /// and writes it to the `pngs` folder in the `outputPath`. + /// Returns true if the operation was successful. Returns false + /// otherwise. + Future _processImages(List uuids, + {bool writeAsFile = true}) async { + // Call Figma API to get Image link + return Future(() async { + var response = await APICallService.makeAPICall( + 'https://api.figma.com/v1/images/${MainInfo().figmaProjectID}?ids=${uuids.join(',')}', + MainInfo().figmaKey); + + if (response != null && + response.containsKey('images') && + response['images'] != null && + response['images'].values.isNotEmpty) { + Map images = response['images']; + // Download the images + for (var entry in images.entries) { + if (entry?.value != null && entry?.value?.isNotEmpty) { + response = await http.get(entry.value).then((imageRes) async { + // Check if the request was successful + if (imageRes == null || imageRes.statusCode != 200) { + log.error('Image ${entry.key} was not processed correctly'); + } + + if (writeAsFile) { + var file = File('${MainInfo().outputPath}pngs/${entry.key}.png' + .replaceAll(':', '_')) + ..createSync(recursive: true); + file.writeAsBytesSync(imageRes.bodyBytes); + } else { + await super.uploadToStorage(imageRes.bodyBytes, entry.key); + } + // TODO: Only print out when verbose flag is active + // log.debug('File written to following path ${file.path}'); + }).catchError((e) { + MainInfo().sentry.captureException(exception: e); + log.error(e.toString()); + }); + } + } + return response; + } + }); + } + + @override + Future processRootElements(Map uuids) async { + _addImagesToQueue(uuids.keys.toList()); + await processImageQueue(writeAsFile: false); + } +} diff --git a/lib/input/figma/helper/figma_page.dart b/lib/input/figma/helper/figma_page.dart index 345d06b0..9a51ff0e 100644 --- a/lib/input/figma/helper/figma_page.dart +++ b/lib/input/figma/helper/figma_page.dart @@ -1,8 +1,12 @@ -import 'package:parabeac_core/input/helper/page.dart'; +import 'package:parabeac_core/input/helper/design_page.dart'; import 'package:quick_log/quick_log.dart'; -class FigmaPage extends Page { +class FigmaPage extends DesignPage { @override - var log = Logger('Figma'); - FigmaPage(String name) : super(name); + var log = Logger('FigmaPage'); + FigmaPage(String name, String id) + : super( + name: name, + id: id, + ); } diff --git a/lib/input/figma/helper/figma_page_item.dart b/lib/input/figma/helper/figma_page_item.dart deleted file mode 100644 index eba9a29a..00000000 --- a/lib/input/figma/helper/figma_page_item.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:parabeac_core/design_logic/design_node.dart'; -import 'package:parabeac_core/input/helper/page.dart'; -import 'package:parabeac_core/input/helper/page_item.dart'; - -class FigmaPageItem extends PageItem { - FigmaPageItem(DesignNode root, Page parentPage) : super(root, parentPage); -} diff --git a/lib/input/figma/helper/figma_node_tree.dart b/lib/input/figma/helper/figma_project.dart similarity index 63% rename from lib/input/figma/helper/figma_node_tree.dart rename to lib/input/figma/helper/figma_project.dart index 49f7edf7..ea61e8e9 100644 --- a/lib/input/figma/helper/figma_node_tree.dart +++ b/lib/input/figma/helper/figma_project.dart @@ -1,16 +1,16 @@ import 'package:parabeac_core/input/figma/entities/layers/canvas.dart'; import 'package:parabeac_core/input/figma/helper/figma_page.dart'; -import 'package:parabeac_core/input/helper/node_tree.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; import 'package:quick_log/src/logger.dart'; -import 'figma_page_item.dart'; +import 'figma_screen.dart'; -class FigmaNodeTree extends NodeTree { +class FigmaProject extends DesignProject { @override bool debug; @override - Logger log = Logger('FigmaNodeTree'); + Logger log = Logger('FigmaProject'); @override String projectName; @@ -19,19 +19,23 @@ class FigmaNodeTree extends NodeTree { FigmaPage rootScreen; - FigmaNodeTree(this.projectName, this.figmaJson) { + FigmaProject(this.projectName, this.figmaJson) { pages.addAll(_setConventionalPages(figmaJson['document']['children'])); } List _setConventionalPages(var canvasAndArtboards) { var figmaPages = []; for (var canvas in canvasAndArtboards) { - var pg = FigmaPage(canvas['name']); + var pg = FigmaPage(canvas['name'], canvas['id']); var node = Canvas.fromJson(canvas); for (var layer in node.children) { - pg.addPageItem(FigmaPageItem(layer, pg)); + pg.addScreen(FigmaScreen( + layer, + layer.UUID, + layer.name, + )); } figmaPages.add(pg); } diff --git a/lib/input/figma/helper/figma_screen.dart b/lib/input/figma/helper/figma_screen.dart new file mode 100644 index 00000000..034be25a --- /dev/null +++ b/lib/input/figma/helper/figma_screen.dart @@ -0,0 +1,15 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/helper/design_page.dart'; +import 'package:parabeac_core/input/helper/design_screen.dart'; + +class FigmaScreen extends DesignScreen { + FigmaScreen( + DesignNode root, + String id, + String name, + ) : super( + designNode: root, + id: id, + name: name, + ); +} diff --git a/lib/input/figma/helper/image_helper.dart b/lib/input/figma/helper/image_helper.dart deleted file mode 100644 index fe94c86a..00000000 --- a/lib/input/figma/helper/image_helper.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'dart:io'; - -import 'package:http/http.dart' as http; -import 'package:parabeac_core/APICaller/api_call_service.dart'; -import 'package:parabeac_core/controllers/main_info.dart'; -import 'package:quick_log/quick_log.dart'; - -List uuidQueue = []; - -Logger log = Logger('Figma Image helper'); - -/// Downloads the image with the given `UUID` -/// and writes it to the `pngs` folder in the `outputPath`. -/// Returns true if the operation was successful. Returns false -/// otherwise. -Future _processImages(List uuids) async { - // Call Figma API to get Image link - return Future(() async { - var response = await APICallService.makeAPICall( - 'https://api.figma.com/v1/images/${MainInfo().figmaProjectID}?ids=${uuids.join(',')}', - MainInfo().figmaKey); - - if (response != null && - response.containsKey('images') && - response['images'] != null && - response['images'].values.isNotEmpty) { - Map images = response['images']; - // Download the images - for (var entry in images.entries) { - if (entry?.value != null && entry?.value.isNotEmpty) { - response = await http.get(entry.value).then((imageRes) { - // Check if the request was successful - if (imageRes == null || imageRes.statusCode != 200) { - log.error('Image ${entry.key} was not processed correctly'); - } - - var file = File('${MainInfo().outputPath}pngs/${entry.key}.png' - .replaceAll(':', '_')) - ..createSync(recursive: true); - file.writeAsBytesSync(imageRes.bodyBytes); - // TODO: Only print out when verbose flag is active - // log.debug('File written to following path ${file.path}'); - }).catchError((e) => log.error(e.toString())); - } - } - return response; - } - }); - // TODO: Investigate API call for when values.first == null -} - -/// Creates separate API requests from `uuidQueue` to speed up -/// the image downloading process. -Future processImageQueue() async { - List> uuidLists; - if (uuidQueue.length >= 8) { - // Split uuids into 8 lists to create separate API requests to figma - uuidLists = List.generate(8, (_) => []); - for (var i = 0; i < uuidQueue.length; i++) { - uuidLists[i % 8].add(uuidQueue[i]); - } - } else { - uuidLists = [uuidQueue]; - } - - // Process images in separate queues - List futures = []; - for (var uuidList in uuidLists) { - futures.add(_processImages(uuidList)); - } - - // Wait for the images to complete writing process - await Future.wait(futures, eagerError: true); -} - -mixin PBImageHelperMixin { - /// Adds [uuid] to queue to be processed as an image. - /// Returns the formatted name of the image reference. - String addToImageQueue(String uuid) { - uuidQueue.add(uuid); - return ('images/' + uuid + '.png').replaceAll(':', '_'); - } -} diff --git a/lib/input/helper/asset_processing_service.dart b/lib/input/helper/asset_processing_service.dart new file mode 100644 index 00000000..4851ea90 --- /dev/null +++ b/lib/input/helper/asset_processing_service.dart @@ -0,0 +1,31 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; + +abstract class AssetProcessingService { + dynamic processImage(String uuid); + + Future processRootElements(Map uuids); + + AzureAssetService aaService = AzureAssetService(); + + Future uploadToStorage(Uint8List img, String name) async { + if (Platform.environment.containsKey(AzureAssetService.KEY_NAME) && + aaService.projectUUID != null) { + // Upload image to storage + + var cont = await aaService.createContainer( + aaService.projectUUID, + img, + ); + var blob = await aaService.putBlob( + aaService.projectUUID, + '${name}.png', + img, + ); + await cont.stream.drain(); + await blob.stream.drain(); + } + } +} diff --git a/lib/input/helper/azure_asset_service.dart b/lib/input/helper/azure_asset_service.dart new file mode 100644 index 00000000..805bde33 --- /dev/null +++ b/lib/input/helper/azure_asset_service.dart @@ -0,0 +1,78 @@ +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:http/http.dart' as http; +import 'package:azblob/azblob.dart'; + +class AzureAssetService { + AzureAssetService._internal(); + + static final AzureAssetService _instance = AzureAssetService._internal(); + + factory AzureAssetService() => _instance; + + String _projectUUID; + + set projectUUID(String UUID) => _projectUUID = UUID; + + String get projectUUID => _projectUUID.toLowerCase(); + + static const KEY_NAME = 'STORAGE_CONNECTION_STRING'; + + String getImageURI(String imageName) => getContainerUri() + '/${imageName}'; + + String getContainerUri() { + if (Platform.environment.containsKey(KEY_NAME) && projectUUID != null) { + var storageStringList = Platform.environment[KEY_NAME].split(';'); + var protocol = storageStringList[0].split('=')[1]; + var accName = storageStringList[1].split('=')[1]; + var suffix = storageStringList.last.split('=')[1]; + return '${protocol}://${accName}.blob.${suffix}/${projectUUID}'; + } + return ''; + } + + Future _putRequestBlob( + String path, Uint8List bodyBytes, + {Map queryParams}) async { + var storage = AzureStorage.parse(Platform.environment[KEY_NAME]); + var uri, headers; + // Request + if (queryParams == null) { + uri = storage.uri(path: '${path}'); + headers = {'x-ms-blob-type': 'BlockBlob'}; + } else { + uri = storage.uri(path: '${path}', queryParameters: queryParams); + } + + var request = http.Request('PUT', uri); + if (headers != null) { + request.headers.addAll(headers); + } + request.bodyBytes = bodyBytes; + storage.sign(request); + + var res = await request.send(); + return res; + } + + Future createContainer( + String container, Uint8List bodyBytes) async => + await _putRequestBlob('/${container}', bodyBytes, + queryParams: {'restype': 'container'}); + + Future putBlob( + String container, String filename, Uint8List bodyBytes) async => + await _putRequestBlob('/${container}/${filename}', bodyBytes); + + Future downloadImage(String uuid) async { + var storage = AzureStorage.parse(Platform.environment[KEY_NAME]); + var uri = storage.uri(path: '/${projectUUID}/${uuid}.png'); + + var request = http.Request('GET', uri); + storage.sign(request); + + var res = await request.send(); + return await res.stream.toBytes(); + } +} diff --git a/lib/input/helper/design_page.dart b/lib/input/helper/design_page.dart new file mode 100644 index 00000000..050e13b1 --- /dev/null +++ b/lib/input/helper/design_page.dart @@ -0,0 +1,67 @@ +import 'package:parabeac_core/design_logic/abstract_design_node_factory.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:quick_log/quick_log.dart'; +import 'design_screen.dart'; + +import 'map_mixin.dart'; + +class DesignPage with MapMixin implements DesignNodeFactory { + var log = Logger('DesignPage'); + + String id; + String imageURI; + String name; + bool convert; + List screens = []; + + DesignPage({ + this.name, + this.id, + }) { + screens = []; + } + + void addScreen(DesignScreen item) { + screens.add(item); + } + + List getPageItems() { + log.info('We encountered a page that has ${screens.length} page items.'); + return screens; + } + + /// Parabeac Design File + Map toPBDF() { + Map result = {}; + result['pbdfType'] = pbdfType; + result['id'] = id; + result['name'] = name; + result['convert'] = convert; + for (var screen in screens) { + addToMap('screens', result, {screen.name: screen.toPBDF()}); + } + return result; + } + + @override + String pbdfType = 'design_page'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + factory DesignPage.fromPBDF(Map json) { + var page = DesignPage(name: json['name'], id: json['id']); + if (json.containsKey('screens')) { + (json['screens'] as Map)?.forEach((key, value) { + if (value != null) { + page.screens + .add(DesignScreen.fromPBDF(value as Map)); + } + }); + } + return page; + } +} diff --git a/lib/input/helper/design_project.dart b/lib/input/helper/design_project.dart new file mode 100644 index 00000000..2e4ba69a --- /dev/null +++ b/lib/input/helper/design_project.dart @@ -0,0 +1,63 @@ +import 'dart:convert'; + +import 'package:parabeac_core/design_logic/abstract_design_node_factory.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/helper/design_page.dart'; +import 'package:parabeac_core/input/helper/map_mixin.dart'; +import 'package:parabeac_core/input/sketch/entities/style/shared_style.dart'; + +class DesignProject with MapMixin implements DesignNodeFactory { + String projectName; + bool debug = false; + String id; + @override + String pbdfType = 'project'; + + DesignProject({ + this.projectName, + this.id, + }); + + List pages = []; + List miscPages = []; + List sharedStyles = []; + + /// Parabeac Design File + Map toPBDF() { + Map result = {}; + result['projectName'] = projectName; + result['pbdfType'] = pbdfType; + result['id'] = id; + for (var page in pages) { + addToMap('pages', result, {page.name: page.toPBDF()}); + } + for (var page in miscPages) { + addToMap('miscPages', result, {page.name: page.toPBDF()}); + } + + for (var sharedStyle in sharedStyles) { + result.addAll(sharedStyle.toJson()); + } + + return result; + } + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + factory DesignProject.fromPBDF(Map json) { + var project = + DesignProject(projectName: json['projectName'], id: json['id']); + if (json.containsKey('pages')) { + (json['pages'] as Map)?.forEach((key, value) { + if (value != null) { + project.pages.add(DesignPage.fromPBDF(value as Map)); + } + }); + } + return project; + } +} diff --git a/lib/input/helper/design_screen.dart b/lib/input/helper/design_screen.dart new file mode 100644 index 00000000..4ea460f2 --- /dev/null +++ b/lib/input/helper/design_screen.dart @@ -0,0 +1,56 @@ +import 'package:parabeac_core/design_logic/abstract_design_node_factory.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; + +class DesignScreen implements DesignNodeFactory { + String id; + String name; + bool convert; + String imageURI; + String type; + DesignNode designNode; + + // Do we still need this? + // DesignPage parentPage; + + DesignScreen({ + DesignNode designNode, + this.id, + this.name, + }) { + this.designNode = designNode; + } + + Map toPBDF() { + var result = {}; + result['pbdfType'] = pbdfType; + result['id'] = id; + result['name'] = name; + result['convert'] = convert; + result['type'] = type; + result['designNode'] = designNode.toPBDF(); + result['azure_blob_uri'] = imageURI; + return result; + } + + @override + String pbdfType = 'screen'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + factory DesignScreen.fromPBDF(Map json) { + var screen = DesignScreen(name: json['name'], id: json['id']); + if (json.containsKey('designNode')) { + screen.designNode = DesignNode.fromPBDF(json['designNode']); + } + return screen; + } + Map toJson() { + var result = {'azure_blob_uri': imageURI}; + result.addAll(designNode.toJson()); + return result; + } +} diff --git a/lib/input/helper/map_mixin.dart b/lib/input/helper/map_mixin.dart new file mode 100644 index 00000000..6a1ab881 --- /dev/null +++ b/lib/input/helper/map_mixin.dart @@ -0,0 +1,9 @@ +mixin MapMixin { + void addToMap(String key, Map destinationMap, Map source) { + if (destinationMap.containsKey(key)) { + destinationMap[key].addAll(source); + } else { + destinationMap[key] = source; + } + } +} diff --git a/lib/input/helper/node_tree.dart b/lib/input/helper/node_tree.dart deleted file mode 100644 index 16fc5be6..00000000 --- a/lib/input/helper/node_tree.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:parabeac_core/input/helper/page.dart'; -import 'package:parabeac_core/input/sketch/entities/style/shared_style.dart'; -import 'package:quick_log/quick_log.dart'; - -abstract class NodeTree { - var log = Logger('NodeTree'); - String projectName; - bool debug = false; - - List pages = []; - List miscPages = []; - List sharedStyles = []; - - Map toJson() { - var result = {}; - result['projectName'] = projectName; - for (var page in pages) { - result.addAll(page.toJson()); - } - for (var page in miscPages) { - result.addAll(page.toJson()); - } - - for (var sharedStyle in sharedStyles) { - result.addAll(sharedStyle.toJson()); - } - - return result; - } -} diff --git a/lib/input/helper/page.dart b/lib/input/helper/page.dart deleted file mode 100644 index 94bdbc0c..00000000 --- a/lib/input/helper/page.dart +++ /dev/null @@ -1,33 +0,0 @@ -import 'package:parabeac_core/input/helper/page_item.dart'; -import 'package:quick_log/quick_log.dart'; - -class Page { - var log = Logger('Sketch'); - - String name; - List _pageItems = []; - - Page( - this.name, - ) { - _pageItems = []; - } - - void addPageItem(PageItem item) { - _pageItems.add(item); - } - - List getPageItems() { - log.info('We encountered a page that has ${_pageItems.length} page items.'); - return _pageItems; - } - - Map toJson() { - Map result = {}; - result['name'] = name; - for (var item in _pageItems) { - result.addAll(item.root.toJson()); - } - return result; - } -} diff --git a/lib/input/helper/page_item.dart b/lib/input/helper/page_item.dart deleted file mode 100644 index ffa68a00..00000000 --- a/lib/input/helper/page_item.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:parabeac_core/design_logic/design_node.dart'; -import 'package:parabeac_core/input/helper/page.dart'; - -class PageItem { - DesignNode root; - Page parentPage; - PageItem(this.root, this.parentPage); - - Map toJson() => root.toJson(); -} diff --git a/lib/input/sketch/entities/layers/abstract_group_layer.dart b/lib/input/sketch/entities/layers/abstract_group_layer.dart index b1b4476d..1003ab31 100644 --- a/lib/input/sketch/entities/layers/abstract_group_layer.dart +++ b/lib/input/sketch/entities/layers/abstract_group_layer.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/group_node.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; @@ -64,4 +65,12 @@ abstract class AbstractGroupLayer extends SketchNode implements GroupNode { @override Map toJson(); + + Map getChildren() { + Map result = {}; + for (var child in children) { + result.addAll((child as DesignNode).toPBDF()); + } + return result; + } } diff --git a/lib/input/sketch/entities/layers/artboard.dart b/lib/input/sketch/entities/layers/artboard.dart index bda323f1..cae7d35b 100644 --- a/lib/input/sketch/entities/layers/artboard.dart +++ b/lib/input/sketch/entities/layers/artboard.dart @@ -1,5 +1,6 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:parabeac_core/design_logic/artboard.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_group_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; @@ -149,4 +150,71 @@ class Artboard extends AbstractGroupLayer isHomeScreen: isFlowHome, )); } + + @override + Map toPBDF() => { + // Change _class for type and layers for children and do_objectID for id + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'hasClickThrough': hasClickThrough, + 'groupLayout': groupLayout, + 'children': getChildren(), // changed it was layers + 'CLASS_NAME': CLASS_NAME, + 'type': type, // changed it was _class + 'includeInCloudUpload': includeInCloudUpload, + 'includeBackgroundColorInExport': includeBackgroundColorInExport, + 'horizontalRulerData': horizontalRulerData, + 'verticalRulerData': verticalRulerData, + 'layout': layout, + 'grid': grid, + 'absoluteBoundingBox': boundaryRectangle, // changed it was frame + 'backgroundColor': backgroundColor, + 'id': UUID, // changed it was do_objectID + 'hasBackgroundColor': hasBackgroundColor, + 'isFlowHome': isFlowHome, + 'resizesContent': resizesContent, + 'presetDictionary': presetDictionary, + 'visible': isVisible, // changed it was isVisible + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'artboard'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } + + @override + void set isFlowHome(_isFlowHome) { + // TODO: implement isFlowHome + } } diff --git a/lib/input/sketch/entities/layers/bitmap.dart b/lib/input/sketch/entities/layers/bitmap.dart index 6233ee18..d0d483d2 100644 --- a/lib/input/sketch/entities/layers/bitmap.dart +++ b/lib/input/sketch/entities/layers/bitmap.dart @@ -1,4 +1,5 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/image.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; @@ -139,4 +140,55 @@ class Bitmap extends SketchNode implements SketchNodeFactory, Image { @override Style get style => _style; + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'CLASS_NAME': CLASS_NAME, + 'fillReplacesImage': fillReplacesImage, + 'intendedDPI': intendedDPI, + 'clippingMask': clippingMask, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'image': imageReferenceMap, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'image'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/sketch/entities/layers/group.dart b/lib/input/sketch/entities/layers/group.dart index f8684e79..32338b7e 100644 --- a/lib/input/sketch/entities/layers/group.dart +++ b/lib/input/sketch/entities/layers/group.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_group_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; @@ -120,4 +121,55 @@ class Group extends AbstractGroupLayer implements SketchNodeFactory { bottomRightCorner: Point( boundaryRectangle.x + boundaryRectangle.width, boundaryRectangle.y + boundaryRectangle.height))); + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'hasClickThrough': hasClickThrough, + 'groupLayout': groupLayout, + 'CLASS_NAME': CLASS_NAME, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + '_ref': imageReference, + 'type': type, + 'visible': isVisible, + 'style': style, + 'children': getChildren(), + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'group'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/sketch/entities/layers/oval.dart b/lib/input/sketch/entities/layers/oval.dart index 891792a5..4f741722 100644 --- a/lib/input/sketch/entities/layers/oval.dart +++ b/lib/input/sketch/entities/layers/oval.dart @@ -5,7 +5,7 @@ import 'package:parabeac_core/input/sketch/entities/layers/abstract_shape_layer. import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_oval.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -116,10 +116,49 @@ class Oval extends AbstractShapeLayer implements SketchNodeFactory { @override Future interpretNode(PBContext currentContext) async { - var image = await convertImage( - UUID, boundaryRectangle.width, boundaryRectangle.height); + var image = await SketchAssetProcessor() + .processImage(UUID, boundaryRectangle.width, boundaryRectangle.height); return Future.value(InheritedOval(this, name, currentContext: currentContext, image: image)); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'edited': edited, + 'isClosed': isClosed, + 'pointRadiusBehaviour': pointRadiusBehaviour, + 'points': points, + 'CLASS_NAME': CLASS_NAME, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'oval'; } diff --git a/lib/input/sketch/entities/layers/page.dart b/lib/input/sketch/entities/layers/page.dart index 751791f4..10e14c16 100644 --- a/lib/input/sketch/entities/layers/page.dart +++ b/lib/input/sketch/entities/layers/page.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_group_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; @@ -123,4 +124,59 @@ class Page extends AbstractGroupLayer implements SketchNodeFactory { assert(false, 'We don\'t product pages as Intermediate Nodes.'); return null; } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'hasClickThrough': hasClickThrough, + 'groupLayout': groupLayout, + 'CLASS_NAME': CLASS_NAME, + 'includeInCloudUpload': includeInCloudUpload, + 'horizontalRulerData': horizontalRulerData, + 'verticalRulerData': verticalRulerData, + 'layout': layout, + 'grid': grid, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'children': getChildren(), + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'page'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/sketch/entities/layers/polygon.dart b/lib/input/sketch/entities/layers/polygon.dart index e2303213..800b0fa9 100644 --- a/lib/input/sketch/entities/layers/polygon.dart +++ b/lib/input/sketch/entities/layers/polygon.dart @@ -1,11 +1,12 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_shape_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_polygon.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -117,10 +118,49 @@ class Polygon extends AbstractShapeLayer implements SketchNodeFactory { @override Future interpretNode(PBContext currentContext) async { - var image = await convertImage( - UUID, boundaryRectangle.width, boundaryRectangle.height); + var image = await SketchAssetProcessor() + .processImage(UUID, boundaryRectangle.width, boundaryRectangle.height); return Future.value(InheritedPolygon(this, name, currentContext: currentContext, image: image)); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'edited': edited, + 'isClosed': isClosed, + 'pointRadiusBehaviour': pointRadiusBehaviour, + 'points': points, + 'CLASS_NAME': CLASS_NAME, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'polygon'; } diff --git a/lib/input/sketch/entities/layers/rectangle.dart b/lib/input/sketch/entities/layers/rectangle.dart index 3289858a..573789e4 100644 --- a/lib/input/sketch/entities/layers/rectangle.dart +++ b/lib/input/sketch/entities/layers/rectangle.dart @@ -145,4 +145,46 @@ class Rectangle extends AbstractShapeLayer }, )); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'edited': edited, + 'isClosed': isClosed, + 'pointRadiusBehaviour': pointRadiusBehaviour, + 'points': points, + 'CLASS_NAME': CLASS_NAME, + 'fixedRadius': fixedRadius, + 'hasConvertedToNewRoundCorners': hasConvertedToNewRoundCorners, + 'needsConvertionToNewRoundCorners': needsConvertionToNewRoundCorners, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'rectangle'; } diff --git a/lib/input/sketch/entities/layers/shape_group.dart b/lib/input/sketch/entities/layers/shape_group.dart index 305975d9..d4a68500 100644 --- a/lib/input/sketch/entities/layers/shape_group.dart +++ b/lib/input/sketch/entities/layers/shape_group.dart @@ -1,11 +1,12 @@ import 'package:json_annotation/json_annotation.dart'; +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_group_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_shape_group.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -119,10 +120,61 @@ class ShapeGroup extends AbstractGroupLayer implements SketchNodeFactory { @override Future interpretNode(PBContext currentContext) async { - var image = await convertImage( - UUID, boundaryRectangle.width, boundaryRectangle.height); + var image = await SketchAssetProcessor() + .processImage(UUID, boundaryRectangle.width, boundaryRectangle.height); return InheritedShapeGroup(this, name, currentContext: currentContext, image: image); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'hasClickThrough': hasClickThrough, + 'groupLayout': groupLayout, + 'CLASS_NAME': CLASS_NAME, + 'windingRule': windingRule, + 'absoluteBoudingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'children': getChildren(), + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'image'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/sketch/entities/layers/shape_path.dart b/lib/input/sketch/entities/layers/shape_path.dart index 46e35b89..17d4a6db 100644 --- a/lib/input/sketch/entities/layers/shape_path.dart +++ b/lib/input/sketch/entities/layers/shape_path.dart @@ -4,7 +4,7 @@ import 'package:parabeac_core/input/sketch/entities/layers/abstract_shape_layer. import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_shape_path.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:json_annotation/json_annotation.dart'; @@ -115,10 +115,49 @@ class ShapePath extends AbstractShapeLayer implements SketchNodeFactory { @override Future interpretNode(PBContext currentContext) async { - var image = await convertImage( - UUID, boundaryRectangle.width, boundaryRectangle.height); + var image = await SketchAssetProcessor() + .processImage(UUID, boundaryRectangle.width, boundaryRectangle.height); return Future.value(InheritedShapePath(this, name, currentContext: currentContext, image: image)); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'edited': edited, + 'isClosed': isClosed, + 'pointRadiusBehaviour': pointRadiusBehaviour, + 'points': points, + 'CLASS_NAME': CLASS_NAME, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'vector'; } diff --git a/lib/input/sketch/entities/layers/sketch_text.dart b/lib/input/sketch/entities/layers/sketch_text.dart index d0375dbd..037fd149 100644 --- a/lib/input/sketch/entities/layers/sketch_text.dart +++ b/lib/input/sketch/entities/layers/sketch_text.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/text.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; @@ -21,11 +22,15 @@ class SketchText extends SketchNode implements SketchNodeFactory, Text { @override String CLASS_NAME = 'text'; - Map attributedString; + @override final bool automaticallyDrawOnUnderlyingPath; + @override final bool dontSynchroniseWithSymbol; + @override final dynamic lineSpacingBehaviour; + @override final dynamic textBehaviour; + @override final dynamic glyphBounds; @override @@ -138,4 +143,86 @@ class SketchText extends SketchNode implements SketchNodeFactory, Text { @override @JsonKey(ignore: true) String content; + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'CLASS_NAME': CLASS_NAME, + 'attributedString': attributedString, + 'automaticallyDrawOnUnderlyingPath': automaticallyDrawOnUnderlyingPath, + 'dontSynchroniseWithSymbol': dontSynchroniseWithSymbol, + 'lineSpacingBehaviour': lineSpacingBehaviour, + 'textBehaviour': textBehaviour, + 'glyphBounds': glyphBounds, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'text'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } + + @override + var attributedString; + + @override + void set automaticallyDrawOnUnderlyingPath( + _automaticallyDrawOnUnderlyingPath) { + // TODO: implement automaticallyDrawOnUnderlyingPath + } + + @override + void set dontSynchroniseWithSymbol(_dontSynchroniseWithSymbol) { + // TODO: implement dontSynchroniseWithSymbol + } + + @override + void set glyphBounds(_glyphBounds) { + // TODO: implement glyphBounds + } + + @override + void set lineSpacingBehaviour(_lineSpacingBehaviour) { + // TODO: implement lineSpacingBehaviour + } + + @override + void set textBehaviour(_textBehaviour) { + // TODO: implement textBehaviour + } } diff --git a/lib/input/sketch/entities/layers/star.dart b/lib/input/sketch/entities/layers/star.dart index 4fe2a281..986a4af0 100644 --- a/lib/input/sketch/entities/layers/star.dart +++ b/lib/input/sketch/entities/layers/star.dart @@ -5,7 +5,7 @@ import 'package:parabeac_core/input/sketch/entities/layers/abstract_shape_layer. import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_star.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -116,10 +116,49 @@ class Star extends AbstractShapeLayer implements SketchNodeFactory { @override Future interpretNode(PBContext currentContext) async { - var image = await convertImage( - UUID, boundaryRectangle.width, boundaryRectangle.height); + var image = await SketchAssetProcessor() + .processImage(UUID, boundaryRectangle.width, boundaryRectangle.height); return Future.value(InheritedStar(this, name, currentContext: currentContext, image: image)); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'edited': edited, + 'isClosed': isClosed, + 'pointRadiusBehaviour': pointRadiusBehaviour, + 'points': points, + 'CLASS_NAME': CLASS_NAME, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'star'; } diff --git a/lib/input/sketch/entities/layers/symbol_instance.dart b/lib/input/sketch/entities/layers/symbol_instance.dart index dcd278f9..a9ab15c7 100644 --- a/lib/input/sketch/entities/layers/symbol_instance.dart +++ b/lib/input/sketch/entities/layers/symbol_instance.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/pb_shared_instance_design_node.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_layer.dart'; @@ -130,7 +131,10 @@ class SymbolInstance extends SketchNode if (!ovrNames.contains(overrideValue.overrideName)) { var properties = extractParameter(overrideValue.overrideName); sharedParameters.add(PBSharedParameterValue( - properties['type'], overrideValue.value, properties['uuid'], overrideValue.overrideName)); + properties['type'], + overrideValue.value, + properties['uuid'], + overrideValue.overrideName)); ovrNames.add(overrideValue.overrideName); } } @@ -148,4 +152,57 @@ class SymbolInstance extends SketchNode @override List parameters; + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'CLASS_NAME': CLASS_NAME, + 'overrideValues': overrideValues, + 'scale': scale, + 'symbolID': symbolID, + 'verticalSpacing': verticalSpacing, + 'horizontalSpacing': horizontalSpacing, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'parameters': parameters, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'symbol_instance'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } } diff --git a/lib/input/sketch/entities/layers/symbol_master.dart b/lib/input/sketch/entities/layers/symbol_master.dart index b2477426..3e40742f 100644 --- a/lib/input/sketch/entities/layers/symbol_master.dart +++ b/lib/input/sketch/entities/layers/symbol_master.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/design_logic/pb_shared_instance_design_node.dart'; import 'package:parabeac_core/input/sketch/entities/abstract_sketch_node_factory.dart'; import 'package:parabeac_core/input/sketch/entities/layers/abstract_group_layer.dart'; @@ -23,6 +24,8 @@ class SymbolMaster extends AbstractGroupLayer implements SketchNodeFactory, PBSharedInstanceDesignNode { @override String CLASS_NAME = 'symbolMaster'; + @override + var overrideValues; final Color backgroundColor; final bool hasBackgroundColor; final dynamic horizontalRulerData; @@ -140,7 +143,7 @@ class SymbolMaster extends AbstractGroupLayer userInfo, style, maintainScrollPosition) { - this.name = name?.replaceAll(RegExp(r'[\d\s_\+]'), ''); + this.name = name?.replaceAll(RegExp(r'[\s_\+]'), ''); // ?.replaceFirst(RegExp(r'^([\d]|_)+'), ''); // someElement/default } @@ -177,19 +180,83 @@ class SymbolMaster extends AbstractGroupLayer return sharedParameters; } - @override - Future interpretNode(PBContext currentContext) { - var sym_master = PBSharedMasterNode( - this, - symbolID, - name, - Point(boundaryRectangle.x, boundaryRectangle.y), - Point(boundaryRectangle.x + boundaryRectangle.width, - boundaryRectangle.y + boundaryRectangle.height), - overridableProperties: _extractParameters(), - currentContext: currentContext, - ); - return Future.value(sym_master); - } + @override + Future interpretNode(PBContext currentContext) { + var sym_master = PBSharedMasterNode( + this, + symbolID, + name, + Point(boundaryRectangle.x, boundaryRectangle.y), + Point(boundaryRectangle.x + boundaryRectangle.width, + boundaryRectangle.y + boundaryRectangle.height), + overridableProperties: _extractParameters(), + currentContext: currentContext, + ); + return Future.value(sym_master); } + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'hasClickThrough': hasClickThrough, + 'groupLayout': groupLayout, + 'CLASS_NAME': CLASS_NAME, + 'backgroundColor': backgroundColor, + 'hasBackgroundColor': hasBackgroundColor, + 'horizontalRulerData': horizontalRulerData, + 'includeBackgroundColorInExport': includeBackgroundColorInExport, + 'includeInCloudUpload': includeInCloudUpload, + 'isFlowHome': isFlowHome, + 'resizesContent': resizesContent, + 'verticalRulerData': verticalRulerData, + 'includeBackgroundColorInInstance': includeBackgroundColorInInstance, + 'symbolID': symbolID, + 'changeIdentifier': changeIdentifier, + 'allowsOverrides': allowsOverrides, + 'overrideProperties': overrideProperties, + 'presetDictionary': presetDictionary, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'children': getChildren(), + 'parameters': parameters, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'symbol_master'; + + @override + DesignNode createDesignNode(Map json) { + // TODO: implement createDesignNode + throw UnimplementedError(); + } + + @override + DesignNode fromPBDF(Map json) { + // TODO: implement fromPBDF + throw UnimplementedError(); + } +} diff --git a/lib/input/sketch/entities/layers/triangle.dart b/lib/input/sketch/entities/layers/triangle.dart index ecfe65f1..6147d4fd 100644 --- a/lib/input/sketch/entities/layers/triangle.dart +++ b/lib/input/sketch/entities/layers/triangle.dart @@ -5,7 +5,7 @@ import 'package:parabeac_core/input/sketch/entities/layers/abstract_shape_layer. import 'package:parabeac_core/input/sketch/entities/layers/flow.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_triangle.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -117,10 +117,49 @@ class Triangle extends AbstractShapeLayer implements SketchNodeFactory { @override Future interpretNode(PBContext currentContext) async { - var image = await convertImage( - UUID, boundaryRectangle.width, boundaryRectangle.height); + var image = await SketchAssetProcessor() + .processImage(UUID, boundaryRectangle.width, boundaryRectangle.height); return Future.value(InheritedTriangle(this, name, currentContext: currentContext, image: image)); } + + @override + Map toPBDF() => { + 'booleanOperation': booleanOperation, + 'exportOptions': exportOptions, + 'flow': flow, + 'isFixedToViewport': isFixedToViewport, + 'isFlippedHorizontal': isFlippedHorizontal, + 'isFlippedVertical': isFlippedVertical, + 'isLocked': isLocked, + 'layerListExpandedType': layerListExpandedType, + 'name': name, + 'nameIsFixed': nameIsFixed, + 'resizingConstraint': resizingConstraint, + 'resizingType': resizingType, + 'rotation': rotation, + 'sharedStyleID': sharedStyleID, + 'shouldBreakMaskChain': shouldBreakMaskChain, + 'hasClippingMask': hasClippingMask, + 'clippingMaskMode': clippingMaskMode, + 'userInfo': userInfo, + 'maintainScrollPosition': maintainScrollPosition, + 'prototypeNodeUUID': prototypeNodeUUID, + 'edited': edited, + 'isClosed': isClosed, + 'pointRadiusBehaviour': pointRadiusBehaviour, + 'points': points, + 'CLASS_NAME': CLASS_NAME, + 'absoluteBoundingBox': boundaryRectangle, + 'id': UUID, + 'type': type, + 'visible': isVisible, + 'style': style, + 'pbdfType': pbdfType, + }; + + @override + @JsonKey(ignore: true) + String pbdfType = 'triangle'; } diff --git a/lib/input/sketch/helper/sketch_asset_processor.dart b/lib/input/sketch/helper/sketch_asset_processor.dart new file mode 100644 index 00000000..09d5901e --- /dev/null +++ b/lib/input/sketch/helper/sketch_asset_processor.dart @@ -0,0 +1,74 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:http/http.dart' as http; +import 'package:parabeac_core/controllers/main_info.dart'; +import 'package:parabeac_core/input/helper/asset_processing_service.dart'; +import 'package:quick_log/quick_log.dart'; + +class SketchAssetProcessor extends AssetProcessingService { + final svg_convertion_endpoint = + Platform.environment.containsKey('SAC_ENDPOINT') + ? Platform.environment['SAC_ENDPOINT'] + : 'http://localhost:4000/vector/local'; + + Logger log = Logger('Image conversion'); + + SketchAssetProcessor._internal(); + + static final SketchAssetProcessor _instance = + SketchAssetProcessor._internal(); + + factory SketchAssetProcessor() => _instance; + + String getBlobName(String path) => path.split('/').last; + + /// Converts an svg with `uuid` from a sketch file to a png with specified + /// `width` and `height` + @override + Future processImage(String uuid, [num width, num height]) async { + try { + var body = Platform.environment.containsKey('SAC_ENDPOINT') + ? { + 'uuid': uuid, + 'width': width, + 'height': height, + 'blob': getBlobName(MainInfo().sketchPath), + 'container': 'design-file' + } + : { + 'uuid': uuid, + 'path': MainInfo().sketchPath, + 'width': width, + 'height': height + }; + + var response = await http + .post( + svg_convertion_endpoint, + headers: {HttpHeaders.contentTypeHeader: 'application/json'}, + body: jsonEncode(body), + ) + .timeout(Duration(minutes: 1)); + + if (response.statusCode >= 400) { + var bodyMap = jsonDecode(response.body); + log.error(bodyMap['error']); + } + return response?.bodyBytes; + } catch (e) { + await MainInfo().sentry.captureException(exception: e); + log.error(e.message); + } + return null; + } + + @override + Future processRootElements(Map uuids) async { + for (var entry in uuids.entries) { + var image = await processImage( + entry.key, uuids[entry.key]['width'], uuids[entry.key]['height']); + await super.uploadToStorage(image, entry.key); + } + } +} diff --git a/lib/input/sketch/helper/sketch_page.dart b/lib/input/sketch/helper/sketch_page.dart index 61e8ab23..a17f6984 100644 --- a/lib/input/sketch/helper/sketch_page.dart +++ b/lib/input/sketch/helper/sketch_page.dart @@ -1,9 +1,13 @@ -import 'package:parabeac_core/input/helper/page.dart'; +import 'package:parabeac_core/input/helper/design_page.dart'; import 'package:quick_log/quick_log.dart'; -class SketchPage extends Page { +class SketchPage extends DesignPage { @override - var log = Logger('Sketch'); + var log = Logger('Design Page Sketch'); - SketchPage(String name) : super(name); + SketchPage(String name, String id) + : super( + name: name, + id: id, + ); } diff --git a/lib/input/sketch/helper/sketch_page_item.dart b/lib/input/sketch/helper/sketch_page_item.dart deleted file mode 100644 index 1aa9c5a3..00000000 --- a/lib/input/sketch/helper/sketch_page_item.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:parabeac_core/design_logic/design_node.dart'; -import 'package:parabeac_core/input/helper/page.dart'; -import 'package:parabeac_core/input/helper/page_item.dart'; - -class SketchPageItem extends PageItem { - SketchPageItem(DesignNode root, Page parentPage) : super(root, parentPage); -} diff --git a/lib/input/sketch/helper/sketch_node_tree.dart b/lib/input/sketch/helper/sketch_project.dart similarity index 79% rename from lib/input/sketch/helper/sketch_node_tree.dart rename to lib/input/sketch/helper/sketch_project.dart index 2abb5ced..0e8cef15 100644 --- a/lib/input/sketch/helper/sketch_node_tree.dart +++ b/lib/input/sketch/helper/sketch_project.dart @@ -1,20 +1,17 @@ import 'package:parabeac_core/controllers/main_info.dart'; -import 'package:parabeac_core/controllers/sketch_controller.dart'; -import 'package:parabeac_core/input/helper/node_tree.dart'; +import 'package:parabeac_core/input/helper/design_project.dart'; import 'package:parabeac_core/input/sketch/entities/documents/document.dart'; import 'package:parabeac_core/input/sketch/entities/layers/page.dart'; import 'package:parabeac_core/input/sketch/entities/objects/foreign_symbol.dart'; import 'package:parabeac_core/input/sketch/entities/style/shared_style.dart'; -import 'package:parabeac_core/input/sketch/entities/style/style.dart'; -import 'package:parabeac_core/input/sketch/entities/style/text_style.dart'; import 'package:parabeac_core/input/sketch/helper/sketch_page.dart'; -import 'package:parabeac_core/input/sketch/helper/sketch_page_item.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_screen.dart'; import 'dart:convert'; import 'package:archive/archive.dart'; import 'package:parabeac_core/input/sketch/services/input_design.dart'; import 'package:quick_log/quick_log.dart'; -class SketchNodeTree extends NodeTree { +class SketchProject extends DesignProject { @override var log = Logger('SketchNodeTree'); SketchPage rootScreen; @@ -27,7 +24,8 @@ class SketchNodeTree extends NodeTree { final InputDesignService _ids; Archive _originalArchive; final Map _pagesAndArtboards; - SketchNodeTree(this._ids, this._pagesAndArtboards, this.projectName) { + SketchProject(this._ids, this._pagesAndArtboards, this.projectName) { + id = _ids.documentFile['do_objectID']; _originalArchive = _ids.archive; miscPages.add(_setThirdPartySymbols()); sharedStyles = _setSharedStyles(); @@ -62,13 +60,12 @@ class SketchNodeTree extends NodeTree { return sharedStyles; } catch (e, stackTrace) { MainInfo().sentry.captureException( - exception: e, - stackTrace: stackTrace, - ); + exception: e, + stackTrace: stackTrace, + ); log.error(e.toString()); return null; } - } SketchPage _setThirdPartySymbols() { @@ -76,9 +73,13 @@ class SketchNodeTree extends NodeTree { var jsonData = _ids.documentFile; var doc = Document.fromJson(jsonData); var foreignLayers = doc.foreignSymbols ?? []; - var pg = SketchPage('third_party_widgets'); + var pg = SketchPage('third_party_widgets', jsonData['do_objectID']); for (var layer in foreignLayers) { - pg.addPageItem(SketchPageItem(layer.originalMaster, pg)); + pg.addScreen(SketchScreen( + layer.originalMaster, + layer.UUID, + '', + )); } return pg; } catch (e, stackTrace) { @@ -98,12 +99,17 @@ class SketchNodeTree extends NodeTree { _originalArchive.findFile('pages/${entry.key}.json').content; var jsonData = json.decode(utf8.decode(pageContent)); - var pg = SketchPage(jsonData['name']); // Sketch Node Holder + var pg = SketchPage( + jsonData['name'], jsonData['do_objectID']); // Sketch Node Holder var node = Page.fromJson(jsonData); // Actual Sketch Node // Turn layers into PBNodes for (var layer in node.children) { - pg.addPageItem(SketchPageItem(layer, pg)); + pg.addScreen(SketchScreen( + layer, + layer.UUID, + layer.name, + )); } sketchPages.add(pg); } diff --git a/lib/input/sketch/helper/sketch_screen.dart b/lib/input/sketch/helper/sketch_screen.dart new file mode 100644 index 00000000..8810592b --- /dev/null +++ b/lib/input/sketch/helper/sketch_screen.dart @@ -0,0 +1,14 @@ +import 'package:parabeac_core/design_logic/design_node.dart'; +import 'package:parabeac_core/input/helper/design_screen.dart'; + +class SketchScreen extends DesignScreen { + SketchScreen( + DesignNode root, + String id, + String name, + ) : super( + designNode: root, + id: id, + name: name, + ); +} diff --git a/lib/input/sketch/helper/svg_png_convertion.dart b/lib/input/sketch/helper/svg_png_convertion.dart deleted file mode 100644 index e83cff63..00000000 --- a/lib/input/sketch/helper/svg_png_convertion.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; -import 'package:http/http.dart' as http; -import 'package:parabeac_core/controllers/main_info.dart'; -import 'package:quick_log/quick_log.dart'; - -final svg_convertion_endpoint = Platform.environment.containsKey('SAC_ENDPOINT') - ? Platform.environment['SAC_ENDPOINT'] - : 'http://localhost:4000/vector/local'; - -Logger log = Logger('Image conversion'); - -/// Converts an svg with `uuid` from a sketch file to a png with specified -/// `width` and `height` -Future convertImage(String uuid, num width, num height) async { - try { - var body = Platform.environment.containsKey('SAC_ENDPOINT') - ? { - 'uuid': uuid, - 'width': width, - 'height': height, - 'blob': getBlobName(MainInfo().sketchPath), - 'container': 'design-file' - } - : { - 'uuid': uuid, - 'path': MainInfo().sketchPath, - 'width': width, - 'height': height - }; - - var response = await http - .post( - svg_convertion_endpoint, - headers: {HttpHeaders.contentTypeHeader: 'application/json'}, - body: jsonEncode(body), - ) - .timeout(Duration(minutes: 1)); - - if (response.statusCode >= 400) { - var bodyMap = jsonDecode(response.body); - log.error(bodyMap['error']); - } - return response?.bodyBytes; - } catch (e) { - log.error(e.message); - } - return null; -} - -String getBlobName(String path) => path.split('/').last; diff --git a/lib/input/sketch/helper/symbol_node_mixin.dart b/lib/input/sketch/helper/symbol_node_mixin.dart index 144057c6..60e47f48 100644 --- a/lib/input/sketch/helper/symbol_node_mixin.dart +++ b/lib/input/sketch/helper/symbol_node_mixin.dart @@ -21,13 +21,18 @@ mixin SymbolNodeMixin { }; // should have been a Map but iterate slowly through the list - String FindName(String uuid, List children, Type type) { + String FindName(String uuid, List children, Type type) { for (var child in children) { if (child.UUID == uuid) { - var name = ((typeToAbbreviation[type] ?? 'un') + ' ' + (child.name ?? 'var')).camelCase; - return name.replaceAll(RegExp(r'[^A-Za-z0-9_]',), ''); - } - else if (child is AbstractGroupLayer){ + var name = + ((typeToAbbreviation[type] ?? 'un') + ' ' + (child.name ?? 'var')) + .camelCase; + return name.replaceAll( + RegExp( + r'[^A-Za-z0-9_]', + ), + ''); + } else if (child is AbstractGroupLayer) { var found = FindName(uuid, child.children, type); if (found != null) { return found; @@ -38,8 +43,7 @@ mixin SymbolNodeMixin { return null; } - Map AddMasterSymbolName(String overrideName, List children){ - + Map AddMasterSymbolName(String overrideName, List children) { var varName; var parmInfo = extractParameter(overrideName); var uuid = parmInfo['uuid']; @@ -59,8 +63,7 @@ mixin SymbolNodeMixin { varName = SN_UUIDtoVarName[overrideName]; } - return {'name': varName, 'type': parmInfo['type'], 'uuid': uuid }; - + return {'name': varName, 'type': parmInfo['type'], 'uuid': uuid}; } ///Extracting the UUID of the parameter either from the [SymbolInstance] @@ -93,6 +96,6 @@ mixin SymbolNodeMixin { type = String; } - return { 'type': type, 'uuid': uuid}; + return {'type': type, 'uuid': uuid}; } } diff --git a/lib/input/sketch/services/input_design.dart b/lib/input/sketch/services/input_design.dart index bafe28c7..ed780570 100644 --- a/lib/input/sketch/services/input_design.dart +++ b/lib/input/sketch/services/input_design.dart @@ -17,9 +17,11 @@ class InputDesignService { Archive _archive; - InputDesignService(this.pathToFile) { + InputDesignService(this.pathToFile, {bool jsonOnly = false}) { _archive = _unzip(File(pathToFile)); - setImageDir(); + if (!jsonOnly) { + setImageDir(); + } } ///The archive of the unzipped sketch project diff --git a/lib/interpret_and_optimize/entities/inherited_shape_path.dart b/lib/interpret_and_optimize/entities/inherited_shape_path.dart index 63f08233..6758df28 100644 --- a/lib/interpret_and_optimize/entities/inherited_shape_path.dart +++ b/lib/interpret_and_optimize/entities/inherited_shape_path.dart @@ -75,9 +75,7 @@ class InheritedShapePath extends PBVisualIntermediateNode if (_isEdgeAdjacent(p1, p2)) { generator = PBContainerGenerator(); - auxiliaryData.color = originalRef.style.borders.isNotEmpty - ? toHex(originalRef.style.borders[0].color) - : toHex(null); // Interpret as default color + auxiliaryData.color = toHex(originalRef.style.borders[0].color); } } } diff --git a/lib/interpret_and_optimize/entities/pb_shared_master_node.dart b/lib/interpret_and_optimize/entities/pb_shared_master_node.dart index 29cfa7ef..6bbc15e3 100644 --- a/lib/interpret_and_optimize/entities/pb_shared_master_node.dart +++ b/lib/interpret_and_optimize/entities/pb_shared_master_node.dart @@ -1,7 +1,6 @@ import 'package:parabeac_core/design_logic/design_node.dart'; import 'package:parabeac_core/generation/generators/symbols/pb_mastersym_gen.dart'; import 'package:parabeac_core/generation/prototyping/pb_prototype_node.dart'; -import 'package:parabeac_core/input/sketch/helper/symbol_node_mixin.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/interfaces/pb_inherited_intermediate.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/layouts/temp_group_layout_node.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; diff --git a/lib/interpret_and_optimize/helpers/pb_image_reference_storage.dart b/lib/interpret_and_optimize/helpers/pb_image_reference_storage.dart index e218a6b3..39daca57 100644 --- a/lib/interpret_and_optimize/helpers/pb_image_reference_storage.dart +++ b/lib/interpret_and_optimize/helpers/pb_image_reference_storage.dart @@ -34,7 +34,11 @@ class ImageReferenceStorage { return true; } if (addReference(name, path)) { - File('${MainInfo().outputPath}pngs/${name}.png').writeAsBytesSync(image); + var imgPath = '${MainInfo().outputPath}pngs/${name}.png'; + if (!File(imgPath).existsSync()) { + File(imgPath).createSync(recursive: true); + } + File(imgPath).writeAsBytesSync(image); return true; } return false; diff --git a/lib/interpret_and_optimize/helpers/pb_state_management_helper.dart b/lib/interpret_and_optimize/helpers/pb_state_management_helper.dart index 3355e555..8fdad3ec 100644 --- a/lib/interpret_and_optimize/helpers/pb_state_management_helper.dart +++ b/lib/interpret_and_optimize/helpers/pb_state_management_helper.dart @@ -1,3 +1,4 @@ +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_state_management_linker.dart'; @@ -26,21 +27,15 @@ class PBStateManagementHelper { /// Returns `true` if `node` is or would be the default node, /// `false` otherwise bool isDefaultNode(PBIntermediateNode node) => - !linker.containsElement(_getNodeName(node.name)); + node is PBSharedMasterNode && + (linker.isSymbolInstance(_getNodeName(node.name)) || + !linker.containsElement(_getNodeName(node.name))); - String _getNodeName(String fullName) { - if (!isValidStateNode(fullName)) { - return ''; - } - return fullName.split('/')[0]; - } + String _getNodeName(String fullName) => + isValidStateNode(fullName) ? fullName.split('/')[0] : ''; - List _getStates(String fullName) { - if (!isValidStateNode(fullName)) { - return []; - } - return fullName.split('/')[1].split(','); - } + List _getStates(String fullName) => + isValidStateNode(fullName) ? fullName.split('/')[1].split(',') : []; /// Returns true if `name` is a valid state management name bool isValidStateNode(String name) => diff --git a/lib/interpret_and_optimize/helpers/pb_state_management_linker.dart b/lib/interpret_and_optimize/helpers/pb_state_management_linker.dart index 1980f731..020af311 100644 --- a/lib/interpret_and_optimize/helpers/pb_state_management_linker.dart +++ b/lib/interpret_and_optimize/helpers/pb_state_management_linker.dart @@ -1,5 +1,6 @@ import 'package:parabeac_core/controllers/interpret.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/interfaces/pb_inherited_intermediate.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/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_symbol_storage.dart'; @@ -26,6 +27,12 @@ class PBStateManagementLinker { bool containsElement(String name) => _statemap.containsKey(name); + /// Returns true if `name` exists in the statemap and it is + /// a symbol instance. + bool isSymbolInstance(String name) => + _statemap.containsKey(name) && + _statemap[name] is PBSharedInstanceIntermediateNode; + /// Adds the `node` variation to the [DirectedStateGraph] of the /// default [PBIntermediateNode], or sets up `node` as default /// to receive [IntermediateStates] in its state graph. @@ -34,6 +41,26 @@ class PBStateManagementLinker { if (!containsElement(rootNodeName)) { _statemap[rootNodeName] = node; } + // Replacing a default node that was an instance node + else if (node is PBSharedMasterNode && + _statemap[rootNodeName] is PBSharedInstanceIntermediateNode) { + var instanceNode = _statemap[rootNodeName]; + + // Transfer states to new default node + instanceNode.auxiliaryData.stateGraph.states + .forEach((state) => node.auxiliaryData.stateGraph.addState(state)); + + // Add old default node as state of new default node + stateQueue + .add(_interpretVariationNode(instanceNode).then((processedNode) { + var intermediateState = + IntermediateState(variation: IntermediateVariation(processedNode)); + node.auxiliaryData.stateGraph.addState(intermediateState); + })); + + // Set new default node + _statemap[rootNodeName] = node; + } // Add state to default node else { if (node is PBSharedMasterNode) { diff --git a/lib/interpret_and_optimize/services/pb_visual_generation_service.dart b/lib/interpret_and_optimize/services/pb_visual_generation_service.dart index 3528d525..6b5cf7b9 100644 --- a/lib/interpret_and_optimize/services/pb_visual_generation_service.dart +++ b/lib/interpret_and_optimize/services/pb_visual_generation_service.dart @@ -6,6 +6,7 @@ import 'package:parabeac_core/generation/prototyping/pb_dest_holder.dart'; import 'package:parabeac_core/generation/prototyping/pb_prototype_node.dart'; import 'package:parabeac_core/input/sketch/services/positional_cleansing_service.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/pb_deny_list_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/node_tuple.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; @@ -51,7 +52,7 @@ class PBVisualGenerationService implements PBGenerationService { while (queue.isNotEmpty) { var currentNode = queue.removeAt(0); - if (currentNode?.designNode?.isVisible ?? false) { + if (currentNode.designNode?.isVisible ?? true) { PBIntermediateNode result; // Check semantics result = PBDenyListHelper() @@ -73,10 +74,11 @@ class PBVisualGenerationService implements PBGenerationService { // Interpret state management node if (!ignoreStates && - smHelper.isValidStateNode(result.name) && - currentNode.designNode.name != + smHelper.isValidStateNode(result.name) && + (currentNode.designNode.name != currentNode.convertedParent?.name ?? - true) { + true) && + result is PBSharedMasterNode) { if (smHelper.isDefaultNode(result)) { smHelper.interpretStateManagementNode(result); } else { diff --git a/lib/main.dart b/lib/main.dart index 63cd264f..e458c31b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,13 @@ import 'dart:convert'; import 'dart:io'; import 'package:parabeac_core/APICaller/api_call_service.dart'; +import 'package:parabeac_core/controllers/design_controller.dart'; import 'package:parabeac_core/controllers/figma_controller.dart'; import 'package:parabeac_core/controllers/main_info.dart'; import 'package:parabeac_core/controllers/sketch_controller.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; +import 'package:parabeac_core/input/helper/azure_asset_service.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:parabeac_core/input/sketch/services/input_design.dart'; import 'package:parabeac_core/interpret_and_optimize/helpers/pb_plugin_list_helper.dart'; import 'package:quick_log/quick_log.dart'; @@ -11,8 +15,8 @@ import 'package:sentry/sentry.dart'; import 'package:uuid/uuid.dart'; import 'package:http/http.dart' as http; import 'package:args/args.dart'; - import 'controllers/main_info.dart'; +import 'package:yaml/yaml.dart'; ArgResults argResults; @@ -24,6 +28,11 @@ void main(List args) async { dsn: 'https://6e011ce0d8cd4b7fb0ff284a23c5cb37@o433482.ingest.sentry.io/5388747'); var log = Logger('Main'); + var pubspec = File('pubspec.yaml'); + await pubspec.readAsString().then((String text) { + Map yaml = loadYaml(text); + log.info('Current version: ${yaml['version']}'); + }); log.info(args.toString()); MainInfo().cwd = Directory.current; @@ -41,8 +50,15 @@ void main(List args) async { defaultsTo: 'default:lib/configurations/configurations.json') ..addOption('fig', help: 'The ID of the figma file', abbr: 'f') ..addOption('figKey', help: 'Your personal API Key', abbr: 'k') + ..addOption( + 'pbdl-in', + help: + 'Takes in a Parabeac Design Logic (PBDL) JSON file and exports it to a project', + ) ..addFlag('help', - help: 'Displays this help information.', abbr: 'h', negatable: false); + help: 'Displays this help information.', abbr: 'h', negatable: false) + ..addFlag('export-pbdl', + help: 'This flag outputs Parabeac Design Logic (PBDL) in JSON format.'); //error handler using logger package void handleError(String msg) { @@ -62,6 +78,7 @@ ${parser.usage} exit(0); } + // Detect platform if (Platform.isMacOS || Platform.isLinux) { MainInfo().platform = 'UIX'; } else if (Platform.isWindows) { @@ -76,22 +93,23 @@ ${parser.usage} MainInfo().figmaProjectID = argResults['fig']; var designType = 'sketch'; + var jsonOnly = argResults['export-pbdl']; var configurationPath = argResults['config-path']; var configurationType = 'default'; String projectName = argResults['project-name']; // Handle input errors - if (path == null && - (MainInfo().figmaKey == null || MainInfo().figmaProjectID == null)) { + if (hasTooFewArgs(argResults)) { handleError( 'Missing required argument: path to Sketch file or both Figma Key and Project ID.'); - } else if (path != null && - (MainInfo().figmaKey != null || MainInfo().figmaProjectID != null)) { + } else if (hasTooManyArgs(argResults)) { handleError( 'Too many arguments: Please provide either the path to Sketch file or the Figma File ID and API Key'); - } else if (path == null) { + } else if (argResults['figKey'] != null && argResults['fig'] != null) { designType = 'figma'; + } else if (argResults['pbdl-in'] != null) { + designType = 'pbdl'; } // usage -c "default:lib/configurations/configurations.json @@ -115,36 +133,44 @@ ${parser.usage} MainInfo().projectName = projectName; // Create pngs directory - await Directory('${MainInfo().outputPath}pngs').create(recursive: true); + + await Directory('${MainInfo().outputPath}' + + (jsonOnly || argResults['pbdl-in'] != null ? '' : 'pngs')) + .create(recursive: true); if (designType == 'sketch') { - var file = await FileSystemEntity.isFile(path); - var exists = await File(path).exists(); + Process process; + if (!jsonOnly) { + var file = await FileSystemEntity.isFile(path); + var exists = await File(path).exists(); - if (!file || !exists) { - handleError('$path is not a file'); - } - MainInfo().sketchPath = path; - InputDesignService(path); - - var process; - if (!Platform.environment.containsKey('SAC_ENDPOINT')) { - process = await Process.start('npm', ['run', 'prod'], - workingDirectory: MainInfo().cwd.path + '/SketchAssetConverter'); - - await for (var event in process.stdout.transform(utf8.decoder)) { - if (event.toLowerCase().contains('server is listening on port')) { - log.fine('Successfully started Sketch Asset Converter'); - break; + if (!file || !exists) { + handleError('$path is not a file'); + } + MainInfo().sketchPath = path; + InputDesignService(path); + + if (!Platform.environment.containsKey('SAC_ENDPOINT')) { + process = await Process.start('npm', ['run', 'prod'], + workingDirectory: MainInfo().cwd.path + '/SketchAssetConverter'); + + await for (var event in process.stdout.transform(utf8.decoder)) { + if (event.toLowerCase().contains('server is listening on port')) { + log.fine('Successfully started Sketch Asset Converter'); + break; + } } } } - await SketchController().convertFile( - path, - MainInfo().outputPath + projectName, - configurationPath, - configurationType); + SketchController().convertFile( + path, + MainInfo().outputPath + projectName, + configurationPath, + configurationType, + jsonOnly: jsonOnly, + apService: SketchAssetProcessor(), + ); process?.kill(); } else if (designType == 'xd') { assert(false, 'We don\'t support Adobe XD.'); @@ -161,15 +187,38 @@ ${parser.usage} MainInfo().figmaKey); if (jsonOfFigma != null) { + AzureAssetService().projectUUID = MainInfo().figmaProjectID; // Starts Figma to Object FigmaController().convertFile( - jsonOfFigma, - MainInfo().outputPath + projectName, - configurationPath, - configurationType); + jsonOfFigma, + MainInfo().outputPath + projectName, + configurationPath, + configurationType, + jsonOnly: jsonOnly, + apService: FigmaAssetProcessor(), + ); } else { log.error('File was not retrieved from Figma.'); } + } else if (designType == 'pbdl') { + var pbdlPath = argResults['pbdl-in']; + var isFile = FileSystemEntity.isFileSync(pbdlPath); + var exists = File(pbdlPath).existsSync(); + + if (!isFile || !exists) { + handleError('$path is not a file'); + } + + var jsonString = await File(pbdlPath).readAsString(); + + var pbdf = json.decode(jsonString); + + DesignController().convertFile( + pbdf, + MainInfo().outputPath + projectName, + configurationPath, + configurationType, + ); } exitCode = 0; } @@ -246,3 +295,25 @@ Future getCleanPath(String path) async { } return result; } + +/// Returns true if `args` contains two or more +/// types of intake to parabeac-core +bool hasTooManyArgs(ArgResults args) { + var hasSketch = args['path'] != null; + var hasFigma = args['figKey'] != null || args['fig'] != null; + var hasPbdl = args['pbdl-in'] != null; + + var hasAll = hasSketch && hasFigma && hasPbdl; + + return hasAll || !(hasSketch ^ hasFigma ^ hasPbdl); +} + +/// Returns true if `args` does not contain any intake +/// to parabeac-core +bool hasTooFewArgs(ArgResults args) { + var hasSketch = args['path'] != null; + var hasFigma = args['figKey'] != null && args['fig'] != null; + var hasPbdl = args['pbdl-in'] != null; + + return !(hasSketch || hasFigma || hasPbdl); +} diff --git a/pubspec.yaml b/pubspec.yaml index 03311e7e..8aa7d109 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: parabeac_core description: A starting point for Dart libraries or applications. -# version: 1.0.0 +version: 1.3.1 # homepage: https://www.example.com environment: @@ -20,6 +20,7 @@ dependencies: http2: ^1.0.1 recase: "^3.0.0" tuple: ^1.0.3 + azblob: ^1.0.3 # path: ^1.6.0 dev_dependencies: diff --git a/test/lib/controllers/interpret_test.dart b/test/lib/controllers/interpret_test.dart index 556f37c5..92503384 100644 --- a/test/lib/controllers/interpret_test.dart +++ b/test/lib/controllers/interpret_test.dart @@ -1,9 +1,9 @@ import 'package:mockito/mockito.dart'; import 'package:parabeac_core/controllers/interpret.dart'; -import 'package:parabeac_core/input/sketch/helper/sketch_node_tree.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_project.dart'; import 'package:test/test.dart'; -class MockSketchNodeTree extends Mock implements SketchNodeTree {} +class MockSketchProject extends Mock implements SketchProject {} void main() { var interpret = Interpret(); @@ -16,7 +16,7 @@ void main() { }); test('Should return a PBIntermediateTree from a SketchNodeTree', () { - var intermediateTree = interpret.interpretAndOptimize(MockSketchNodeTree()); + var intermediateTree = interpret.interpretAndOptimize(MockSketchProject()); expect(intermediateTree, isNotNull); }); diff --git a/test/lib/input_services/input_to_pbdl_test.dart b/test/lib/input_services/input_to_pbdl_test.dart index b88c2d3f..55a4057b 100644 --- a/test/lib/input_services/input_to_pbdl_test.dart +++ b/test/lib/input_services/input_to_pbdl_test.dart @@ -3,10 +3,10 @@ import 'package:parabeac_core/APICaller/api_call_service.dart'; import 'package:parabeac_core/controllers/figma_controller.dart'; import 'package:parabeac_core/controllers/main_info.dart'; import 'package:parabeac_core/controllers/sketch_controller.dart'; -import 'package:parabeac_core/input/figma/helper/figma_node_tree.dart'; import 'package:parabeac_core/input/figma/helper/figma_page.dart'; -import 'package:parabeac_core/input/sketch/helper/sketch_node_tree.dart'; +import 'package:parabeac_core/input/figma/helper/figma_project.dart'; import 'package:parabeac_core/input/sketch/helper/sketch_page.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_project.dart'; import 'package:parabeac_core/input/sketch/services/input_design.dart'; import 'package:test/test.dart'; @@ -35,7 +35,7 @@ void main() { await FigmaController().generateFigmaTree(result, outputPath); expect(figmaNodeTree != null, true); - expect(figmaNodeTree is FigmaNodeTree, true); + expect(figmaNodeTree is FigmaProject, true); expect(figmaNodeTree.pages.isNotEmpty, true); expect(figmaNodeTree.pages[0] is FigmaPage, true); }); @@ -44,7 +44,7 @@ void main() { ids, ids.metaFileJson['pagesAndArtboards'], outputPath); expect(sketchNodeTree != null, true); - expect(sketchNodeTree is SketchNodeTree, true); + expect(sketchNodeTree is SketchProject, true); expect(sketchNodeTree.pages.isNotEmpty, true); expect(sketchNodeTree.pages[0] is SketchPage, true); }); diff --git a/test/lib/interpret_and_optimize/services/interpret_test.dart b/test/lib/interpret_and_optimize/services/interpret_test.dart index e9e5e3af..7297cf80 100644 --- a/test/lib/interpret_and_optimize/services/interpret_test.dart +++ b/test/lib/interpret_and_optimize/services/interpret_test.dart @@ -6,9 +6,9 @@ import 'package:parabeac_core/input/sketch/entities/layers/artboard.dart'; import 'package:parabeac_core/input/sketch/entities/layers/group.dart'; import 'package:parabeac_core/input/sketch/entities/layers/sketch_text.dart'; import 'package:parabeac_core/input/sketch/entities/objects/frame.dart'; -import 'package:parabeac_core/input/sketch/helper/sketch_node_tree.dart'; import 'package:parabeac_core/input/sketch/helper/sketch_page.dart'; -import 'package:parabeac_core/input/sketch/helper/sketch_page_item.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_project.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_screen.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_container.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/alignments/injected_align.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/layouts/temp_group_layout_node.dart'; @@ -20,11 +20,11 @@ import 'package:test/test.dart'; import 'package:mockito/mockito.dart'; import 'package:parabeac_core/interpret_and_optimize/entities/inherited_scaffold.dart'; -class MockNodeTree extends Mock implements SketchNodeTree {} +class MockProject extends Mock implements SketchProject {} class MockPage extends Mock implements SketchPage {} -class MockPageItem extends Mock implements SketchPageItem {} +class MockScreen extends Mock implements SketchScreen {} class MockArtboard extends Mock implements Artboard { @override @@ -62,9 +62,9 @@ class MockContainer extends Mock implements SketchText { } void main() { - MockNodeTree nodeTree; + MockProject project; MockPage page; - MockPageItem pageItem; + MockScreen screen; MockArtboard artboard; MockGroup mockGroup; MockContainer container; @@ -75,16 +75,16 @@ void main() { MainInfo().configurations = MainInfo().defaultConfigs; MainInfo().configurationType = 'default'; - nodeTree = MockNodeTree(); + project = MockProject(); page = MockPage(); - pageItem = MockPageItem(); + screen = MockScreen(); artboard = MockArtboard(); mockGroup = MockGroup(); container = MockContainer(); - when(nodeTree.pages).thenReturn([page]); - when(page.getPageItems()).thenReturn([pageItem]); - when(pageItem.root).thenReturn(artboard); + when(project.pages).thenReturn([page]); + when(page.getPageItems()).thenReturn([screen]); + when(screen.designNode).thenReturn(artboard); when(artboard.children).thenReturn([mockGroup]); when(artboard.isVisible).thenReturn(true); @@ -123,7 +123,7 @@ void main() { }); test('', () async { var mainTree = await Interpret().interpretAndOptimize( - nodeTree, + project, ); expect(mainTree != null, true); expect(mainTree is PBProject, true); diff --git a/test/lib/middleware/bloc_test.dart b/test/lib/middleware/bloc_test.dart new file mode 100644 index 00000000..9b6948cd --- /dev/null +++ b/test/lib/middleware/bloc_test.dart @@ -0,0 +1,123 @@ +import 'dart:io'; + +import 'package:mockito/mockito.dart'; +import 'package:parabeac_core/generation/generators/middleware/state_management/bloc_middleware.dart'; +import 'package:parabeac_core/generation/generators/pb_generation_manager.dart'; +import 'package:parabeac_core/generation/generators/pb_generator.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_project_data.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_view_data.dart'; +import 'package:parabeac_core/generation/generators/value_objects/file_structure_strategy.dart/flutter_file_structure_strategy.dart'; +import 'package:parabeac_core/generation/generators/writers/pb_flutter_writer.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_project.dart'; +import 'package:test/test.dart'; +import 'provider_test.dart'; + +class MockPBGenerationManager extends Mock implements PBGenerationManager {} + +class MockPBIntermediateNode extends Mock implements PBIntermediateNode {} + +class MockContext extends Mock implements PBContext {} + +class MockProject extends Mock implements PBProject {} + +class MockPBGenerationProjectData extends Mock + implements PBGenerationProjectData {} + +class MockPBGenerationViewData extends Mock implements PBGenerationViewData {} + +class MockPBGenerator extends Mock implements PBGenerator {} + +void main() { + group('Middlewares Tests', () { + var testingPath = '${Directory.current.path}/test/lib/middleware/'; + var mockPBGenerationManager = MockPBGenerationManager(); + var bLoCMiddleware = BLoCMiddleware(mockPBGenerationManager); + var node = MockPBIntermediateNode(); + var node2 = MockPBIntermediateNode(); + var mockContext = MockContext(); + var mockProject = MockProject(); + var mockPBGenerationProjectData = MockPBGenerationProjectData(); + var mockPBGenerationViewData = MockPBGenerationViewData(); + var mockPBGenerator = MockPBGenerator(); + var mockFileStructureStrategy = FlutterFileStructureStrategy( + testingPath, + PBFlutterWriter(), + mockProject, + ); + var mockIntermediateAuxiliaryData = MockIntermediateAuxiliaryData(); + var mockDirectedStateGraph = MockDirectedStateGraph(); + var mockIntermediateState = MockIntermediateState(); + var mockIntermediateVariation = MockIntermediateVariation(); + + setUp(() async { + /// Set up nodes + when(node.name).thenReturn('someElement/blue'); + when(node.generator).thenReturn(mockPBGenerator); + when(node.managerData).thenReturn(mockPBGenerationViewData); + when(node.currentContext).thenReturn(mockContext); + when(node.auxiliaryData).thenReturn(mockIntermediateAuxiliaryData); + // 2 + when(node2.name).thenReturn('someElement/green'); + when(node2.generator).thenReturn(mockPBGenerator); + + /// IntermediateAuxiliaryData + when(mockIntermediateAuxiliaryData.stateGraph) + .thenReturn(mockDirectedStateGraph); + + /// DirectedStateGraph + when(mockDirectedStateGraph.states).thenReturn([mockIntermediateState]); + + /// IntermediateState + when(mockIntermediateState.variation) + .thenReturn(mockIntermediateVariation); + + /// IntermediateVariation + when(mockIntermediateVariation.node).thenReturn(node2); + + /// Context + when(mockContext.project).thenReturn(mockProject); + + /// Project + when(mockProject.genProjectData).thenReturn(mockPBGenerationProjectData); + when(mockProject.forest).thenReturn([]); + when(mockProject.fileStructureStrategy) + .thenReturn(mockFileStructureStrategy); + + /// PBGenerationManager + when(mockPBGenerationManager.generate(node)).thenReturn('codeForBlue\n'); + when(mockPBGenerationManager.generate(node2)) + .thenReturn('codeForGreen\n'); + + /// PBGenerationProjectData + when(mockPBGenerationProjectData.addDependencies(any, any)) + .thenReturn('mockDependency'); + }); + + test('BLoC Strategy Test', () async { + await mockFileStructureStrategy.setUpDirectories(); + var tempNode = await bLoCMiddleware.applyMiddleware(node); + expect(tempNode is PBIntermediateNode, true); + expect( + await File( + '${testingPath}lib/view/some_element_bloc/some_element_bloc.dart') + .exists(), + true); + expect( + await File( + '${testingPath}lib/view/some_element_bloc/some_element_event.dart') + .exists(), + true); + expect( + await File( + '${testingPath}lib/view/some_element_bloc/some_element_state.dart') + .exists(), + true); + }); + + tearDownAll(() { + Process.runSync('rm', ['-rf', '${testingPath}lib']); + }); + }); +} diff --git a/test/lib/middleware/provider_test.dart b/test/lib/middleware/provider_test.dart new file mode 100644 index 00000000..12d11a67 --- /dev/null +++ b/test/lib/middleware/provider_test.dart @@ -0,0 +1,123 @@ +import 'dart:io'; +import 'package:mockito/mockito.dart'; +import 'package:parabeac_core/generation/generators/attribute-helper/pb_generator_context.dart'; +import 'package:parabeac_core/generation/generators/middleware/state_management/provider_middleware.dart'; +import 'package:parabeac_core/generation/generators/pb_generation_manager.dart'; +import 'package:parabeac_core/generation/generators/pb_generator.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_project_data.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_view_data.dart'; +import 'package:parabeac_core/generation/generators/value_objects/file_structure_strategy.dart/provider_file_structure_strategy.dart'; +import 'package:parabeac_core/generation/generators/writers/pb_flutter_writer.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_project.dart'; +import 'package:parabeac_core/interpret_and_optimize/state_management/directed_state_graph.dart'; +import 'package:parabeac_core/interpret_and_optimize/state_management/intermediate_auxillary_data.dart'; +import 'package:parabeac_core/interpret_and_optimize/state_management/intermediate_state.dart'; +import 'package:parabeac_core/interpret_and_optimize/state_management/intermediate_variation.dart'; +import 'package:test/test.dart'; + +class MockPBGenerationManager extends Mock implements PBGenerationManager {} + +class MockPBIntermediateNode extends Mock implements PBIntermediateNode {} + +class MockContext extends Mock implements PBContext {} + +class MockProject extends Mock implements PBProject {} + +class MockPBGenerationProjectData extends Mock + implements PBGenerationProjectData {} + +class MockPBGenerationViewData extends Mock implements PBGenerationViewData {} + +class MockPBGenerator extends Mock implements PBGenerator {} + +class MockIntermediateAuxiliaryData extends Mock + implements IntermediateAuxiliaryData {} + +class MockDirectedStateGraph extends Mock implements DirectedStateGraph {} + +class MockIntermediateState extends Mock implements IntermediateState {} + +class MockIntermediateVariation extends Mock implements IntermediateVariation {} + +void main() { + group('Middlewares Tests', () { + var testingPath = '${Directory.current.path}/test/lib/middleware/'; + var mockPBGenerationManager = MockPBGenerationManager(); + var providerMiddleware = ProviderMiddleware(mockPBGenerationManager); + var node = MockPBIntermediateNode(); + var node2 = MockPBIntermediateNode(); + var mockContext = MockContext(); + var mockProject = MockProject(); + var mockPBGenerationProjectData = MockPBGenerationProjectData(); + var mockPBGenerationViewData = MockPBGenerationViewData(); + var mockPBGenerator = MockPBGenerator(); + var providerFileStructureStrategy = ProviderFileStructureStrategy( + testingPath, + PBFlutterWriter(), + mockProject, + ); + var mockIntermediateAuxiliaryData = MockIntermediateAuxiliaryData(); + var mockDirectedStateGraph = MockDirectedStateGraph(); + var mockIntermediateState = MockIntermediateState(); + var mockIntermediateVariation = MockIntermediateVariation(); + + setUp(() async { + /// Nodes set up + // 1 + when(node.name).thenReturn('someElement/blue'); + when(node.generator).thenReturn(mockPBGenerator); + when(node.auxiliaryData).thenReturn(mockIntermediateAuxiliaryData); + when(node.managerData).thenReturn(mockPBGenerationViewData); + when(node.currentContext).thenReturn(mockContext); + // 2 + when(node2.name).thenReturn('someElement/green'); + when(node2.generator).thenReturn(mockPBGenerator); + + /// IntermediateAuxiliaryData + when(mockIntermediateAuxiliaryData.stateGraph) + .thenReturn(mockDirectedStateGraph); + + /// DirectedStateGraph + when(mockDirectedStateGraph.states).thenReturn([mockIntermediateState]); + + /// IntermediateState + when(mockIntermediateState.variation) + .thenReturn(mockIntermediateVariation); + + /// IntermediateVariation + when(mockIntermediateVariation.node).thenReturn(node2); + + /// PBGenerator + when(mockPBGenerator.generate(any, any)).thenReturn('code'); + + /// Context + when(mockContext.project).thenReturn(mockProject); + + /// Project + when(mockProject.genProjectData).thenReturn(mockPBGenerationProjectData); + when(mockProject.forest).thenReturn([]); + when(mockProject.fileStructureStrategy) + .thenReturn(providerFileStructureStrategy); + + /// PBGenerationManager + when(mockPBGenerationManager.generate(any)).thenReturn('code'); + + /// PBGenerationProjectData + when(mockPBGenerationProjectData.addDependencies('', '')).thenReturn(''); + }); + + test('Provider Strategy Test', () async { + await providerFileStructureStrategy.setUpDirectories(); + var tempNode = await providerMiddleware.applyMiddleware(node); + expect(tempNode is PBIntermediateNode, true); + expect(await File('${testingPath}lib/models/some_element.dart').exists(), + true); + }); + + tearDownAll(() { + Process.runSync('rm', ['-rf', '${testingPath}lib']); + }); + }); +} diff --git a/test/lib/middleware/stateful_test.dart b/test/lib/middleware/stateful_test.dart new file mode 100644 index 00000000..5b3f3181 --- /dev/null +++ b/test/lib/middleware/stateful_test.dart @@ -0,0 +1,118 @@ +import 'dart:io'; + +import 'package:mockito/mockito.dart'; +import 'package:parabeac_core/generation/generators/middleware/state_management/stateful_middleware.dart'; +import 'package:parabeac_core/generation/generators/pb_generation_manager.dart'; +import 'package:parabeac_core/generation/generators/pb_generator.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_project_data.dart'; +import 'package:parabeac_core/generation/generators/util/pb_generation_view_data.dart'; +import 'package:parabeac_core/generation/generators/value_objects/file_structure_strategy.dart/flutter_file_structure_strategy.dart'; +import 'package:parabeac_core/generation/generators/writers/pb_flutter_writer.dart'; +import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_context.dart'; +import 'package:parabeac_core/interpret_and_optimize/helpers/pb_project.dart'; +import 'package:test/test.dart'; +import 'provider_test.dart'; + +class MockPBGenerationManager extends Mock implements PBGenerationManager {} + +class MockPBIntermediateNode extends Mock implements PBIntermediateNode {} + +class MockContext extends Mock implements PBContext {} + +class MockProject extends Mock implements PBProject {} + +class MockPBGenerationProjectData extends Mock + implements PBGenerationProjectData {} + +class MockPBGenerationViewData extends Mock implements PBGenerationViewData {} + +class MockPBGenerator extends Mock implements PBGenerator {} + +void main() { + group('Middlewares Tests', () { + var testingPath = '${Directory.current.path}/test/lib/middleware/'; + var mockPBGenerationManager = MockPBGenerationManager(); + var bLoCMiddleware = StatefulMiddleware(mockPBGenerationManager); + var node = MockPBIntermediateNode(); + var node2 = MockPBIntermediateNode(); + var mockContext = MockContext(); + var mockProject = MockProject(); + var mockPBGenerationProjectData = MockPBGenerationProjectData(); + var mockPBGenerationViewData = MockPBGenerationViewData(); + var mockPBGenerator = MockPBGenerator(); + var mockFileStructureStrategy = FlutterFileStructureStrategy( + testingPath, + PBFlutterWriter(), + mockProject, + ); + var mockIntermediateAuxiliaryData = MockIntermediateAuxiliaryData(); + var mockDirectedStateGraph = MockDirectedStateGraph(); + var mockIntermediateState = MockIntermediateState(); + var mockIntermediateVariation = MockIntermediateVariation(); + + setUp(() async { + /// Set up nodes + when(node.name).thenReturn('someElement/blue'); + when(node.generator).thenReturn(mockPBGenerator); + when(node.managerData).thenReturn(mockPBGenerationViewData); + when(node.currentContext).thenReturn(mockContext); + when(node.auxiliaryData).thenReturn(mockIntermediateAuxiliaryData); + // 2 + when(node2.name).thenReturn('someElement/green'); + when(node2.generator).thenReturn(mockPBGenerator); + + /// IntermediateAuxiliaryData + when(mockIntermediateAuxiliaryData.stateGraph) + .thenReturn(mockDirectedStateGraph); + + /// DirectedStateGraph + when(mockDirectedStateGraph.states).thenReturn([mockIntermediateState]); + + /// IntermediateState + when(mockIntermediateState.variation) + .thenReturn(mockIntermediateVariation); + + /// IntermediateVariation + when(mockIntermediateVariation.node).thenReturn(node2); + + /// Context + when(mockContext.project).thenReturn(mockProject); + + /// Project + when(mockProject.genProjectData).thenReturn(mockPBGenerationProjectData); + when(mockProject.forest).thenReturn([]); + when(mockProject.fileStructureStrategy) + .thenReturn(mockFileStructureStrategy); + + /// PBGenerationManager + when(mockPBGenerationManager.generate(node)).thenReturn('codeForBlue\n'); + when(mockPBGenerationManager.generate(node2)) + .thenReturn('codeForGreen\n'); + + /// PBGenerationProjectData + when(mockPBGenerationProjectData.addDependencies(any, any)) + .thenReturn('mockDependency'); + }); + + test('Stateful Strategy Test', () async { + await mockFileStructureStrategy.setUpDirectories(); + var tempNode = await bLoCMiddleware.applyMiddleware(node); + expect(tempNode is PBIntermediateNode, true); + expect( + await File( + '${testingPath}lib/view/some_element_blue/some_element_blue.dart') + .exists(), + true); + expect( + await File( + '${testingPath}lib/view/some_element_blue/some_element_green.dart') + .exists(), + true); + }); + + tearDownAll(() { + Process.runSync('rm', ['-rf', '${testingPath}lib']); + }); + }); +} diff --git a/test/lib/output_services/png_gen_test.dart b/test/lib/output_services/png_gen_test.dart index 506a66b6..be0be362 100644 --- a/test/lib/output_services/png_gen_test.dart +++ b/test/lib/output_services/png_gen_test.dart @@ -2,9 +2,9 @@ import 'dart:convert'; import 'dart:io'; import 'package:parabeac_core/controllers/main_info.dart'; -import 'package:parabeac_core/input/sketch/helper/svg_png_convertion.dart'; +import 'package:parabeac_core/input/figma/helper/figma_asset_processor.dart'; +import 'package:parabeac_core/input/sketch/helper/sketch_asset_processor.dart'; import 'package:test/test.dart'; -import 'package:parabeac_core/input/figma/helper/image_helper.dart'; void main() async { var process; @@ -45,7 +45,7 @@ void main() async { test('Testing Image Conversion', () async { for (var uuid in uuids) { - var image = await convertImage(uuid, 23, 21); + var image = await SketchAssetProcessor().processImage(uuid, 23, 21); expect(image, isNot(null)); } }); @@ -67,7 +67,7 @@ void main() async { test('Testing Image Conversion', () async { for (var uuid in uuids) { - var image = await convertImage(uuid, 23, 21); + var image = await SketchAssetProcessor().processImage(uuid, 23, 21); expect(image, isNot(null)); } }); @@ -78,17 +78,20 @@ void main() async { MainInfo().figmaKey = Platform.environment['FIG_API_KEY']; MainInfo().figmaProjectID = 'zXXWPWb5wJXd0ImGUjEU1X'; MainInfo().outputPath = '${Directory.current.path}/test/tmp/'; - uuidQueue.addAll([ + var figmaUuids = [ '0:12', // Boolean operation '0:15', // Group '0:31', // Ellipse '0:57', // Rectangle - ]); + ]; + for (var uuid in figmaUuids) { + FigmaAssetProcessor().processImage(uuid); + } }); test('Testing Image Conversion', () async { - await processImageQueue(); - for (var uuid in uuidQueue) { + await FigmaAssetProcessor().processImageQueue(); + for (var uuid in FigmaAssetProcessor().uuidQueue) { expect( File('${MainInfo().outputPath}pngs/$uuid.png'.replaceAll(':', '_')) .existsSync(),