Skip to content
This repository has been archived by the owner on Jan 25, 2024. It is now read-only.

Commit

Permalink
Merge pull request #629 from Parabeac/release/2.7.0
Browse files Browse the repository at this point in the history
Release/2.7.0
  • Loading branch information
ivan-015 committed Apr 6, 2022
2 parents 4987480 + 06a5f99 commit b812f70
Show file tree
Hide file tree
Showing 57 changed files with 1,055 additions and 2,728 deletions.
6 changes: 3 additions & 3 deletions .mergify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ pull_request_rules:
- name: Backport PR to dev if merging to stable
conditions:
- base=stable
- "#approved-reviews-by>=2" #Two approvals needed
- "#approved-reviews-by>=1"
actions:
backport:
branches: ["dev"]

- name: Merge pull request on two approvals
- name: Merge pull request on approval
conditions:
- "#approved-reviews-by>=2" # Two approvals needed
- "#approved-reviews-by>=1"
- -closed
- label!=review-required # Only merge PRs that are NOT labeled review-required.
actions:
Expand Down
16 changes: 16 additions & 0 deletions lib/analytics/analytics_constants.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const RUN_PARABEAC = 'Run Parabeac';

/// Interpretation
const INTERPRETATION = 'Interpretation';
const HANDLE_CHILDREN = 'Handle Children';
const INTERMEDIATE_SERVICES = 'Intermediate Services';

/// Generation
const GENERATION = 'Generation';
const COMMAND_QUEUE = 'Command Queue';
const GEN_DRY_RUN = 'Gen AIT Dry Run';
const GEN_AIT = 'Gen AIT';

/// Misc
const PRE_GEN = 'Pre Gen Tasks';
const POST_GEN = 'Post Gen Tasks';
56 changes: 56 additions & 0 deletions lib/analytics/sentry_analytics_service.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import 'package:quick_log/quick_log.dart';
import 'package:sentry/sentry.dart';

