From bac24fdb8487b1e44f028f406eb18c7a0c5821f8 Mon Sep 17 00:00:00 2001 From: matmoul Date: Tue, 3 Oct 2017 01:31:41 +0200 Subject: [PATCH] Large change --- src/js/background.js | 124 +++++++++++++++++++++---------------------- src/src.zip | Bin 19601 -> 20624 bytes 2 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/js/background.js b/src/js/background.js index 15c787e..e5096de 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -1,12 +1,11 @@ var core = {}; // Main app object in background.js var app = {}; // Shared app object with pages -core._init = function(){ // Called from core.Settings.load() - core.Bookmarks.initRoot(function(){ - core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); // Sync bookmarks with stored data +core.init = function(){ // Called from core.Settings.load() + core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root, function(){ // Sync bookmarks with stored data core.ContextMenus.initMenu(); core.Bookmarks.initListener(); - }) + }); } core.Settings = {}; // Settings helper object @@ -40,16 +39,17 @@ core.Settings.load = function(){ // Load settings and call core.init } }).then(function(obj){ app.settings = obj; - core._init(); - },function(){}); + core.init(); + }); } core.Settings.save = function(){ // Save settings browser.storage.local.set(app.settings); + browser.runtime.sendMessage({ command: 'SettingsChanged' }); } core.Settings.load(); // Need to be loaded first and call core.init when ready core.ContextMenus = {} // ContextMenu helper Object -core.ContextMenus.initMenu = function(){ // (Called from core._init) Init context menu in all pages +core.ContextMenus.initMenu = function(){ // (Called from core.init) Init context menu in all pages browser.contextMenus.create({ // Create Context menu id: 'AddToQuickDial', title: browser.i18n.getMessage("menuAddToQuickDial"), @@ -63,51 +63,33 @@ core.ContextMenus.initMenu = function(){ // (Called from core._init) Init contex } core.Bookmarks = {} // Bookmarks helper object -core.Bookmarks.initListener = function(){ // (Called from core._init) (/!\ Need filter to root tree only) Init listener of bookmarks +core.Bookmarks.initListener = function(){ // (Called from core.init) (/!\ Need filter to root tree only) Init listener of bookmarks function notifyBookmarksChanged(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } browser.bookmarks.onCreated.addListener(notifyBookmarksChanged); - browser.bookmarks.onChanged.addListener(notifyBookmarksChanged); + //browser.bookmarks.onChanged.addListener(notifyBookmarksChanged); // /!\ Need to be removed browser.bookmarks.onMoved.addListener(notifyBookmarksChanged); browser.bookmarks.onRemoved.addListener(notifyBookmarksChanged); } -core.Bookmarks.initRoot = function(callback){ // (Called from core._init) Create the root folder if not exist +core.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and create it if not exist + if(!callback) return; browser.bookmarks.getSubTree('menu________').then(function(bookmarkItems){ - getChildItem = function(bookmarkItem, path, callback){ + function getChildItem(bookmarkItem, path, callback){ if(path.length == 0){ - if(callback) callback(bookmarkItem); + callback(bookmarkItem); return; } - for(var child of bookmarkItem.children){ - if((path + '/').startsWith(child.title + '/')){ - getChildItem(child, path.substr(child.title.length + 1), callback); - return; - } - } + for(var child of bookmarkItem.children) + if((path + '/').startsWith(child.title + '/')) + return getChildItem(child, path.substr(child.title.length + 1), callback); browser.bookmarks.create({ parentId: bookmarkItem.id, title: path.substr(0, (path + '/').indexOf('/')) - }).then(callback); + }).then(function(bookmarkItem){ + return getChildItem(bookmarkItem, path.substr(bookmarkItem.title.length + 1), callback); + }, function(){ callback(); }); } - getChildItem(bookmarkItems[0], app.settings.grid.root, callback); - }, function(){ - console.log('Can not load bookmarks'); - if(callback) callback(null); - }); -} -core.Bookmarks.load = function(rootPath, callback){ // callback(bookmarkItem) Return BookmarkItem from rootPath - browser.bookmarks.getSubTree('menu________').then(function(bookmarkItems){ - if(callback) callback(core.Bookmarks.getItem(bookmarkItems[0], rootPath + '/')) - }, function(){ - console.log('Can not load bookmarks'); - if(callback) callback(null); - }); -} -core.Bookmarks.getItem = function(bookmarkItem, path){ // Return BookmarkItem from path from bookmarkItem as root - if(path.length == 0) return bookmarkItem; - for(var child of bookmarkItem.children) - if(path.startsWith(child.title + '/')) - return core.Bookmarks.getItem(child, path.substr(child.title.length + 1)); - return null; + getChildItem(bookmarkItems[0], rootPath, callback); + }, function(){ callback(); }); } core.SiteInfos = {} // Siteinfos helper object @@ -116,7 +98,7 @@ core.SiteInfos.fromTab = function(callback){ // Retrieve infos from current tab. function whaitLoaded(){ browser.tabs.get(tab.id).then(function(tab){ if(tab.status == 'loading') setTimeout(whaitLoaded, 300); - else{ + else { browser.tabs.update(tab.id, {active: true}).then(function(){ setTimeout(function(){ browser.tabs.captureVisibleTab().then(function(img){ @@ -127,18 +109,12 @@ core.SiteInfos.fromTab = function(callback){ // Retrieve infos from current tab. if(callback) callback(); }); }, 300); - }, function(){ - if(callback) callback(); - }); + }, function(){ if(callback) callback(); }); } - }, function(){ - if(callback) callback(); - }); + }, function(){ if(callback) callback(); }); } setTimeout(whaitLoaded, 300); - }, function(){ - if(callback) callback(); - }); + }, function(){ if(callback) callback(); }); } core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a new tab. callback( { url, title, icon, screenshot } || error: callback() ) browser.tabs.create({url: url, active: false}).then(function(tab){ @@ -146,7 +122,7 @@ core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a n function whaitLoaded(){ browser.tabs.get(tab.id).then(function(tab){ if(tab.status == 'loading') setTimeout(whaitLoaded, 300); - else{ + else { browser.tabs.update(tab.id, {active: true}).then(function(){ setTimeout(function(){ browser.tabs.captureVisibleTab().then(function(img){ @@ -157,18 +133,12 @@ core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a n if(callback) callback(); }); }, 300); - }, function(){ - if(callback) callback(); - }); + }, function(){ if(callback) callback(); }); } - }, function(){ - if(callback) callback(); - }); + }, function(){ if(callback) callback(); }); } setTimeout(whaitLoaded, 300); - }, function(){ - if(callback) callback(); - }); + }, function(){ if(callback) callback(); }); } core.SiteInfos.fromFrame = function(url, callback){ // Retrieve infos from an iframe. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() ) function pageLoaded(){ @@ -227,11 +197,31 @@ core.SiteInfos.fromWS = function(url, callback){ // Retrieve infos from a Web Se } core.GridNodes = {}; // GridNodes helper object -core.GridNodes.sync = function(gridNode, rootPath){ // Sync GridNodes with Bookmarks +/* +core.GridNodes.GridNodeType = { + empty: 0, + back: 1, + folder: 2, + bookmark:3 +} +core.GridNodes.GridNode = function(){ + this.id = -1; + this.lastUpdate = new Date(0); + this.type = core.GridNodes.GridNodeType.empty; + this.path = ''; + this.title = ''; + this.icon = ''; + this.image = ''; + //this.url = ''; + //this.children = []; +} +*/ +core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes with Bookmarks core.Bookmarks.load(rootPath, function(bookmarkItem){ core.GridNodes.syncItem(gridNode, bookmarkItem); + core.GridNodes.save(); browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); - core.Settings.save(); + if(callback) callback(); }); } core.GridNodes.syncItem = function(gridNode, bookmarkItem){ // Sync GridNode with BookmarkItem @@ -283,6 +273,12 @@ core.GridNodes.syncItem = function(gridNode, bookmarkItem){ // Sync GridNode wit EmptyItems.length = 0; } else node.type = 'empty'; } +core.GridNodes.save = function(){ // Save GridNode + browser.storage.local.set(app.settings); +} +core.GridNodes.saveNode = function(gridNode){ // Save GridNode + browser.storage.local.set(app.settings); +} core.GridNodes.getChild = function(gridNode, id){ // Return child node by ID for(var child of gridNode.children) if(child.id == id) return child; return null; @@ -304,7 +300,7 @@ core.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of browser.bookmarks.update(gridNode.id, { title: infos.title }).then(function(bookmarkItem){}, function(){}); - core.Settings.save(); + core.GridNodes.saveNode(gridNode); } gridNode.__isLoading = false; if(callback) callback(infos); @@ -334,7 +330,7 @@ core.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // var node2 = gridNode.children[newIndex]; gridNode.children[index] = node2; gridNode.children[newIndex] = node1; - core.Settings.save(); + core.GridNodes.saveNode(gridNode); if(callback) callback(); browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); } @@ -355,7 +351,7 @@ core.GridNodes.capturePage = function(gridNode, callback){ browser.bookmarks.update(gridNode.id, { title: gridNode.title }).then(function(bookmarkItem){}, function(){}); - core.Settings.save(); + core.GridNodes.saveNode(gridNode); if(callback) callback(); browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); }, function(){ diff --git a/src/src.zip b/src/src.zip index 2bdaea78f17dca622f29e80b0105a93a90b6e68b..f4731cbc624b9b6127220586655723458497047f 100644 GIT binary patch delta 5239 zcmZu#1z42J*I#x?W$6&fMd{WRSOlbN2@w!Ul}k&5H2cyeA*_H>0!oM=-Q6YK-HjkA zNPU3Ud;j--civ~>yfeQuGiT16=b2x`JB-)K7|@4E2qqcmGKpQ6jDX&TTvX`K7&jx7 zpV?aSW~DcoIM#iH^Mq5k|MlXHng^Wnxlp88j4oCU1oa z#?Kv4^*gWH`c@^#+8%m8K{37&<}_WkHC9p?jEp2>Vv=33y3h21*oC?vzH$8?n{f@$ z<4bzT{|en9t!1$T|Cze>6yw?^5?>0T)6Ar#_whw@j3F(L>EPC_qrk-wNV7YdC7#?x zuvD^fUa$jXt53lJlXj3nm>i`9=QAodh}W<@uHn-9sTa}5o@upv8&gy@6@xODaxoWi zyK_IE^)R<<58w2)ma6WTxt;vTl*g5T7_{$g%W0yatL{Sl)b|qjw7P`*2^m3}>p6## zxJC7I@^l0jRxQQZ7<*HZ%uubdk$k~DuBf)3N~duLu0Ef&rAe0A5i_u zaEkfnCe6atR+G}qwwEqk8*X`FoN&OftPP=~I?~Z! zQkV(isPqwgl5H?M5qrLUr;8E}m5Z~u(-xR?5+-rD>;09rPD4>4E6W)f67eFJkj*T9 zDwD|Rt{<*_#Mnj(!QNJam~|(&(tW>B{GeQjowxVxNNg<_JF_K`+LG=cX^lo`&mNji z-?^Y}Z3S^~7%5upyAcqZNLh~zL1(P=sgKSsBbLZ44LmOAn>bK0aQ!3B+!hCbrPj`>n6OSB7aUf_R2_6G*Tr7xFrBmm*j*?+{)k z=Q4BB;}PnJNeWxW@h6s$uHR5nn%ptSd~GXS(f8=-*sGy46lECQDYE$*4K59>KmHPV ztI3;4#%`-9YvWi4zLKKi>3$12eH;Fodvh7Q(wpZVO#y*Z+5qoFFIA)bVOI|~-k1yA zJQap!`pFl|?{?zsxlYo}*8(V8j+_AWkL5aU!* zrf2NZvyTaS#7r)T3Z$4pu0Z8_14i)Zsld-Ls@ZlQLmATJEsd9Fkk37B4+?&g4t$Q3 zsT0eR^0Rn^t?u07Me5oC2;lyKXW5e2|fMr>PTTwWSWS3-88)x73Patva43gj zR^cQB?(9o-D4bZPy4o_ww#ekeE`6KtU7i3FT{0`<+ui$$t!p+q+tnES@+lpAfwNfS#& zFiC-7i0<1KO=nFaC4Z3}{1&x2H4V72Ud7w11M#dv7O*Fv$ARH!FtVdjW*ZeWHY5GYL@#C|* z7$@&QXW#KW9hg0>+nuGIngGqi&3vBc5gUDCGE=muyTRQ_7X6cz;z9}cz#pHsH zMs}{m*eYtNG&MnyA^?$tvSBGhew2r)#}T1;g|~sJ(j5bR%~zS_X^V zYjqX^H88yPCQkRCVAk~-?8iHi!JmLivX7er3NQ34gI!J`Fy|PYbKE1^H`#9U_OGq-{OnO%SR(i_4(k6R~Jeq{TCM@Hg;)a!*?}!Ig!g`7Ud>5%0>ZG@^ z42iMj0zc@VkMcpQRrxN$7e-z2W#AXBLCh-ZcmIQvZmJoE0{DPM}n*;Q`&gj{oSF zzUxK(Lc00kg9k~Cf9z{ICIVA;YF_#mPxcp6lr;`?TpPIII;5%?p1XyPPt!|Qp6TR@ z$%-~fpw+}nKefv2vofA0fb@v)s7#R4Eq2axoCLV?UiAvDe)%H zi3ad8NsFNwl7|rfhE>s6^QS>VeU)yBly2Di*UrLn4KUSw8ZRm|4`4F>*#2!%+WUsE zWOkV$?*^@2ckiewL_5?8c9-a22e+L5U?C`h2wwXj_d0C%!w0cOASowT4i)ymON_9t zEuh?W6Hz}*`P>1?XKAw9tIFY2N))G4U>sQ0H=umo)ZJ{e&f^DA?+

