From 91715551d1db04fabed93589d63ddd672d32f38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=2E=20Iv=C3=A1n=20Alegre?= Date: Thu, 18 Apr 2013 12:18:55 +0200 Subject: [PATCH] Mixing notes and bugfixes The application now mixes notes between local and remote list of notes. Also it has been solved various bugs when using File API and Events API Add: Mix of local/remotes notes comparing both list of notes * New local note not present in remote list -> Send webinos event with the new note * New remote note not present in local list -> Save it both in memory and file (webinos File API) * Existing updated note: * Updated only in local -> Send webinos event with the updated note * Updated only in remote -> Save it both in memory and file (webinos File API) * Updated in both sides -> Make a note with all the content of the local and remote note. Send event and save it in local. Add: Ask other PZP for an updated notes list with "cn-getNotes" event. Add: otherPZP variable updated when searching File API services to be used in the future. It won't have sense when fixing webinos.session.getOtherPZP() Fix: Loading foreign file API service. Now it loads only the File API from the own device Fix: File API in webinos 0.8.0 for Android is not working, so it retrieves the note of list from other connected PZP with cn-getNotes event. --- README.md | 1 - editNote.html | 1 + favicon.ico | Bin 0 -> 1150 bytes index.html | 1 + js/dataManager.js | 61 +++++++++++++++++++++++++++++++++++ js/fileManager.js | 11 ++++++- js/graphicalManager.js | 34 ++++++++++++------- js/sugar-1.3.9-custom.min.js | 53 ++++++++++++++++++++++++++++++ js/webinosManager.js | 4 +-- 9 files changed, 151 insertions(+), 15 deletions(-) create mode 100644 favicon.ico create mode 100644 js/sugar-1.3.9-custom.min.js diff --git a/README.md b/README.md index a1ba5f9..c6db21a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ ## Creative Notes ================= -**NOTE: This Creative Notes version works on Webinos platform until 0.8.0** ### Installing diff --git a/editNote.html b/editNote.html index e83df99..80e3d7f 100644 --- a/editNote.html +++ b/editNote.html @@ -10,6 +10,7 @@ + diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2cccb5453140073ebdf142a4146ab2101e6385aa GIT binary patch literal 1150 zcmZQzU<5(|0R}M0U}0bo1F|%L7$l?s#Ef7P$NHt_%de+G06bmM;*MwcVRhv^IU zW`dgm6C+mdym|A0N`Vf8y5s4?9T_k-jK*dbk{nn+GErV$4mK~)3)NjPbMWa!HV2u# zYrXwXWc{0#YJjCbe*B263@008ClCNBNO&VF{QLJWG8co5qzA13!pT~=8ju_^0P*GI z)ldXL-Us0y kK>R_Tf#HEO5Ccs-0L2YJx`7djnSnGrP>vs{9*9Bu0Ne*oGynhq literal 0 HcmV?d00001 diff --git a/index.html b/index.html index ce8dd27..bda6ff8 100644 --- a/index.html +++ b/index.html @@ -10,6 +10,7 @@ + diff --git a/js/dataManager.js b/js/dataManager.js index 43f3c74..e91a5bc 100644 --- a/js/dataManager.js +++ b/js/dataManager.js @@ -70,6 +70,9 @@ function dataManager(){ return noteIndex; } } + + // Ends iteration, not found + return -1; } this.addNote = function (note, notesList){ @@ -90,6 +93,64 @@ function dataManager(){ fileMgr.writeNotesList(notesList); } + /*** + Use SugarJS to work with sets + ***/ + this.mixNotesList = function(localNotesList, remoteNotesList){ + var notesList1 = localNotesList; + var notesList2 = remoteNotesList; + + // Function that mixes two notes with the same id and changes in both. + var mixNotes = function(localNote, remoteNote){ + var note = localNote; + var note2 = remoteNote; + var onlyLocalContent = note.content.subtract(note2.content); // [] if only remote changes + var onlyRemoteContent = note2.content.subtract(note.content); // [] if only local changes + if (onlyLocalContent.length == 0){ + // The note has not been updated locally, only remotely + note.content = note2.content; + console.log("Note modified in remote, update only in local"); + dataMgr.addNote(note, notesList); + } else if (onlyRemoteContent.length == 0){ + // The note only has local updates + console.log("Note modified in local, send webinos event"); + webinosMgr.sendNoteEvent(note); + } else { + console.log("Note modified in both sides, send webinos event"); + note.content = note.content.union(note2.content); + webinosMgr.sendNoteEvent(note); + } + console.log(note); + console.log(note2); + } + + var modifiedLocalNotes = notesList1.subtract(notesList2); + var modifiedRemoteNotes = notesList2.subtract(notesList1); + + for (noteI in modifiedLocalNotes){ + var note = modifiedLocalNotes[noteI]; + if (dataMgr.getNoteById(note.id, modifiedRemoteNotes) == -1){ + // Inexistent note in remote. Brand new local note + console.log("New local note, send webinos event"); + webinosMgr.sendNoteEvent(note); + } else { + // Modified in both sides + console.log("Updated note: Mix local and remote notes"); + var note2 = dataMgr.getNoteById(note.id, notesList2); + mixNotes(note, note2); + } + } + + for (noteI in modifiedRemoteNotes){ + var note = modifiedRemoteNotes[noteI]; + if (dataMgr.getNoteById(note.id, modifiedLocalNotes) == -1){ + // Inexistent note in local. Brand new remote note + console.log("New remote note, add it locally"); + dataMgr.addNote(note, notesList); + } + } + } + /* DATA MODEL OF NOTESLIST [ { diff --git a/js/fileManager.js b/js/fileManager.js index d85d64a..a11e4e4 100644 --- a/js/fileManager.js +++ b/js/fileManager.js @@ -1,6 +1,7 @@ function fileManager(successCB, errorCB){ var fileService; var fileSystem; + var otherFileServices = []; var notesListFileName = "CreativeNotes.json"; @@ -11,9 +12,17 @@ function fileManager(successCB, errorCB){ function errorWithCB(log){ console.log(log); errorCB(log); - } + } function onServiceFound(ser){ + // Test if it's fileAPI from another PZP + if (ser.serviceAddress != webinos.session.getPZPId()){ + // Add it to otherPZP list, to otherFileServices and exit (we do not bind at the moment) + otherPZP.push(ser.serviceAddress); + otherFileServices.push(ser); + return; + } + fileService = ser; ser.bindService({ onBind: function(){ diff --git a/js/graphicalManager.js b/js/graphicalManager.js index c6220e7..49d57d9 100644 --- a/js/graphicalManager.js +++ b/js/graphicalManager.js @@ -9,9 +9,10 @@ var defaultUntitledTitle = "Untitled Note"; var noteWidth = "95%"; // Show a spinning wheel while testing everything -var defaultGroup = "WebinosTelefonica" +var defaultGroup = "WebinosTelefonica"; var pzhName; +var otherPZP = []; // Filled when searching fileAPI services (fileManager.js) var noteIdLength = 32; @@ -98,7 +99,7 @@ function saveNote(){ currentNote.content = currentNote.content.concat(noteData); // Just for backup - serverMgr.sendNote(currentNote); + // serverMgr.sendNote(currentNote); // If new note if (dataMgr.getId(currentNote) == -1){ @@ -241,20 +242,21 @@ function initIndex(){ if (!notesList){ // First, try to get notes from the local file. If something bad happens, download/ask - // If fileAPI is not ready, there is no file, or it's corrupted + // If fileAPI is not ready (or not supported), there is no file, or it's corrupted var errorCB = function(error){ - // Override InvalidStateError - if (!error || error.name != "InvalidStateError"){ - // Get a list of notes from other PZP through webinos - webinosMgr.getNotesFromOtherPZP( - function(notes){ + // Get a list of notes from other PZP through webinos + webinosMgr.getNotesFromOtherPZP( + function(notes){ + // This function can be called more than one time (various responses) + // Test if notesList has been already loaded + if (!notesList){ console.log("NOTES RETRIEVED FROM OTHER PZP"); notesList = notes; fileMgr.writeNotesList(notesList); updateNotesList(); } - ) - } + } + ) } // If fileAPI is ready @@ -264,10 +266,20 @@ function initIndex(){ var gotNotesList = function(nl){ notesList = nl; updateNotesList(); + + // Now retrieve remote NotesList, and look for changes + var gotRemoteNL = false; + webinosMgr.getNotesFromOtherPZP( + function(remoteNotesList){ + if (!gotRemoteNL){ + gotRemoteNL = true; + dataMgr.mixNotesList(notesList, remoteNotesList); + } + } + ); } // If there is no file to read, same actions as fileAPI not ready. - fileMgr.readNotesList(gotNotesList, errorCB); } diff --git a/js/sugar-1.3.9-custom.min.js b/js/sugar-1.3.9-custom.min.js new file mode 100644 index 0000000..a69d270 --- /dev/null +++ b/js/sugar-1.3.9-custom.min.js @@ -0,0 +1,53 @@ +/* + * Sugar Library v1.3.9 + * + * Freely distributable and licensed under the MIT-style license. + * Copyright (c) 2013 Andrew Plummer + * http://sugarjs.com/ + * + * ---------------------------- */ +(function(){var k=true,l=null,n=false;function aa(a){return function(){return a}}var p=Object,q=Array,r=RegExp,s=Date,t=String,u=Number,v=Math,ba=p.prototype.toString,ca=typeof global!=="undefined"?global:this,da={},ea=p.defineProperty&&p.defineProperties,x="Array,Boolean,Date,Function,Number,String,RegExp".split(","),ga=fa(x[0]),ha=fa(x[1]),ia=fa(x[2]),y=fa(x[3]),A=fa(x[4]),B=fa(x[5]),C=fa(x[6]); +function fa(a){var b,c;if(/String|Number|Boolean/.test(a))b=a.toLowerCase();c=a==="Array"&&q.isArray||function(d){if(b&&typeof d===b)return k;return ba.call(d)==="[object "+a+"]"};return da[a]=c}function ja(a){if(!a.SugarMethods){ka(a,"SugarMethods",{});D(a,n,n,{extend:function(b,c,d){D(a,d!==n,c,b)},sugarRestore:function(){return la(a,arguments,function(b,c,d){ka(b,c,d.method)})},sugarRevert:function(){return la(a,arguments,function(b,c,d){if(d.qa)ka(b,c,d.Ba);else delete b[c]})}})}} +function D(a,b,c,d){var e=b?a.prototype:a;ja(a);E(d,function(f,h){var i=e[f],j=F(e,f);if(typeof c==="function")h=ma(e[f],h,c);if(c!==n||!e[f])ka(e,f,h);a.SugarMethods[f]={xa:b,method:h,Ba:i,qa:j}})}function G(a,b,c,d,e){var f={};d=B(d)?d.split(","):d;d.forEach(function(h,i){e(f,h,i)});D(a,b,c,f)}function la(a,b,c){var d=b.length===0,e=H(b),f=n;E(a.SugarMethods,function(h,i){if(d||e.indexOf(h)>-1){f=k;c(i.xa?a.prototype:a,h,i)}});return f} +function ma(a,b,c){return function(){return(a&&(c===k||!c.apply(this,arguments))?a:b).apply(this,arguments)}}function ka(a,b,c){if(ea)p.defineProperty(a,b,{value:c,configurable:k,enumerable:n,writable:k});else a[b]=c}function H(a,b){var c=[],d,e;d=0;for(e=a.length;d=b;){e.push(a);c&&c.call(this,a);a+=d||1}return e}function N(a,b,c){c=v[c||"round"];var d=v.pow(10,v.abs(b||0));if(b<0)d=1/d;return c(a*d)/d}function O(a,b){return N(a,b,"floor")}function P(a,b,c,d){d=v.abs(a).toString(d||10);d=ta(b-d.replace(/\.\d+/,"").length,"0")+d;if(c||a<0)d=(a<0?"-":"+")+d;return d} +function ua(a){if(a>=11&&a<=13)return"th";else switch(a%10){case 1:return"st";case 2:return"nd";case 3:return"rd";default:return"th"}}function va(){return"\t\n\u000b\u000c\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u2028\u2029\u3000\ufeff"}function ta(a,b){return q(v.max(0,I(a)?a:1)+1).join(b||"")}function wa(a,b){var c=a.toString().match(/[^/]*$/)[0];if(b)c=(c+b).split("").sort().join("").replace(/([gimy])\1+/g,"$1");return c} +function R(a){B(a)||(a=t(a));return a.replace(/([\\/'*+?|()\[\]{}.^$])/g,"\\$1")}function xa(a,b){var c=typeof a,d,e,f,h,i,j,g;if(c==="string")return a;f=ba.call(a);d=L(a);e=f==="[object Array]";if(a!=l&&d||e){b||(b=[]);if(b.length>1)for(j=b.length;j--;)if(b[j]===a)return"CYC";b.push(a);d=t(a.constructor);h=e?a:p.keys(a).sort();j=0;for(g=h.length;j>0);if(c<0)c=e+c;if(!f&&c<0||f&&c>=e)c=h;for(;f&&c>=0||!f&&c>>0==e&&e!=4294967295&&e>=c&&d.push(parseInt(e));d.sort().each(function(f){return b.call(a,a[f],f,a)});return a}function Ha(a,b,c,d,e){var f,h;T(a,function(i,j,g){if(Ea(i,b,g,[i,j,g])){f=i;h=j;return n}},c,d);return e?h:f} +function Ia(a,b){var c=[],d={},e;T(a,function(f,h){e=b?S(f,b,a,[f,h,a]):f;Ja(d,e)||c.push(f)});return c}function Ka(a,b,c){var d=[],e={};b.each(function(f){Ja(e,f)});a.each(function(f){var h=xa(f),i=!ya(f);if(La(e,h,f,i)!=c){var j=0;if(i)for(h=e[h];je||i&&g0)c=b}catch(d){}a=a.concat(c)});return a}}); +D(q,k,n,{find:function(a,b,c){return Ha(this,a,b,c)},findAll:function(a,b,c){var d=[];T(this,function(e,f,h){Ea(e,a,h,[e,f,h])&&d.push(e)},b,c);return d},findIndex:function(a,b,c){a=Ha(this,a,b,c,k);return K(a)?-1:a},count:function(a){if(K(a))return this.length;return this.findAll(a).length},removeAt:function(a,b){var c,d;if(K(a))return this;if(K(b))b=a;c=0;for(d=b-a;c<=d;c++)this.splice(a,1);return this},include:function(a,b){return this.clone().add(a,b)},exclude:function(){return q.prototype.remove.apply(this.clone(), +arguments)},clone:function(){return qa([],this)},unique:function(a){return Ia(this,a)},flatten:function(a){return Ma(this,a)},union:function(){return Ia(this.concat(Na(arguments)))},intersect:function(){return Ka(this,Na(arguments),n)},subtract:function(){return Ka(this,Na(arguments),k)},at:function(){return za(this,arguments)},first:function(a){if(K(a))return this[0];if(a<0)a=0;return this.slice(0,a)},last:function(a){if(K(a))return this[this.length-1];return this.slice(this.length-a<0?0:this.length- +a)},from:function(a){return this.slice(a)},to:function(a){if(K(a))a=this.length;return this.slice(0,a)},min:function(a,b){return Oa(this,a,"min",b)},max:function(a,b){return Oa(this,a,"max",b)},least:function(a,b){return Oa(this.groupBy.apply(this,[a]),"length","min",b)},most:function(a,b){return Oa(this.groupBy.apply(this,[a]),"length","max",b)},sum:function(a){a=a?this.map(a):this;return a.length>0?a.reduce(function(b,c){return b+c}):0},average:function(a){a=a?this.map(a):this;return a.length>0? +a.sum()/a.length:0},inGroups:function(a,b){var c=arguments.length>1,d=this,e=[],f=N(this.length/a,void 0,"ceil");sa(0,a-1,function(h){h=h*f;var i=d.slice(h,h+f);c&&i.lengthh?1:0;return f*(b?-1:1)});return c},randomize:function(){for(var a=this.concat(),b=a.length,c,d;b;){c=v.random()*b|0; +d=a[--b];a[b]=a[c];a[c]=d}return a},zip:function(){var a=H(arguments);return this.map(function(b,c){return[b].concat(a.map(function(d){return c in d?d[c]:l}))})},sample:function(a){var b=this.randomize();return arguments.length>0?b.slice(0,a):b[0]},each:function(a,b,c){T(this,a,b,c);return this},add:function(a,b){if(!A(u(b))||isNaN(b))b=this.length;q.prototype.splice.apply(this,[b,0].concat(a));return this},remove:function(){var a,b=this;H(arguments,function(c){for(a=0;a0&&!y(a[0])},"map,every,all,some,any,none,filter",function(a,b){a[b]=function(c){return this[b](function(d,e){return b==="map"?S(d,c,this,[d,e,this]):Ea(d,c,this,[d,e,this])})}})})(); +(function(){q[Va]="A\u00c1\u00c0\u00c2\u00c3\u0104BC\u0106\u010c\u00c7D\u010e\u00d0E\u00c9\u00c8\u011a\u00ca\u00cb\u0118FG\u011eH\u0131I\u00cd\u00cc\u0130\u00ce\u00cfJKL\u0141MN\u0143\u0147\u00d1O\u00d3\u00d2\u00d4PQR\u0158S\u015a\u0160\u015eT\u0164U\u00da\u00d9\u016e\u00db\u00dcVWXY\u00ddZ\u0179\u017b\u017d\u00de\u00c6\u0152\u00d8\u00d5\u00c5\u00c4\u00d6".split("").map(function(b){return b+b.toLowerCase()}).join("");var a={};T("A\u00c1\u00c0\u00c2\u00c3\u00c4,C\u00c7,E\u00c9\u00c8\u00ca\u00cb,I\u00cd\u00cc\u0130\u00ce\u00cf,O\u00d3\u00d2\u00d4\u00d5\u00d6,S\u00df,U\u00da\u00d9\u00db\u00dc".split(","), +function(b){var c=b.charAt(0);T(b.slice(1).split(""),function(d){a[d]=c;a[d.toLowerCase()]=c.toLowerCase()})});q[Qa]=k;q[Ta]=a})();Xa(Ya);Xa(Za,k);Aa($a,ra); +function Jb(a,b,c,d,e){var f;if(b!==Infinity){if(!a.timers)a.timers=[];A(b)||(b=0);a.timers.push(setTimeout(function(){a.timers.splice(f,1);c.apply(d,e||[])},b));f=a.timers.length}} +D(Function,k,n,{lazy:function(a,b){function c(){if(!f||e.lengthm;)g=Function.prototype.apply.apply(d,e.shift());Jb(c,i,function(){f=n;h()});f=k}};return c},delay:function(a){var b=H(arguments).slice(1);Jb(this,a,this,this,b);return this},throttle:function(a){return this.lazy(a,1)},debounce:function(a){function b(){b.cancel(); +Jb(b,a,c,this,arguments)}var c=this;return b},cancel:function(){if(ga(this.timers))for(;this.timers.length>0;)clearTimeout(this.timers.shift());return this},after:function(a){var b=this,c=0,d=[];if(A(a)){if(a===0){b.call();return b}}else a=1;return function(){var e;d.push(H(arguments));c++;if(c==a){e=b.call(this,d);c=0;d=[];return e}}},once:function(){return this.throttle(Infinity)},fill:function(){var a=this,b=H(arguments);return function(){var c=H(arguments);b.forEach(function(d,e){if(d!=l||e>= +c.length)c.splice(e,0,d)});return a.apply(this,c)}}}); +var Lb="isObject,isNaN".split(","),Mb="keys,values,select,reject,each,merge,clone,equal,watch,tap,has,toQueryString".split(","); +function Nb(a,b,c,d){var e=/^(.+?)(\[.*\])$/,f,h,i;if(d!==n&&(h=b.match(e))){i=h[1];b=h[2].replace(/^\[|\]$/g,"").split("][");b.forEach(function(j){f=!j||j.match(/^\d+$/);if(!i&&ga(a))i=a.length;F(a,i)||(a[i]=f?[]:{});a=a[i];i=j});if(!i&&f)i=a.length.toString();Nb(a,i,c)}else a[b]=c.match(/^[+-]?\d+(\.\d+)?$/)?parseFloat(c):c==="true"?k:c==="false"?n:c} +function Ob(a,b){var c;if(ga(b)||L(b)&&b.toString===ba){c=[];E(b,function(d,e){if(a)d=a+"["+d+"]";c.push(Ob(d,e))});return c.join("&")}else{if(!a)return"";return Pb(a)+"="+(ia(b)?b.getTime():Pb(b))}}function Pb(a){return!a&&a!==n&&a!==0?"":encodeURIComponent(a).replace(/%20/g,"+")}function Qb(a,b,c){var d={},e;E(a,function(f,h){e=n;na(b,function(i){if(C(i)?i.test(f):pa(i)?F(i,f):f===t(i))e=k},1);if(e===c)d[f]=h});return d} +D(p,n,k,{watch:function(a,b,c){if(ea){var d=a[b];p.defineProperty(a,b,{enumerable:k,configurable:k,get:function(){return d},set:function(e){d=c.call(a,b,d,e)}})}}});D(p,n,function(a,b){return y(b)},{keys:function(a,b){var c=p.keys(a);c.forEach(function(d){b.call(a,d,a[d])});return c}}); +D(p,n,n,{isObject:function(a){return L(a)},isNaN:function(a){return A(a)&&a.valueOf()!==a.valueOf()},equal:function(a,b){return ya(a)&&ya(b)?xa(a)===xa(b):a===b},extended:function(a){return new ra(a)},merge:function(a,b,c,d){var e,f;if(a&&typeof b!="string")for(e in b)if(F(b,e)&&a){f=b[e];if(I(a[e])){if(d===n)continue;if(y(d))f=d.call(b,e,a[e],b[e])}if(c===k&&f&&pa(f))if(ia(f))f=new s(f.getTime());else if(C(f))f=new r(f.source,wa(f));else{a[e]||(a[e]=q.isArray(f)?[]:{});p.merge(a[e],b[e],c,d);continue}a[e]= +f}return a},values:function(a,b){var c=[];E(a,function(d,e){c.push(e);b&&b.call(a,e)});return c},clone:function(a,b){var c;if(ia(a)&&a.clone)return a.clone();else if(pa(a))c=a instanceof ra?new ra:new a.constructor;else return a;return p.merge(c,a,b)},fromQueryString:function(a,b){var c=p.extended();a=a&&a.toString?a.toString():"";a.replace(/^.*?\?/,"").split("&").forEach(function(d){d=d.split("=");d.length===2&&Nb(c,d[0],decodeURIComponent(d[1]),b)});return c},toQueryString:function(a,b){return Ob(b, +a)},tap:function(a,b){var c=b;y(b)||(c=function(){b&&a[b]()});c.call(a,a);return a},has:function(a,b){return F(a,b)},select:function(a){return Qb(a,arguments,k)},reject:function(a){return Qb(a,arguments,n)}});G(p,n,n,x,function(a,b){var c="is"+b;Lb.push(c);a[c]=da[b]});(function(){D(p,n,function(){return arguments.length===0},{extend:function(){var a=Lb.concat(Mb);if(typeof ab!=="undefined")a=a.concat(ab);Aa(a,p)}})})();Aa(Mb,ra);})(); \ No newline at end of file diff --git a/js/webinosManager.js b/js/webinosManager.js index ee8ac91..3158818 100644 --- a/js/webinosManager.js +++ b/js/webinosManager.js @@ -74,7 +74,7 @@ function webinosManager(){ case "cn-getNotes": // Do nothing, we are asking for notes, we don't have notes. break; - case "cn-sendNotes": + case "cn-updatedNote": // The event has been sent by this client showAlert("Note succesfully created/updated"); break; @@ -86,7 +86,7 @@ function webinosManager(){ // Someone is asking for notesList sendGetNotesResponseEvent(event); break; - case "cn-sendNotes": + case "cn-updatedNote": // Someone has send a new or updated note showAlert(event.addressing.source.id.split('/')[1] + " has sent a new or updated note"); dataMgr.addNote(event.payload, notesList);