/// Class that uses Sentry to log transactions.
///
/// These transactions are meant to track performance throughout parabeac_core.
class SentryService {
static final _logger = Logger('$SentryService');
static var transactions = <String, ISentrySpan>{};

/// Starts a main transaction.
///
/// The [id] is the unique name of the transaction. The [operation] is what is being performed.
/// The optional [description] is used to provide more context on the [operation] within Sentry.
static void startTransaction(String id, String operation,
{String description}) {
if (!transactions.containsKey(id)) {
final transaction =
Sentry.startTransaction(id, operation, description: description);

transactions[id] = transaction;
} else {
_logger
.error('Transaction $id already exists. Cannot start transaction.');
}
}

/// Starts a child transaction from a parent transaction with a unique [id].
///
/// The [id] refers to the `parent` transaction.
/// The [operation] is what the `child` transaction is performing, and must be unique.
/// The optional [description] is used to provide more context on the [operation] within Sentry.
static void startChildTransactionFrom(String id, String operation,
{String description}) {
if (transactions.containsKey(id) && !transactions.containsKey(operation)) {
final transaction =
transactions[id].startChild(operation, description: description);

transactions[operation] = transaction;
} else {
_logger.error(
'Transaction \"$id\" does not exist or transaction \"$operation\" already exists. Cannot start child transaction.');
}
}

/// Finishes transaction with a unique [id].
static Future<void> finishTransaction(String id) async {
if (transactions.containsKey(id)) {
await transactions[id].finish();
transactions.remove(id);
} else {
_logger
.error('Transaction $id does not exist. Cannot finish transaction.');
}
}
}
9 changes: 9 additions & 0 deletions lib/controllers/interpret.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'package:parabeac_core/analytics/analytics_constants.dart';
import 'package:parabeac_core/analytics/sentry_analytics_service.dart';
import 'package:parabeac_core/controllers/main_info.dart';
import 'package:parabeac_core/generation/prototyping/pb_prototype_linker_service.dart';
import 'package:parabeac_core/interpret_and_optimize/entities/layouts/group/base_group.dart';
Expand Down Expand Up @@ -153,6 +155,11 @@ class AITServiceBuilder {
var transformation = transformationTuple.item2;
var name = transformationTuple.item1;

SentryService.startChildTransactionFrom(
INTERMEDIATE_SERVICES,
name,
description: 'Applying transformation: $name',
);
_stopwatch.start();
log.debug('Started running $name...');
try {
Expand All @@ -179,10 +186,12 @@ class AITServiceBuilder {
log.error('${e.toString()} at $name');
} finally {
_stopwatch.stop();
await SentryService.finishTransaction(name);
log.debug(
'Stoped running $name (${_stopwatch.elapsed.inMilliseconds})');
}
}

log.fine('Finish transforming $treeName');
return _intermediateTree;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,54 @@ class PBBoxDecorationHelper extends PBAttributesHelper {

@override
String generate(PBIntermediateNode source, PBContext generatorContext) {
if (source is PBContainer) {
final buffer = StringBuffer();
buffer.write('decoration: BoxDecoration(');
var borderInfo = source.auxiliaryData.borderInfo;
var effectsInfo = source.auxiliaryData.effects;
var colors = source.auxiliaryData.colors;
if (colors != null && colors.isNotEmpty) {
buffer.write(PBColorGenHelper().generate(source, generatorContext));
final buffer = StringBuffer();
buffer.write('decoration: BoxDecoration(');
var borderInfo = source.auxiliaryData.borderInfo;
var effectsInfo = source.auxiliaryData.effects;
var colors = source.auxiliaryData.colors;
if (colors != null && colors.isNotEmpty) {
buffer.write(PBColorGenHelper().generate(source, generatorContext));
}
if (borderInfo != null) {
if (borderInfo.borderRadius != null) {
// Write border radius if it exists
buffer.write(
'borderRadius: BorderRadius.all(Radius.circular(${borderInfo.borderRadius})),');
} else if (borderInfo.type == 'circle') {
buffer.write('shape: BoxShape.circle,');
}
if (borderInfo != null) {
if (borderInfo.borderRadius != null) {
// Write border radius if it exists
buffer.write(
'borderRadius: BorderRadius.all(Radius.circular(${borderInfo.borderRadius})),');
} else if (borderInfo.type == 'circle') {
buffer.write('shape: BoxShape.circle,');
}

// Write border outline properties if applicable
if (borderInfo.thickness > 0 && borderInfo.visible) {
buffer.write('border: Border.all(');
if (borderInfo.color != null) {
buffer.write('color: Color(${borderInfo.color.toString()}),');
}
buffer.write('width: ${borderInfo.thickness},');
buffer.write('),'); // end of Border.all(
// Write border outline properties if applicable
if (borderInfo.thickness > 0 && borderInfo.visible) {
buffer.write('border: Border.all(');
if (borderInfo.color != null) {
buffer.write('color: Color(${borderInfo.color.toString()}),');
}
buffer.write('width: ${borderInfo.thickness},');
buffer.write('),'); // end of Border.all(
}
}

if (effectsInfo != null &&
effectsInfo.isNotEmpty &&
effectsInfo.first.type.toLowerCase().contains('shadow')) {
buffer.write('boxShadow: [');
if (effectsInfo != null &&
effectsInfo.isNotEmpty &&
effectsInfo.first.type.toLowerCase().contains('shadow')) {
buffer.write('boxShadow: [');

for (var effect in effectsInfo) {
buffer.write('''
for (var effect in effectsInfo) {
buffer.write('''
BoxShadow(
${PBColorGenHelper().getHexColor(effect.color)}
spreadRadius: ${effect.radius},
blurRadius: ${effect.radius},
offset: Offset(${effect.offset['x']}, ${effect.offset['y']}),
),
''');
}

buffer.write('],');
}
buffer.write('),');

return buffer.toString();
buffer.write('],');
}
return '';
buffer.write('),');

return buffer.toString();
}
}
4 changes: 4 additions & 0 deletions lib/generation/generators/symbols/pb_mastersym_gen.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:parabeac_core/generation/generators/attribute-helper/pb_box_decoration_gen_helper.dart';
import 'package:parabeac_core/generation/generators/pb_generator.dart';
import 'package:parabeac_core/generation/generators/value_objects/template_strategy/stateful_template_strategy.dart';
import 'package:parabeac_core/interpret_and_optimize/entities/pb_shared_master_node.dart';
Expand Down Expand Up @@ -30,7 +31,10 @@ class PBMasterSymbolGenerator extends PBGenerator {
if (generatedWidget == null || generatedWidget.isEmpty) {
return '';
}
var decoration = PBBoxDecorationHelper().generate(source, context);
buffer.write('Container($decoration child:');
buffer.write(generatedWidget);
buffer.write(')');
return buffer.toString();
} else {
return '';
Expand Down
2 changes: 0 additions & 2 deletions lib/interpret_and_optimize/entities/inherited_circle.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions lib/interpret_and_optimize/entities/inherited_material.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions lib/interpret_and_optimize/entities/inherited_scaffold.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ class PBIntermediateTree extends DirectedGraph<PBIntermediateNode> {
/// Finds a [PBIntermediateNode] that is a child of `parent` of `type` in the [PBIntermediateTree], containing `name`.
///
/// Returns null if not found.
PBIntermediateNode findChild(PBIntermediateNode parent, String name, Type type) {
@Deprecated('Use `this.where()` instead')
PBIntermediateNode findChild(
PBIntermediateNode parent, String name, Type type) {
/// Check if the node is a match
if (parent.name.contains(name) && parent.runtimeType == type) {
return parent;
Expand Down Expand Up @@ -260,6 +262,25 @@ class PBIntermediateTree extends DirectedGraph<PBIntermediateNode> {
return true;
}

/// Inserts [insertee] between [parent] and [child].
///
/// As a side effect, [insertee] will be the new parent of [child].
/// Additionally, [insertee] will be the new child of [parent].
void injectBetween(
{PBIntermediateNode parent,
PBIntermediateNode child,
PBIntermediateNode insertee}) {
assert(parent != null && child != null && insertee != null);

addEdges(insertee, [child]);
removeEdges(parent, [child]);
addEdges(parent, [insertee]);

if(child.parent != insertee || insertee.parent != parent) {
_logger.warning('Injecting `insertee` may have had side effects on the graph.');
}
}

/// Checks if the [PBIntermediateTree] is a [TREE_TYPE.SCREEN],
/// meaning that the [rootNode] is of type [InheritedScaffold]
bool isScreen() => tree_type == TREE_TYPE.SCREEN;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:parabeac_core/interpret_and_optimize/entities/layouts/rules/layo
import 'package:parabeac_core/interpret_and_optimize/entities/layouts/rules/stack_reduction_visual_rule.dart';
import 'package:parabeac_core/interpret_and_optimize/entities/layouts/stack.dart';
import 'package:parabeac_core/interpret_and_optimize/entities/layouts/group/group.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_constraints.dart';
import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_intermediate_node.dart';
import 'package:parabeac_core/interpret_and_optimize/entities/subclasses/pb_layout_intermediate_node.dart';
Expand Down Expand Up @@ -73,6 +74,9 @@ class PBLayoutGenerationService extends AITHandler {
_applyPostConditionRules(tree.rootNode, context);

_wrapLayout(tree, context);
if (tree.rootNode is PBSharedMasterNode) {
_applyComponentRules(tree, tree.rootNode);
}
return Future.value(tree);
} catch (e, stackTrace) {
await Sentry.captureException(e, stackTrace: stackTrace);
Expand All @@ -82,6 +86,31 @@ class PBLayoutGenerationService extends AITHandler {
}
}

/// Method that applies specific layout rules that only apply to the [PBSharedMasterNode]s.
///
/// Namely, when a [PBSharedMasterNode] has only one child, we need to inject
/// a stack to ensure alignment.
void _applyComponentRules(
PBIntermediateTree tree, PBSharedMasterNode component) {
if (tree.childrenOf(component).length == 1 &&
tree.childrenOf(component).first is! Group) {
var child = tree.childrenOf(component).first;

/// TODO: Improve the way we create Stacks
var stack = PBIntermediateStackLayout(
name: component.name,
constraints: component.constraints.copyWith(),
)
..auxiliaryData = component.auxiliaryData
..frame = component.frame.copyWith()
..layoutCrossAxisSizing = component.layoutCrossAxisSizing
..layoutMainAxisSizing = component.layoutMainAxisSizing;

/// Insert the stack below the component.
tree.injectBetween(insertee: stack, parent: component, child: child);
}
}

void _wrapLayout(PBIntermediateTree tree, PBContext context) {
// Get all the LayoutIntermediateNodes from the tree
tree.whereType<PBLayoutIntermediateNode>().forEach((tempGroup) {
Expand Down Expand Up @@ -200,7 +229,15 @@ class PBLayoutGenerationService extends AITHandler {
/// This conditional statement is to not mixup the elements that pertain to different [currentNode.attributeName].
/// For example, if [currentNode.attributeName] is an `appBar` and [nextNode.attributeName] is a `stack`,
/// then you would not generate a [PBLayoutIntermediateNode] to encapsulate them both.
if (currentNode.attributeName != nextNode.attributeName) {
///
/// currentNode and parent shall be skipped if they are either a Row or Column
/// because they should not be interpreted as Stack even though, their children
/// are too close to each other.
if (currentNode.attributeName != nextNode.attributeName ||
currentNode is PBIntermediateColumnLayout ||
currentNode is PBIntermediateRowLayout ||
parent is PBIntermediateColumnLayout ||
parent is PBIntermediateRowLayout) {
break;
}
if (layout.satisfyRules(context, currentNode, nextNode) &&
Expand Down
Loading

0 comments on commit b812f70

Please sign in to comment.