atome 0.1.0 → 0.1.00002

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).popmotion={})}(this,(function(t){"use strict";function e(t,e){var n={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(r=Object.getOwnPropertySymbols(t);o<r.length;o++)e.indexOf(r[o])<0&&Object.prototype.propertyIsEnumerable.call(t,r[o])&&(n[r[o]]=t[r[o]])}return n}const n=(t,e,n)=>Math.min(Math.max(n,t),e),r=.001;function o({duration:t=800,bounce:e=.25,velocity:o=0,mass:a=1}){let i,c,u=1-e;u=n(.05,1,u),t=n(.01,10,t/1e3),u<1?(i=e=>{const n=e*u,a=n*t,i=n-o,c=s(e,u),l=Math.exp(-a);return r-i/c*l},c=e=>{const n=e*u*t,a=n*o+o,c=Math.pow(u,2)*Math.pow(e,2)*t,l=Math.exp(-n),p=s(Math.pow(e,2),u);return(-i(e)+r>0?-1:1)*((a-c)*l)/p}):(i=e=>Math.exp(-e*t)*((e-o)*t+1)-.001,c=e=>Math.exp(-e*t)*(t*t*(o-e)));const l=function(t,e,n){let r=n;for(let n=1;n<12;n++)r-=t(r)/e(r);return r}(i,c,5/t);if(t*=1e3,isNaN(l))return{stiffness:100,damping:10,duration:t};{const e=Math.pow(l,2)*a;return{stiffness:e,damping:2*u*Math.sqrt(a*e),duration:t}}}function s(t,e){return t*Math.sqrt(1-e*e)}const a=["duration","bounce"],i=["stiffness","damping","mass"];function c(t,e){return e.some((e=>void 0!==t[e]))}function u(t){var{from:n=0,to:r=1,restSpeed:u=2,restDelta:p}=t,f=e(t,["from","to","restSpeed","restDelta"]);const d={done:!1,value:n};let{stiffness:h,damping:m,mass:g,velocity:y,duration:b,isResolvedFromDuration:M}=function(t){let e=Object.assign({velocity:0,stiffness:100,damping:10,mass:1,isResolvedFromDuration:!1},t);if(!c(t,i)&&c(t,a)){const n=o(t);e=Object.assign(Object.assign(Object.assign({},e),n),{velocity:0,mass:1}),e.isResolvedFromDuration=!0}return e}(f),v=l,O=l;function x(){const t=y?-y/1e3:0,e=r-n,o=m/(2*Math.sqrt(h*g)),a=Math.sqrt(h/g)/1e3;if(void 0===p&&(p=Math.min(Math.abs(r-n)/100,.4)),o<1){const n=s(a,o);v=s=>{const i=Math.exp(-o*a*s);return r-i*((t+o*a*e)/n*Math.sin(n*s)+e*Math.cos(n*s))},O=r=>{const s=Math.exp(-o*a*r);return o*a*s*(Math.sin(n*r)*(t+o*a*e)/n+e*Math.cos(n*r))-s*(Math.cos(n*r)*(t+o*a*e)-n*e*Math.sin(n*r))}}else if(1===o)v=n=>r-Math.exp(-a*n)*(e+(t+a*e)*n);else{const n=a*Math.sqrt(o*o-1);v=s=>{const i=Math.exp(-o*a*s),c=Math.min(n*s,300);return r-i*((t+o*a*e)*Math.sinh(c)+n*e*Math.cosh(c))/n}}}return x(),{next:t=>{const e=v(t);if(M)d.done=t>=b;else{const n=1e3*O(t),o=Math.abs(n)<=u,s=Math.abs(r-e)<=p;d.done=o&&s}return d.value=d.done?r:e,d},flipTarget:()=>{y=-y,[n,r]=[r,n],x()}}}u.needsInterpolation=(t,e)=>"string"==typeof t||"string"==typeof e;const l=t=>0,p=(t,e,n)=>{const r=e-t;return 0===r?1:(n-t)/r},f=(t,e,n)=>-n*t+n*e+t,d=(t,e)=>n=>Math.max(Math.min(n,e),t),h=t=>t%1?Number(t.toFixed(5)):t,m=/(-)?([\d]*\.?[\d])+/g,g=/(#[0-9a-f]{6}|#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2,3}\s*\/*\s*[\d\.]+%?\))/gi,y=/^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2,3}\s*\/*\s*[\d\.]+%?\))$/i;function b(t){return"string"==typeof t}const M={test:t=>"number"==typeof t,parse:parseFloat,transform:t=>t},v=Object.assign(Object.assign({},M),{transform:d(0,1)});Object.assign(Object.assign({},M),{default:1});const O=(x="%",{test:t=>b(t)&&t.endsWith(x)&&1===t.split(" ").length,parse:parseFloat,transform:t=>`${t}${x}`});var x;Object.assign(Object.assign({},O),{parse:t=>O.parse(t)/100,transform:t=>O.transform(100*t)});const w=(t,e)=>n=>Boolean(b(n)&&y.test(n)&&n.startsWith(t)||e&&Object.prototype.hasOwnProperty.call(n,e)),j=(t,e,n)=>r=>{if(!b(r))return r;const[o,s,a,i]=r.match(m);return{[t]:parseFloat(o),[e]:parseFloat(s),[n]:parseFloat(a),alpha:void 0!==i?parseFloat(i):1}},I={test:w("hsl","hue"),parse:j("hue","saturation","lightness"),transform:({hue:t,saturation:e,lightness:n,alpha:r=1})=>"hsla("+Math.round(t)+", "+O.transform(h(e))+", "+O.transform(h(n))+", "+h(v.transform(r))+")"},A=d(0,255),D=Object.assign(Object.assign({},M),{transform:t=>Math.round(A(t))}),P={test:w("rgb","red"),parse:j("red","green","blue"),transform:({red:t,green:e,blue:n,alpha:r=1})=>"rgba("+D.transform(t)+", "+D.transform(e)+", "+D.transform(n)+", "+h(v.transform(r))+")"};const S={test:w("#"),parse:function(t){let e="",n="",r="",o="";return t.length>5?(e=t.substr(1,2),n=t.substr(3,2),r=t.substr(5,2),o=t.substr(7,2)):(e=t.substr(1,1),n=t.substr(2,1),r=t.substr(3,1),o=t.substr(4,1),e+=e,n+=n,r+=r,o+=o),{red:parseInt(e,16),green:parseInt(n,16),blue:parseInt(r,16),alpha:o?parseInt(o,16)/255:1}},transform:P.transform},T=t=>P.test(t)||S.test(t)||I.test(t),F=t=>P.test(t)?P.parse(t):I.test(t)?I.parse(t):S.parse(t),R=t=>b(t)?t:t.hasOwnProperty("red")?P.transform(t):I.transform(t),C="${c}",k="${n}";function q(t){"number"==typeof t&&(t=`${t}`);const e=[];let n=0;const r=t.match(g);r&&(n=r.length,t=t.replace(g,C),e.push(...r.map(F)));const o=t.match(m);return o&&(t=t.replace(m,k),e.push(...o.map(M.parse))),{values:e,numColors:n,tokenised:t}}function N(t){return q(t).values}function $(t){const{values:e,numColors:n,tokenised:r}=q(t),o=e.length;return t=>{let e=r;for(let r=0;r<o;r++)e=e.replace(r<n?C:k,r<n?R(t[r]):h(t[r]));return e}}const B=t=>"number"==typeof t?0:t;const E={test:function(t){var e,n,r,o;return isNaN(t)&&b(t)&&(null!==(n=null===(e=t.match(m))||void 0===e?void 0:e.length)&&void 0!==n?n:0)+(null!==(o=null===(r=t.match(g))||void 0===r?void 0:r.length)&&void 0!==o?o:0)>0},parse:N,createTransformer:$,getAnimatableNone:function(t){const e=N(t);return $(t)(e.map(B))}};function U(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+(e-t)*(2/3-n)*6:t}function z({hue:t,saturation:e,lightness:n,alpha:r}){t/=360,n/=100;let o=0,s=0,a=0;if(e/=100){const r=n<.5?n*(1+e):n+e-n*e,i=2*n-r;o=U(i,r,t+1/3),s=U(i,r,t),a=U(i,r,t-1/3)}else o=s=a=n;return{red:Math.round(255*o),green:Math.round(255*s),blue:Math.round(255*a),alpha:r}}const G=(t,e,n)=>{const r=t*t,o=e*e;return Math.sqrt(Math.max(0,n*(o-r)+r))},H=[S,P,I],L=t=>H.find((e=>e.test(t))),W=(t,e)=>{let n=L(t),r=L(e),o=n.parse(t),s=r.parse(e);n===I&&(o=z(o),n=P),r===I&&(s=z(s),r=P);const a=Object.assign({},o);return t=>{for(const e in a)"alpha"!==e&&(a[e]=G(o[e],s[e],t));return a.alpha=f(o.alpha,s.alpha,t),n.transform(a)}},_={x:0,y:0,z:0},V=t=>"number"==typeof t,J=(t,e)=>n=>e(t(n)),K=(...t)=>t.reduce(J);function Q(t,e){return V(t)?n=>f(t,e,n):T(t)?W(t,e):tt(t,e)}const X=(t,e)=>{const n=[...t],r=n.length,o=t.map(((t,n)=>Q(t,e[n])));return t=>{for(let e=0;e<r;e++)n[e]=o[e](t);return n}},Y=(t,e)=>{const n=Object.assign(Object.assign({},t),e),r={};for(const o in n)void 0!==t[o]&&void 0!==e[o]&&(r[o]=Q(t[o],e[o]));return t=>{for(const e in r)n[e]=r[e](t);return n}};function Z(t){const e=E.parse(t),n=e.length;let r=0,o=0,s=0;for(let t=0;t<n;t++)r||"number"==typeof e[t]?r++:void 0!==e[t].hue?s++:o++;return{parsed:e,numNumbers:r,numRGB:o,numHSL:s}}const tt=(t,e)=>{const n=E.createTransformer(e),r=Z(t),o=Z(e);return r.numHSL===o.numHSL&&r.numRGB===o.numRGB&&r.numNumbers>=o.numNumbers?K(X(r.parsed,o.parsed),n):n=>`${n>0?e:t}`},et=(t,e)=>n=>f(t,e,n);function nt(t,e,n){const r=[],o=n||("number"==typeof(s=t[0])?et:"string"==typeof s?T(s)?W:tt:Array.isArray(s)?X:"object"==typeof s?Y:void 0);var s;const a=t.length-1;for(let n=0;n<a;n++){let s=o(t[n],t[n+1]);if(e){const t=Array.isArray(e)?e[n]:e;s=K(t,s)}r.push(s)}return r}function rt(t,e,{clamp:r=!0,ease:o,mixer:s}={}){const a=t.length;e.length,!o||!Array.isArray(o)||o.length,t[0]>t[a-1]&&(t=[].concat(t),e=[].concat(e),t.reverse(),e.reverse());const i=nt(e,o,s),c=2===a?function([t,e],[n]){return r=>n(p(t,e,r))}(t,i):function(t,e){const n=t.length,r=n-1;return o=>{let s=0,a=!1;if(o<=t[0]?a=!0:o>=t[r]&&(s=r-1,a=!0),!a){let e=1;for(;e<n&&!(t[e]>o||e===r);e++);s=e-1}const i=p(t[s],t[s+1],o);return e[s](i)}}(t,i);return r?e=>c(n(t[0],t[a-1],e)):c}const ot=t=>e=>1-t(1-e),st=t=>e=>e<=.5?t(2*e)/2:(2-t(2*(1-e)))/2,at=t=>e=>Math.pow(e,t),it=t=>e=>e*e*((t+1)*e-t),ct=t=>{const e=it(t);return t=>(t*=2)<1?.5*e(t):.5*(2-Math.pow(2,-10*(t-1)))},ut=t=>t,lt=at(2),pt=ot(lt),ft=st(lt),dt=t=>1-Math.sin(Math.acos(t)),ht=ot(dt),mt=st(ht),gt=it(1.525),yt=ot(gt),bt=st(gt),Mt=ct(1.525),vt=t=>{if(1===t||0===t)return t;const e=t*t;return t<.36363636363636365?7.5625*e:t<.7272727272727273?9.075*e-9.9*t+3.4:t<.9?12.066481994459833*e-19.63545706371191*t+8.898060941828255:10.8*t*t-20.52*t+10.72},Ot=ot(vt);function xt(t,e){return t.map((()=>e||ft)).splice(0,t.length-1)}function wt({from:t=0,to:e=1,ease:n,offset:r,duration:o=300}){const s={done:!1,value:t},a=Array.isArray(e)?e:[t,e],i=function(t,e){return t.map((t=>t*e))}(r&&r.length===a.length?r:function(t){const e=t.length;return t.map(((t,n)=>0!==n?n/(e-1):0))}(a),o);function c(){return rt(i,a,{ease:Array.isArray(n)?n:xt(a,n)})}let u=c();return{next:t=>(s.value=u(t),s.done=t>=o,s),flipTarget:()=>{a.reverse(),u=c()}}}function jt({velocity:t=0,from:e=0,power:n=.8,timeConstant:r=350,restDelta:o=.5,modifyTarget:s}){const a={done:!1,value:e};let i=n*t;const c=e+i,u=void 0===s?c:s(c);return u!==c&&(i=u-e),{next:t=>{const e=-i*Math.exp(-t/r);return a.done=!(e>o||e<-o),a.value=a.done?u:u+e,a},flipTarget:()=>{}}}const It={keyframes:wt,spring:u,decay:jt};const At=1/60*1e3,Dt="undefined"!=typeof performance?()=>performance.now():()=>Date.now(),Pt="undefined"!=typeof window?t=>window.requestAnimationFrame(t):t=>setTimeout((()=>t(Dt())),At);let St=!0,Tt=!1,Ft=!1;const Rt={delta:0,timestamp:0},Ct=["read","update","preRender","render","postRender"],kt=Ct.reduce(((t,e)=>(t[e]=function(t){let e=[],n=[],r=0,o=!1,s=!1;const a=new WeakSet,i={schedule:(t,s=!1,i=!1)=>{const c=i&&o,u=c?e:n;return s&&a.add(t),-1===u.indexOf(t)&&(u.push(t),c&&o&&(r=e.length)),t},cancel:t=>{const e=n.indexOf(t);-1!==e&&n.splice(e,1),a.delete(t)},process:c=>{if(o)s=!0;else{if(o=!0,[e,n]=[n,e],n.length=0,r=e.length,r)for(let n=0;n<r;n++){const r=e[n];r(c),a.has(r)&&(i.schedule(r),t())}o=!1,s&&(s=!1,i.process(c))}}};return i}((()=>Tt=!0)),t)),{}),qt=Ct.reduce(((t,e)=>{const n=kt[e];return t[e]=(t,e=!1,r=!1)=>(Tt||Et(),n.schedule(t,e,r)),t}),{}),Nt=Ct.reduce(((t,e)=>(t[e]=kt[e].cancel,t)),{});Ct.reduce(((t,e)=>(t[e]=()=>kt[e].process(Rt),t)),{});const $t=t=>kt[t].process(Rt),Bt=t=>{Tt=!1,Rt.delta=St?At:Math.max(Math.min(t-Rt.timestamp,40),1),Rt.timestamp=t,Ft=!0,Ct.forEach($t),Ft=!1,Tt&&(St=!1,Pt(Bt))},Et=()=>{Tt=!0,St=!0,Ft||Pt(Bt)},Ut=()=>Rt;function zt(t,e,n=0){return t-e-n}const Gt=t=>{const e=({delta:e})=>t(e);return{start:()=>qt.update(e,!0),stop:()=>Nt.update(e)}};function Ht(t){var n,r,{from:o,autoplay:s=!0,driver:a=Gt,elapsed:i=0,repeat:c=0,repeatType:l="loop",repeatDelay:p=0,onPlay:f,onStop:d,onComplete:h,onRepeat:m,onUpdate:g}=t,y=e(t,["from","autoplay","driver","elapsed","repeat","repeatType","repeatDelay","onPlay","onStop","onComplete","onRepeat","onUpdate"]);let b,M,v,{to:O}=y,x=0,w=y.duration,j=!1,I=!0;const A=function(t){if(Array.isArray(t.to))return wt;if(It[t.type])return It[t.type];const e=new Set(Object.keys(t));return e.has("ease")||e.has("duration")&&!e.has("dampingRatio")?wt:e.has("dampingRatio")||e.has("stiffness")||e.has("mass")||e.has("damping")||e.has("restSpeed")||e.has("restDelta")?u:wt}(y);(null===(r=(n=A).needsInterpolation)||void 0===r?void 0:r.call(n,o,O))&&(v=rt([0,100],[o,O],{clamp:!1}),o=0,O=100);const D=A(Object.assign(Object.assign({},y),{from:o,to:O}));function P(){x++,"reverse"===l?(I=x%2==0,i=function(t,e,n=0,r=!0){return r?zt(e+-t,e,n):e-(t-e)+n}(i,w,p,I)):(i=zt(i,w,p),"mirror"===l&&D.flipTarget()),j=!1,m&&m()}function S(t){if(I||(t=-t),i+=t,!j){const t=D.next(Math.max(0,i));M=t.value,v&&(M=v(M)),j=I?t.done:i<=0}null==g||g(M),j&&(0===x&&(null!=w||(w=i)),x<c?function(t,e,n,r){return r?t>=e+n:t<=-n}(i,w,p,I)&&P():(b.stop(),h&&h()))}return s&&(null==f||f(),b=a(S),b.start()),{stop:()=>{null==d||d(),b.stop()}}}function Lt(t,e){return e?t*(1e3/e):0}const Wt=t=>180*t/Math.PI,_t=t=>t,Vt=(t=_t)=>(e,n,r)=>{const o=n-r,s=-(0-e+1)*(0-t(Math.abs(o)));return o<=0?n+s:n-s},Jt=Vt(),Kt=Vt(Math.sqrt),Qt=t=>t*Math.PI/180,Xt=t=>t.hasOwnProperty("x")&&t.hasOwnProperty("y"),Yt=t=>Xt(t)&&t.hasOwnProperty("z"),Zt=(t,e)=>Math.abs(t-e);const te=(t,e=2)=>(e=Math.pow(10,e),Math.round(t*e)/e),ee=(t,e,n,r=0)=>te(t+n*(e-t)/Math.max(r,n));const ne=(t,e)=>1-3*e+3*t,re=(t,e)=>3*e-6*t,oe=t=>3*t,se=(t,e,n)=>((ne(e,n)*t+re(e,n))*t+oe(e))*t,ae=(t,e,n)=>3*ne(e,n)*t*t+2*re(e,n)*t+oe(e);const ie=.1;t.angle=(t,e=_)=>Wt(Math.atan2(e.y-t.y,e.x-t.x)),t.animate=Ht,t.anticipate=Mt,t.applyOffset=(t,e)=>{let n=!0;return void 0===e&&(e=t,n=!1),r=>n?r-t+e:(t=r,n=!0,e)},t.attract=Jt,t.attractExpo=Kt,t.backIn=gt,t.backInOut=bt,t.backOut=yt,t.bounceIn=Ot,t.bounceInOut=t=>t<.5?.5*(1-vt(1-2*t)):.5*vt(2*t-1)+.5,t.bounceOut=vt,t.circIn=dt,t.circInOut=mt,t.circOut=ht,t.clamp=n,t.createAnticipate=ct,t.createAttractor=Vt,t.createBackIn=it,t.createExpoIn=at,t.cubicBezier=function(t,e,n,r){if(t===e&&n===r)return ut;const o=new Float32Array(11);for(let e=0;e<11;++e)o[e]=se(e*ie,t,n);function s(e){let r=0,s=1;for(;10!==s&&o[s]<=e;++s)r+=ie;--s;const a=r+(e-o[s])/(o[s+1]-o[s])*ie,i=ae(a,t,n);return i>=.001?function(t,e,n,r){for(let o=0;o<8;++o){const o=ae(e,n,r);if(0===o)return e;e-=(se(e,n,r)-t)/o}return e}(e,a,t,n):0===i?a:function(t,e,n,r,o){let s,a,i=0;do{a=e+(n-e)/2,s=se(a,r,o)-t,s>0?n=a:e=a}while(Math.abs(s)>1e-7&&++i<10);return a}(e,r,r+ie,t,n)}return t=>0===t||1===t?t:se(s(t),e,r)},t.decay=jt,t.degreesToRadians=Qt,t.distance=function(t,e){if(V(t)&&V(e))return Zt(t,e);if(Xt(t)&&Xt(e)){const n=Zt(t.x,e.x),r=Zt(t.y,e.y),o=Yt(t)&&Yt(e)?Zt(t.z,e.z):0;return Math.sqrt(Math.pow(n,2)+Math.pow(r,2)+Math.pow(o,2))}},t.easeIn=lt,t.easeInOut=ft,t.easeOut=pt,t.inertia=function({from:t=0,velocity:e=0,min:n,max:r,power:o=.8,timeConstant:s=750,bounceStiffness:a=500,bounceDamping:i=10,restDelta:c=1,modifyTarget:u,driver:l,onUpdate:p,onComplete:f,onStop:d}){let h;function m(t){return void 0!==n&&t<n||void 0!==r&&t>r}function g(t){return void 0===n?r:void 0===r||Math.abs(n-t)<Math.abs(r-t)?n:r}function y(t){null==h||h.stop(),h=Ht(Object.assign(Object.assign({},t),{driver:l,onUpdate:e=>{var n;null==p||p(e),null===(n=t.onUpdate)||void 0===n||n.call(t,e)},onComplete:f,onStop:d}))}function b(t){y(Object.assign({type:"spring",stiffness:a,damping:i,restDelta:c},t))}if(m(t))b({from:t,velocity:e,to:g(t)});else{let r=o*e+t;void 0!==u&&(r=u(r));const a=g(r),i=a===n?-1:1;let l,p;const f=t=>{l=p,p=t,e=Lt(t-l,Ut().delta),(1===i&&t>a||-1===i&&t<a)&&b({from:t,to:a,velocity:e})};y({type:"decay",from:t,velocity:e,timeConstant:s,power:o,restDelta:c,modifyTarget:u,onUpdate:m(r)?f:void 0})}return{stop:()=>null==h?void 0:h.stop()}},t.interpolate=rt,t.isPoint=Xt,t.isPoint3D=Yt,t.keyframes=wt,t.linear=ut,t.mirrorEasing=st,t.mix=f,t.mixColor=W,t.mixComplex=tt,t.pipe=K,t.pointFromVector=(t,e,n)=>(e=Qt(e),{x:n*Math.cos(e)+t.x,y:n*Math.sin(e)+t.y}),t.progress=p,t.radiansToDegrees=Wt,t.reverseEasing=ot,t.smooth=(t=50)=>{let e=0,n=0;return r=>{const o=Ut().timestamp,s=o!==n?o-n:0,a=s?ee(e,r,s,t):e;return n=o,e=a,a}},t.smoothFrame=ee,t.snap=t=>{if("number"==typeof t)return e=>Math.round(e/t)*t;{let e=0;const n=t.length;return r=>{let o=Math.abs(t[0]-r);for(e=1;e<n;e++){const s=t[e],a=Math.abs(s-r);if(0===a)return s;if(a>o)return t[e-1];if(e===n-1)return s;o=a}}}},t.spring=u,t.steps=(t,e="end")=>r=>{const o=(r="end"===e?Math.min(r,.999):Math.max(r,.001))*t,s="end"===e?Math.floor(o):Math.ceil(o);return n(0,1,s/t)},t.toDecimal=te,t.velocityPerFrame=function(t,e){return t/(1e3/e)},t.velocityPerSecond=Lt,t.wrap=(t,e,n)=>{const r=e-t;return((n-t)%r+r)%r+t},Object.defineProperty(t,"__esModule",{value:!0})}));
@@ -0,0 +1,26 @@
1
+ require "opal-jquery"
2
+
3
+ # class Element
4
+ # def self.create(tag = 'div', opt = {})
5
+ # `jQuery('<'+tag+'/>',opt.$to_n())`
6
+ # end
7
+ # end
8
+ #
9
+ # def box(params = {})
10
+ # # el = Element.new(:div)
11
+ # el = Element.create(:div, { id: 'some_big_id',
12
+ # class: 'some-class some-other-class',
13
+ # title: 'now this div has a title!' })
14
+ # # el.text("kjh")
15
+ # Element.find('#user_view').append(el)
16
+ # el.css(:color, :red).css( "box-shadow": "0px 0px 9px red")
17
+ # .css(:width, 33).css(:height, 33).css(:position, "absolute").css(:left, "33px").css(:top, "33px")
18
+ # .css( 'border-radius', '3px 6px 3px 6px')
19
+ #
20
+ # el.on(:click) do
21
+ # el.css("background-color", "yellowgreen")
22
+ # el.text(el.css("background-color"))
23
+ # end
24
+ # end
25
+
26
+ box({ width: 33, height: 33, smooth: 6, shadow: { blur: 6, x: 6, y: 6, invert: false, thickness: 0, bounding: true, color: :black } })
@@ -0,0 +1,376 @@
1
+ # frozen_string_literal: true
2
+
3
+ # instructions to install :
4
+ # gem install bundler roda sqlite3 sequel rack-unreloader faye-websocket websocket-extensions websocket-driver puma -N
5
+ # important if crash the gem install rack-unreloader -v 1.7.0 gem install roda -v 2.26.0
6
+ # bundle update
7
+ # bundle install
8
+ # to run: rackup --server puma --port 4567 or without puma : rackup -p 4567
9
+
10
+ # puts RUBY_VERSION
11
+ if RUBY_PLATFORM == "x64-mingw32"
12
+ require "em/pure_ruby"
13
+ end
14
+ require "roda"
15
+ require "sequel"
16
+ require "rufus-scheduler"
17
+ require "faye/websocket"
18
+ require "json"
19
+ require "securerandom"
20
+ require "mail"
21
+ require "digest"
22
+ require "filewatcher"
23
+
24
+
25
+
26
+ class String
27
+ def is_json?
28
+ begin
29
+ !JSON.parse(self).nil?
30
+ rescue
31
+ false
32
+ end
33
+ end
34
+ end
35
+
36
+ class App < Roda
37
+
38
+ @@channels = {}
39
+ @@user
40
+ @@test_socket = []
41
+
42
+ #plugin :mail_processor
43
+ eden = Sequel.connect("sqlite://eden.sqlite3")
44
+ unless File.exist?("eden.sqlite3")
45
+ eden.create_table :objects do
46
+ primary_key :atome_id
47
+ String :id
48
+ String :type
49
+ String :name
50
+ String :content
51
+ end
52
+ end
53
+
54
+ index_content = File.read("../view/index.html")
55
+
56
+ # index_content = index_content.gsub('<script type="text/javascript" src="../cordova.js"></script>', "")
57
+ # below an attempt to load atome in pure ruby not opal
58
+ require "../atome/lib/atome.rb"
59
+ box("je sais pas ou ca passe")
60
+ opts[:root] = '../view'
61
+ plugin :static, %w[/css /js /medias], root: '../view'
62
+ # plugin "faye/websocket"
63
+ route do |r|
64
+ if Faye::WebSocket.websocket?(env)
65
+ ws = Faye::WebSocket.new(env)
66
+ # @@test_socket[0] = ws
67
+ @@test_socket[0] = ws
68
+ ws.on :message do |event|
69
+ client_data = event.data
70
+ if client_data.is_json?
71
+ data = JSON.parse(client_data)
72
+ # puts data
73
+ case data["type"]
74
+ when "login"
75
+ user_id = data["username"]
76
+ # @user_id[user_id]=ws
77
+ # @user[data["username"]] = ws
78
+ # ws.send()
79
+ # message_back = "text ({content: '#{data["username"]} with id : #{data["id"]} is connected!', y:330})"
80
+ # message_back={id: data["id"], log: true}
81
+ #
82
+ session_id = SecureRandom.uuid
83
+ message_back = JSON.generate({ type: :response, request_id: data["request_id"], session_id: session_id, log: true })
84
+ ws.send(message_back)
85
+
86
+ when "start_channel"
87
+ channel_id = SecureRandom.uuid
88
+ # self.channels(channel_id)
89
+ @@channels[channel_id] = []
90
+ # @session[data["username"]] =session_id
91
+ message_back = JSON.generate({ type: :response, request_id: data["request_id"], channel_id: channel_id })
92
+ ws.send(message_back)
93
+ when "list_channels"
94
+ message_back = JSON.generate({ type: :response, request_id: data["request_id"], channels: @@channels.keys })
95
+ ws.send(message_back)
96
+ when "connect_channel"
97
+ channel_id = data["channel_id"]
98
+ @@channels[channel_id] << ws
99
+ message_back = JSON.generate({ type: :response, request_id: data["request_id"], connected: true })
100
+ ws.send(message_back)
101
+ when "push_to_channel"
102
+ channel_id = data["channel_id"]
103
+ message_received = data["message"]
104
+ #fixme the type depend on the kind if received message
105
+ message_to_push = JSON.generate({ type: :code, content: message_received })
106
+ @@channels[channel_id].each do |ws_found|
107
+ # we exclude the sender from the recipient
108
+ unless ws_found == ws
109
+ ws_found.send(message_to_push)
110
+ end
111
+ end
112
+ message_back = JSON.generate({ type: :response, request_id: data["request_id"], pushed: true })
113
+ ws.send(message_back)
114
+ when "read"
115
+ file_content = File.read(data["file"])
116
+ hashed_content = { content: file_content }
117
+ hashed_options = { options: data["options"].to_s }
118
+ message_to_push = JSON.generate({ type: :read, atome: data["atome"], target: data["target"], content: hashed_content, options: hashed_options })
119
+ ws.send(message_to_push)
120
+ when "set"
121
+ msg = { type: :monitor, atome: data["atome"], target: data["target"], output: data["output"], content: data["content"],options: data["options"] }
122
+ set_output msg
123
+ when "monitor"
124
+ # file = data["file"]
125
+ # monitor "public/medias/e_projects/chambon/code.rb"
126
+ # puts file.class
127
+ # if !file.instance_of?(Array)
128
+ # file=[file]
129
+ # end
130
+
131
+
132
+ # @@threads << Thread.new do
133
+ # puts "hello from thread"
134
+ # Filewatcher.new(file).watch do |changes|
135
+ # file_content = file
136
+ # hashed_content = { content: data["file"] }
137
+ # hashed_options = { options: data["options"].to_s }
138
+ if data["file"]
139
+ msg = { type: :monitor, atome: data["atome"], target: data["target"], content: data["file"], options: data["options"] }
140
+ monitor msg
141
+ else
142
+ msg = { type: :monitor, atome: data["atome"], target: data["target"], input: data["input"], options: data["options"] }
143
+ capture_input msg
144
+ end
145
+ # puts "------"
146
+ # puts file.class
147
+ # puts "------"
148
+ # message_to_push = JSON.generate({ type: :monitor, atome: data["atome"], target: data["target"], content: hashed_content, options: hashed_options })
149
+ # # puts ws.inspect
150
+ # # puts "---"
151
+ # puts "hashed_content : #{hashed_content}}"
152
+ # puts "hashed_options : #{hashed_options}}"
153
+ # puts "message_to_push : #{message_to_push}}"
154
+ # ws.send(message_to_push)
155
+ # # @@channels[channel_id].each do |ws_found|
156
+ # # # we exclude the sender from the recipient
157
+ # # unless ws_found == ws
158
+ # # ws_found.send(message_to_push)
159
+ # # end
160
+ # # end
161
+ # end
162
+ # puts "koolll!!!!"
163
+ # end
164
+ # @@threads.each(&:join)
165
+
166
+ # t= Thread.new do
167
+ # puts "hello from thread"
168
+ # Filewatcher.new(file).watch do |changes|
169
+ # # file_content = File.read(changes)
170
+ # hashed_content = { content: file_content }
171
+ # hashed_options = { options: data["options"].to_s }
172
+ # message_to_push = JSON.generate({ type: :monitor, atome: data["atome"], target: data["target"], content: hashed_content, options: hashed_options })
173
+ # # puts ws.inspect
174
+ # # puts "---"
175
+ # puts "hashed_content : #{hashed_content}}"
176
+ # puts "hashed_options : #{hashed_options}}"
177
+ # puts "message_to_push : #{message_to_push}}"
178
+ # ws.send(message_to_push)
179
+ # # @@channels[channel_id].each do |ws_found|
180
+ # # # we exclude the sender from the recipient
181
+ # # unless ws_found == ws
182
+ # # ws_found.send(message_to_push)
183
+ # # end
184
+ # # end
185
+ # end
186
+ #
187
+ # end
188
+ #
189
+ # t.join
190
+
191
+ # # ugly patch below needs to use filewatcher above instead
192
+ # t=Thread.new do
193
+ # sleep 12
194
+ # puts file = data["file"]
195
+ # end
196
+ # t.join
197
+ # if @file_require == (Digest::SHA256.hexdigest File.read data["file"])
198
+ # @file_require = Digest::SHA256.hexdigest File.read data["file"]
199
+ # else
200
+ # @file_require = Digest::SHA256.hexdigest File.read data["file"]
201
+ # # file_content = File.read()
202
+ # file = data["file"]
203
+ # hashed_file = { content: file }
204
+ # hashed_options = { options: data["options"].to_s }
205
+ # message_to_push = JSON.generate({ type: :monitor, atome: data["atome"], target: data["target"], file: hashed_file, options: hashed_options })
206
+ # ws.send(message_to_push)
207
+ # end
208
+ when "list"
209
+ files_found = Dir[data["path"] + "/*"]
210
+ hashed_content = { content: files_found }
211
+ hashed_options = { options: data["options"].to_s }
212
+ message_to_push = JSON.generate({ type: :read, target: data["target"], content: hashed_content, options: hashed_options })
213
+ ws.send(message_to_push)
214
+ when "write"
215
+ File.write(data["file"], data["content"])
216
+ hashed_content = { content: data["content"].to_s }
217
+ hashed_options = { options: data["options"].to_s }
218
+ message_to_push = JSON.generate({ type: :read, target: data["target"], content: hashed_content, options: hashed_options })
219
+ ws.send(message_to_push)
220
+ when "copy"
221
+ FileUtils.cp data["source"], data["dest"]
222
+ when "delete"
223
+ File.delete(data["file"])
224
+ hashed_content = { content: data["file"].to_s }
225
+ hashed_options = { options: data["options"].to_s }
226
+ message_to_push = JSON.generate({ type: :read, target: data["target"], content: hashed_content, options: hashed_options })
227
+ ws.send(message_to_push)
228
+ when "mail"
229
+ if data["from"]
230
+ sender = data["from"]
231
+ else
232
+ sender = "contact@atome.one"
233
+ end
234
+ receiver = data["to"]
235
+ mail_subject = data["subject"]
236
+ content = data["content"]
237
+ attachment = data["attachment"]
238
+ attachments = []
239
+ if attachment
240
+ if attachment.instance_of?(Array)
241
+ attachment.each do |file|
242
+ filename = File.basename(file)
243
+ attachments << { file: file, filename: filename }
244
+ end
245
+ else
246
+ filename = File.basename(attachment)
247
+ attachments << { file: attachment, filename: filename }
248
+ end
249
+ end
250
+ # puts "----- + -----"
251
+ # puts "sender: #{sender}"
252
+ # puts "receiver: #{receiver}"
253
+ # puts "mail_subject: #{mail_subject}"
254
+ # puts "content: #{content}"
255
+ # puts "attachments: #{attachments}"
256
+ # puts "----- - -----"
257
+ mail = Mail.new do
258
+ from sender
259
+ to receiver
260
+ subject mail_subject
261
+ body content
262
+ attachments.each do |file_to_add|
263
+ file = file_to_add[:file]
264
+ filename = file_to_add[:filename]
265
+ add_file :filename => filename, :content => File.read(file)
266
+ end
267
+ end
268
+
269
+ mail.delivery_method :sendmail
270
+
271
+ mail.deliver
272
+ when "atome"
273
+ message_to_push = JSON.generate({ type: :atome, target: data["target"], atome: data["atome"], content: data["content"] })
274
+ ws.send(message_to_push)
275
+ when "code"
276
+ message_to_push = JSON.generate({ type: :code, content: data["content"] })
277
+ ws.send(message_to_push)
278
+ when "command"
279
+ file_content = `#{data["content"]}`
280
+ # hashed_content = { content: file_content }.merge(data["options"])
281
+ message_to_push = JSON.generate({ type: :command, target: data["target"], atome: data["atome"], content: file_content })
282
+ ws.send(message_to_push)
283
+ else
284
+ # ws.send("unknown message received")
285
+ end
286
+ end
287
+ end
288
+ #ws.on :open do |event|
289
+ # #ws = nil
290
+ #end
291
+ ws.on :close do |event|
292
+ #ws = nil
293
+ end
294
+ ws.rack_response
295
+ end
296
+ r.root do
297
+ r.redirect "/index"
298
+ end
299
+ r.on "index" do
300
+ r.is do
301
+ r.get do
302
+ #sleep 7
303
+ #box()
304
+ index_content
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ def self.monitor_callback(val, params)
311
+ ws = @@test_socket[0]
312
+ file_content = File.read(val)
313
+ params[:content] = val
314
+ msg = { "type": "eval", "atome": "text", "target": "tryout", "content": { "content": file_content }, "options": "clear" }
315
+ params[:content] = { "content": { "content": file_content } }
316
+ message_to_push = JSON.generate(msg)
317
+ ws.send(message_to_push)
318
+ end
319
+
320
+ def self.device_output_callback( params)
321
+ ws = @@test_socket[0]
322
+ file_content = params[:content]
323
+ msg = { "type": "read", "atome": "text", "target": "tryout", "content": { "content": file_content }, "options": "clear" }
324
+ params[:content] = { "content": { "content": file_content } }
325
+ message_to_push = JSON.generate(msg)
326
+ ws.send(message_to_push)
327
+ end
328
+ end
329
+
330
+
331
+
332
+
333
+ # Update all connections in a single thread
334
+ def monitor(params)
335
+ Thread.new do
336
+ Filewatcher.new(params[:content]).watch do |changes|
337
+ App.monitor_callback(changes, params)
338
+ end
339
+ end
340
+ end
341
+
342
+ @bbb_ready = false
343
+ @bbb_thread = false
344
+
345
+ def capture_input params
346
+ unless @bbb_ready
347
+ @bbb_ready = true
348
+ puts "bbb is ready"
349
+ # require "./beagleboard"
350
+
351
+ end
352
+ if @bbb_thread
353
+ @bbb_thread.exit
354
+ end
355
+
356
+ @bbb_thread = Thread.new do
357
+
358
+ i = 0
359
+ while i < 2000
360
+ puts i
361
+ sleep 1
362
+ i += 1
363
+ end
364
+ end
365
+ end
366
+
367
+
368
+ def set_output params
369
+ App.device_output_callback( params)
370
+ end
371
+
372
+
373
+ # capture_input(1, { my_condition: :callback })
374
+ #
375
+ # capture_input(1, { my_condition: :callback })
376
+ # capture_input(1, { my_condition: :callback })