YOP+$zvd!A zz*WL;%WFvr$CXNf1Gu9%6NdA`-#mmi7u7ZsOys1#-2f9-N(IvZtG zcTQ)gi`~U0TvV8Ba<2TPr-h^Jl>ldq|GtRqb(fnw`=pO@x(2;bH=Zg|%e-dpSu2mu zBrWd`7&bUoO4W}H$*4XODyRwgi2ux(8OkLdyggtTF`-1#R|kyc+yBTBhxb5G&_0Fg zsVAIYT~5Db6*d$OQ-yd8$_HC1iKPU!ZbZjdt_e(*Fg+Jy!)Aerq2CaQjN`YvS;PhE zHNUntOAKi)ld5pLrsS(7K7txYvK8m$Ckv4f0@|XT#^o_79>>?*&UG@z&-v9oYU5UB z^mpr0q1-MVRsiV`4-`D1OD;Y*vJEehIX$`id8(C)Ut3u>>D$+ATE&>KuIA})*zx=d zy3hAKyHRGvTn61?-{Y%gU)GS+P8kR#Mh@yun#K9E2YrGCH<*T}&lX4L4ig{n4|Srg zD!7y;t*yCJ-<1m~B8m@X_Qb!1MKrh!OiG^4D2RSYn>rbSGQ=LX9+`n!tbn0!r6 zMQ`~_H`E;5lo$7@;=YA{s@-{%uR=AoC4Q);5&@j4=ocOz6OC_|W*3VtQMrYyYSXj# zRCIFw5hR}V)0ucjXLeK6g+1w8)rTr%%)=snb6NCa{e8=hu40+FR+%Kd8)YoB<}cl3 zH8k^`%c?7g6we|5c-SGYUU+{N7Y{IygOR-h&+j1sE=cF%El179oRN6ZcXp8pevi2v z$ZhIiX`vS`PT<2pBt3jUM#|5ul!3!qx{4LMhl%?~ZPJq)vChZA4r-dayUR6g^v}%> zPE&~~qDD>n1F7V_n6weq1;=s+xYuVTPW*&qWvKz|t-WTkVLwA`*(i~1GT@$WveHV+ z0fD@1NurWvf&dE-KIz&y1Baee73f&vPQ6qKTb{ndAa{1fQ%gR~0@^_853$7Y5n1hE z^_QS~r9O*Wf9>VhRuZjYs8kFPNDu-7;s0YR=JrvK>XavViA2yjxut?+k%cjtz#5oD znu7vQ!SA4Ukh;4$nr6I+g*qh|*m6cIeNs2mc)#&Zz*=~BN*QwqtKrKH%|KC9c4qZf z$Kz+~LTW?7Jo&WG^>qqTgl9STHWs&GRf)4EIK;aJ()^3a0j^R4ydSH#5)hlhBk|K* z!zYaU70+%6C6#9iF)+?FmVjX}VBsY7(DwXv)2vEcRE_+{82{9$KRsK;ONu&!JUZcz zLcW?=mBeFopDRDT2+Whitb1qBP7&_e-X^s_d!s?E2f9DneF$_~h1h!V4Tonhebbuv z{g`TXU+04(|AXVGgcVC7u7~R7{dK$tP@++8~F5eCtyU%L{M8P^jn>w*Vtp4Wn2yJw9Pe&$a7tbsrUf1Uc7+?xuL*T=ThY zonM0a-l@>mj@6IlLAy?B=vPMB6sP;a$;@z7<)=>#tw-r;E$6QHXrB@!-qbPn60N`-Mzs>2AP1ou4! zQ`+qkEJvEdpWXLV-=E$V`k2;|kT9A+dtCXJXGyxQkk=WL{*Y2Id?>dir5Z_l3*H!9 zMZj8N@Jb>tFXCMm`{y0eI^a{kXAHsd_u)nN9|!fbES|7BekTNrYF|=ev+RKj-}}xd zRm`w8N3EQWsY0n&-!l_uG!mXg>ZcKl2!YWYC;Le>;fM%ndSL<2fh4SWz;*wVjEC!x=?!KLnM8d zdD7@avlwmj#*>Hus>3kll{Np!nljD3DhW2QJ{lQGVQ6BnG#V*#AWtZ#mRN*4Mv(dD zu?kCC5>0#Uy;$JAr^tX&lT6p5u^U8|FQYapN+OjW%uI4?mGU7H155__ixB!p+(4Jf zv0RZs^Kt?g)D44+Xd5f?YH)ey4Wk2>xy?WG<$Aw z;ZOgo{=XQi-_T;OYQ+ENtNun`@m;?x3H*t<48gzCxj0z%uYmm9`u`n~e?yABn0`b4 ziqC(~_unD#3VZ9KEcV*^2l$^Gy*yV%8m(%15a`kj|JM5N>-YDH0u}ys86P6CE{+-m PBD?qkFhQW*D---59d|5C delta 4194 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 H-|Bw=-5qIO