diff --git a/android/.idea/misc.xml b/android/.idea/misc.xml index 8bbe1216..ba7052b8 100644 --- a/android/.idea/misc.xml +++ b/android/.idea/misc.xml @@ -24,10 +24,10 @@ - + - + \ No newline at end of file diff --git a/android/syrnative/build.gradle b/android/syrnative/build.gradle index e3f7ea3f..9368053a 100644 --- a/android/syrnative/build.gradle +++ b/android/syrnative/build.gradle @@ -17,7 +17,7 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - buildToolsVersion '26.0.2' + buildToolsVersion '27.0.3' compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 diff --git a/lib/component.js b/lib/component.js index 97fb4658..a1e7782e 100644 --- a/lib/component.js +++ b/lib/component.js @@ -34,15 +34,17 @@ class Component { // send updated AST to raster // check to see that this instance is available before we attempt to update it - if(Render.getInstance(this.uuid)) { + if (Render.getInstance(this.uuid)) { this.render ? Render(this) : ''; if (cb) { cb(); } } else { - console.warn('Set state called, while component exited the component tree! >>>', this); + console.warn( + 'Set state called, while component exited the component tree! >>>', + this + ); } - }; } } diff --git a/lib/events.js b/lib/events.js index 36752b09..9d7e64f2 100644 --- a/lib/events.js +++ b/lib/events.js @@ -68,12 +68,14 @@ class events { let lifeCycleNotifiers = {}; let lifeCycleQueue = []; function handleLifeCycle(event, component) { + // console.log('Events', event, component) // todo: early exit logic, if we've crawled a parent alreadycd // then lets not crawl it again. let walk = (event, component) => { let handler = component[event.type] || (component.props && component.props[event.type]); + // console.log('handler>>>', handler) if (handler) { // if the component is currently already awaiting notification queue // then notify diff --git a/lib/rastermanager.js b/lib/rastermanager.js index d658ef79..fa0535dc 100644 --- a/lib/rastermanager.js +++ b/lib/rastermanager.js @@ -207,7 +207,6 @@ const initializeComponent = component => { const updateComponent = (component, rendered) => { function reflow(component, passedUpdates) { - let updates = []; let shouldComponentUpdate = true; let previousProps = (component.instance && component.instance.props) || {}; @@ -227,14 +226,17 @@ const updateComponent = (component, rendered) => { // console.log('setting props >>> ' + component.elementName + ' ' + JSON.stringify(component.instance.props) + ' --> ' + JSON.stringify(passedUpdates.attributes)) component.instance.setProps(passedUpdates.attributes); - if (component.instance.shouldComponentUpdate) { - shouldComponentUpdate = component.instance.shouldComponentUpdate.call(this, passedUpdates.attributes, component.instance.state); + shouldComponentUpdate = component.instance.shouldComponentUpdate.call( + this, + passedUpdates.attributes, + component.instance.state + ); } // --- component update start --- - if(shouldComponentUpdate) { + if (shouldComponentUpdate) { if (passedUpdates.attributes.style) { component.instance.style = passedUpdates.attributes.style; // console.log('updating styles >>> ' + component.elementName + '' + JSON.stringify(passedUpdates.attributes.style)) @@ -268,7 +270,6 @@ const updateComponent = (component, rendered) => { } if (updates.length > 0) { - updates = flattenChildren(updates); // get a fence id from the components children @@ -291,7 +292,6 @@ const updateComponent = (component, rendered) => { // check the cache if (typeof _cache[uuid] == 'undefined') { - // key is added during create component // not clean :shrug: - derek update.uuid = fenceid + '-' + update.guid; @@ -304,7 +304,7 @@ const updateComponent = (component, rendered) => { component.children.splice(index, 0, newComponent); } else { // update the component - reflow(_cache[uuid], update) + reflow(_cache[uuid], update); } // cache the update id's to verify if we need to unmount @@ -319,22 +319,23 @@ const updateComponent = (component, rendered) => { // if the component is not int he update tree // mark for removal - if(!updateIDs[child.instance.uuid]) { + if (!updateIDs[child.instance.uuid]) { child.unmount = true; // and remove from cache delete _cache[child.instance.uuid]; - } - else if(child.unmount) { + } else if (child.unmount) { // if we're reconciling a tree previously built, // remove any unmounts from the tree we marked last time component.children.splice(index, 1); } } - } if (component.instance && component.instance.componentDidUpdate) { - shouldComponentUpdate = component.instance.componentDidUpdate.call(this, previousProps); + shouldComponentUpdate = component.instance.componentDidUpdate.call( + this, + previousProps + ); } } @@ -346,7 +347,7 @@ const updateComponent = (component, rendered) => { reflow(component); component.update = true; - + // console.timeEnd("ui reconciled"); return component; }; diff --git a/lib/rasters/dom/animator.js b/lib/rasters/dom/animator.js index 97637d44..13bbe183 100644 --- a/lib/rasters/dom/animator.js +++ b/lib/rasters/dom/animator.js @@ -1,3 +1,5 @@ +import {DOMRaster} from './index'; + class animator { constructor() { this._animatedInstances = {}; @@ -12,64 +14,68 @@ class animator { this._animatedInstances[message.guid] = element; } const animationValues = message.animation; + const duration = animationValues.duration; const property = animationValues.animatedProperty; let fromValue = animationValues.value; let toValue = animationValues.toValue; - let keyframes = []; + let transform; if (property) { switch (true) { case /opacity/.test(property): { - keyframes = [{ opacity: fromValue }, { opacity: toValue }]; + transform = null; break; } case /height/.test(property): { - fromValue = element.style.height; - toValue = `${toValue}px`; - keyframes = [{ height: fromValue }, { height: toValue }]; + transform = `translateY(${toValue}px)`; break; } case /width/.test(property): { - fromValue = element.style.width; - toValue = `${toValue}px`; - keyframes = [{ width: fromValue }, { width: toValue }]; + transform = `translateX(${toValue}px)`; break; } case /rotate|rotate[XYZ]/.test(property): { - keyframes = [ - { - transform: `${property}(${fromValue}deg)`, - }, - { - transform: `${property}(${toValue}deg)`, - }, - ]; + let value = toValue; + + let fullRotation = value % 360 == 0 ? true : false; + + // match axis to get current rotation angle + let re = /(rotateZ)(\(.*(?:deg\)))/g; + let degrees = element.style.webkitTransform.match(re); + if (degrees && degrees.length > 0) { + degrees = parseInt(degrees[0].replace(/^\D+/gi, '')); + } + + // get the value of the next rotation from current value + value = value + degrees; + transform = `${property}(${value}deg)`; break; } } - } else { - //default to z animations A.K.A rotate - keyframes = [ - { transform: `rotateZ(${fromValue}deg)` }, - { transform: `rotateZ(${toValue}deg)` }, - ]; } - let animation = element.animate(keyframes, { - duration: animationValues.duration, - fill: 'both', - composite: 'add', - }); - animation.onfinish = () => { - //@TODO Looking for alternatives to remove this. - if (property == 'height' || property == 'width') { - element.style[property] = toValue; - } - SyrEvents.emit({ - type: 'animationComplete', - guid: message.guid, - animation: message.animation, - }); + let handler = () => { + // remove handler + element.removeEventListener(`transitionend`, handler); + // callback + setTimeout(() => { + SyrEvents.emit({ + type: 'animationComplete', + guid: message.guid, + animation: message.animation, + }); + }, 0); }; + // add call back + element.addEventListener(`transitionend`, handler, false); + + // animate + element.style.transition = `all ${duration / 1000 || 0}s`; + element.style.transitionTimingFunction = 'linear'; + if (transform) { + element.style.transform = transform; + } else { + element.style.opacity = toValue; + } } animateComponentXY(message) { @@ -82,6 +88,7 @@ class animator { } const animationValues = message.animation; + const duration = `all ${animationValues.duration / 1000 || 1}s`; const x = animationValues.x || 0; const x2 = animationValues.x2 || 0; @@ -89,29 +96,27 @@ class animator { const y2 = animationValues.y2 || 0; let destinationY = y > y2 ? y2 - y : y2 + y; - let destinationX = x > x2 ? x2 - y : x2 + x; - - let animation = element.animate( - [ - { transform: `translateX(${x}px) translateY(${y}px)` }, - { - transform: `translateX(${destinationX}px) translateY(${destinationY}px)`, - }, - ], - { - duration: animationValues.duration, - fill: 'both', - composite: 'add', - } - ); - - animation.onfinish = () => { - SyrEvents.emit({ - type: 'animationComplete', - guid: message.guid, - animation: message.animation, - }); + + // set the call back + let handler = () => { + // remove handler + element.removeEventListener('transitionend', handler); + // callback + setTimeout(() => { + SyrEvents.emit({ + type: 'animationComplete', + guid: message.guid, + animation: message.animation, + }); + }, 0); }; + // add call back + element.addEventListener('transitionend', handler, false); + + // animate + element.style.transition = duration; + element.style.transitionTimingFunction = 'linear'; + element.style.transform = `translate(${x2}px, ${destinationY}px)`; } animate(message) { diff --git a/lib/rasters/dom/index.js b/lib/rasters/dom/index.js index dcd8cf67..321c8cdf 100644 --- a/lib/rasters/dom/index.js +++ b/lib/rasters/dom/index.js @@ -1,4 +1,5 @@ import { Raster } from './raster'; +import { RasterUtils } from '../rasterutils'; const document = global.document || { body: { @@ -37,6 +38,9 @@ class domraster { } props() { + if (RasterUtils.props && RasterUtils.props.initial_props) { + return JSON.parse(RasterUtils.props.initial_props); + } return {}; } } diff --git a/lib/rasters/dom/raster.js b/lib/rasters/dom/raster.js index 22b1d465..731f2495 100644 --- a/lib/rasters/dom/raster.js +++ b/lib/rasters/dom/raster.js @@ -6,13 +6,7 @@ let _instances = {}; class raster { parseAST(ast, target) { if (!ast.update) { - this.build(ast, target, () => { - console.log('uuid', ast.uuid); - SyrEvents.emit({ - type: 'componentDidMount', - guid: ast.uuid, - }); - }); + this.build(ast, target); } else { this.update(ast, target); } @@ -20,7 +14,7 @@ class raster { setupAnimation(ast) { Animator.animate(ast); } - build(ast, target, cb) { + build(ast, target) { let instance = this.createComponent(ast); let renderTarget = target ? target : document.body; renderTarget = @@ -30,34 +24,51 @@ class raster { if (instance) { renderTarget.appendChild(instance); _instances[ast.instance.uuid] = instance; - cb(); if (ast.children) { this.buildChidren(ast, instance, ast.update); + SyrEvents.emit({ + type: 'componentDidMount', + guid: ast.uuid, + }); } } else { - this.build(ast.children[0], target, cb); + this.build(ast.children[0], renderTarget); + SyrEvents.emit({ + type: 'componentDidMount', + guid: ast.uuid, + }); } } buildChidren(component, parent, isUpdate) { - // console.log('Children >>>', component, parent) component.children.forEach(element => { - let component; + let component = element; if (element.instance && element.instance.tag) { component = element; } else if (element.children) { component = element.children[0]; + SyrEvents.emit({ + type: 'componentDidMount', + guid: element.instance.uuid, + }); } let instance = this.createComponent(component); if (instance) { parent.appendChild(instance); _instances[component.instance.uuid] = instance; + // console.log('Component did mount', component) + if (component.children) { + this.buildChidren(component, instance); + } SyrEvents.emit({ type: 'componentDidMount', guid: component.instance.uuid, }); - } - if (component.children) { - this.buildChidren(component, instance); + }else { + this.build(ast.children[0], renderTarget); + SyrEvents.emit({ + type: 'componentDidMount', + guid: ast.uuid, + }); } }); } @@ -114,18 +125,18 @@ class raster { }); renderTarget.removeChild(document.getElementById(uuid)); } else { - let parent = document.getElementById(uuid); + // let parent = document.getElementById(uuid); component.children.forEach(child => { let childUuid = child.instance.uuid; let childCachedInstance = _instances[childUuid]; let unMountChildInstance = component.unmount; if (unMountChildInstance) { - delete _inistances[childUuid]; + delete _instances[childUuid]; SyrEvents.emit({ type: 'componentWillUnMount', guid: uuid, }); - parent.removeChild(document.getElementById(childUuid)); + renderTarget.removeChild(document.getElementById(childUuid)); } }); } @@ -143,6 +154,7 @@ class raster { if (newInstance) { viewParent.appendChild(newInstance); _instances[component.instance.uuid] = newInstance; + console.log('Conponent Did mount'); SyrEvents.emit({ type: 'componentDidMount', guid: component.instance.uuid, diff --git a/samples/addRemoveItem.js b/samples/addRemoveItem.js index a5012278..03f13fa5 100644 --- a/samples/addRemoveItem.js +++ b/samples/addRemoveItem.js @@ -58,7 +58,7 @@ class example extends Component { backgroundColor: '#09aea4', }} > - {this.state.components} + {this.state.components}