diff --git a/TODO b/TODO index 740ca9f..00adff5 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ Config Page Improve screenshot result Add favicon support +Need a solution to update folder and bookmark when it are updated from Firefox \ No newline at end of file diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 2fb0e6a..001e97e 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -34,6 +34,11 @@ "description": "Text of refresh menu item." }, + "menuCapturePage": { + "message": "Capture in a new tab", + "description": "Text of capture menu item." + }, + "menuDeleteItem": { "message": "Delete", "description": "Text of delete menu item." diff --git a/src/_locales/fr/messages.json b/src/_locales/fr/messages.json index ac834a8..d9f4c0b 100644 --- a/src/_locales/fr/messages.json +++ b/src/_locales/fr/messages.json @@ -34,6 +34,11 @@ "description": "Text of refresh menu item." }, + "menuCapturePage": { + "message": "Capturer dans un nouvel onglet", + "description": "Text of capture menu item." + }, + "menuDeleteItem": { "message": "Supprimer", "description": "Text of delete menu item." diff --git a/src/js/background.js b/src/js/background.js index e5096de..827b65d 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -1,15 +1,17 @@ var core = {}; // Main app object in background.js var app = {}; // Shared app object with pages -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.init = function(){ // Init module + core.Settings.load(function(){ + 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 -core.Settings.load = function(){ // Load settings and call core.init +core.Settings.load = function(callback){ // Load settings browser.storage.local.get({ background: '#3c4048', grid: { @@ -39,14 +41,15 @@ core.Settings.load = function(){ // Load settings and call core.init } }).then(function(obj){ app.settings = obj; - core.init(); + if(callback) callback(); }); } 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.init(); core.ContextMenus = {} // ContextMenu helper Object core.ContextMenus.initMenu = function(){ // (Called from core.init) Init context menu in all pages @@ -63,12 +66,15 @@ core.ContextMenus.initMenu = function(){ // (Called from core.init) Init context } core.Bookmarks = {} // Bookmarks helper object +core.Bookmarks._onCreated = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } +core.Bookmarks._onChanged = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } +core.Bookmarks._onMoved = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } +core.Bookmarks._onRemoved = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } 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); // /!\ Need to be removed - browser.bookmarks.onMoved.addListener(notifyBookmarksChanged); - browser.bookmarks.onRemoved.addListener(notifyBookmarksChanged); + browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); + //browser.bookmarks.onChanged.addListener(core.Bookmarks._onChanged); + browser.bookmarks.onMoved.addListener(core.Bookmarks._onMoved); + browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); } core.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and create it if not exist if(!callback) return; @@ -196,92 +202,88 @@ core.SiteInfos.fromWS = function(url, callback){ // Retrieve infos from a Web Se return core.SiteInfos.fromFrame(url, callback); } -core.GridNodes = {}; // GridNodes helper object /* -core.GridNodes.GridNodeType = { - empty: 0, - back: 1, - folder: 2, - bookmark:3 -} core.GridNodes.GridNode = function(){ - this.id = -1; - this.lastUpdate = new Date(0); + this.id = null; // 0 + //this.lastUpdate = new Date(0); this.type = core.GridNodes.GridNodeType.empty; - this.path = ''; - this.title = ''; - this.icon = ''; - this.image = ''; - //this.url = ''; - //this.children = []; + //this.path = ''; + this.title = null; // '' + this.icon = null; // '' + this.image = null; // '' + this.url = null; // '' + this.children = null; // [] } */ +core.GridNodes = {}; // GridNodes helper object +core.GridNodes.GridNodeType = { // GridNodeType + back: -1, + empty: 0, + folder: 1, + bookmark: 2 +} core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes with Bookmarks core.Bookmarks.load(rootPath, function(bookmarkItem){ - core.GridNodes.syncItem(gridNode, bookmarkItem); + function syncNode(gridNode, bookmarkItem){ + gridNode.id = bookmarkItem.id; + if(!gridNode.title) gridNode.title = bookmarkItem.title; + if(bookmarkItem.url){ + gridNode.type = core.GridNodes.GridNodeType.bookmark; + if(!gridNode.url) gridNode.url = bookmarkItem.url; + } else if(bookmarkItem.children){ + gridNode.type = core.GridNodes.GridNodeType.folder; + var EmptyNodes = []; + if(! gridNode.children) gridNode.children = []; + else { + for(var i=gridNode.children.length-1; i>=0; i--){ + if(gridNode.children[i].type==core.GridNodes.GridNodeType.empty){ + EmptyNodes.unshift(gridNode.children[i]); + } else { + var found = false; + for(var child of bookmarkItem.children){ + if(child.id==gridNode.children[i].id){ + found = true; + break; + } + } + if(! found){ + if(i0){ + childGridNode = EmptyNodes[0]; + EmptyNodes.shift(); + }else { + childGridNode = {}; + gridNode.children.push(childGridNode) + } + } + syncNode(childGridNode, child); + } + EmptyNodes.length = 0; + } else { + gridNode.type = core.GridNodes.GridNodeType.empty; + } + } + + syncNode(gridNode, bookmarkItem); core.GridNodes.save(); - browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); if(callback) callback(); }); } -core.GridNodes.syncItem = function(gridNode, bookmarkItem){ // Sync GridNode with BookmarkItem - gridNode.id = bookmarkItem.id; - gridNode.title = bookmarkItem.title; // /!\ Need check last update - if(bookmarkItem.url){ - gridNode.type = 'bookmark'; - gridNode.url = bookmarkItem.url; // /!\ Need check last update - } else if(bookmarkItem.children){ - gridNode.type = 'folder'; - var EmptyItems = []; - if(! gridNode.children) gridNode.children = []; - else { - for(var i=gridNode.children.length-1; i>=0; i--){ - if(gridNode.children[i].type!='empty'){ - var found = false; - for(var child of bookmarkItem.children){ - if(child.id==gridNode.children[i].id){ - found = true; - break; - } - } - if(! found){ - if(i0){ - childGridNode = EmptyItems[0]; - EmptyItems.shift(); - }else { - childGridNode = {}; - gridNode.children.push(childGridNode) - } - } - core.GridNodes.syncItem(childGridNode, child); - } - 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; + browser.runtime.sendMessage({ command: 'GridNodesSaved'}); } core.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootGridNode path if(path.length == 0 || path == '/') return gridNode; @@ -290,6 +292,98 @@ core.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootG return core.GridNodes.getNode(child, path.substr(child.title.length + 1)); return null; } +core.GridNodes.getChildNode = function(gridNode, id){ // Return child node by ID + for(var child of gridNode.children) if(child.id == id) return child; + return null; +} +core.GridNodes.saveNode = function(gridNode){ // Save GridNode + browser.storage.local.set(app.settings); + browser.runtime.sendMessage({ command: 'GridNodeSaved', gridNode: gridNode }); +} +core.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex. callback(gridNode, node1, node2) + while(newIndex>=gridNode.children.length) + gridNode.children.push({ type: core.GridNodes.GridNodeType.empty }); + var node1 = gridNode.children[index]; + var node2 = gridNode.children[newIndex]; + gridNode.children[index] = node2; + gridNode.children[newIndex] = node1; + for(var i=gridNode.children.length-1; i>=0; i--){ + if(gridNode.children[i].type != core.GridNodes.GridNodeType.empty) break; + gridNode.children.pop(); + } + core.GridNodes.saveNode(gridNode); + if(callback) callback(gridNode, node1, node2); +} +core.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode. callback(gridNode, newGridNode) + browser.bookmarks.onCreated.removeListener(core.Bookmarks._onCreated); + browser.bookmarks.create({ + parentId: gridNode.id, + title: name + }).then(function(bookmarkItem){ + if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ??? + browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); + var newGridNode = { id: bookmarkItem.id, type: core.GridNodes.GridNodeType.folder, title: name, children: [] }; + var EmptyCellFound = false; + for(var i=0; i=0; i--){ + if(gridNode.children[i].type != core.GridNodes.GridNodeType.empty) break; + gridNode.children.pop(); + } + browser.bookmarks.onRemoved.removeListener(core.Bookmarks._onRemoved); + browser.bookmarks.removeTree(id).then(function(){ + browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); + }, function(){ + browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); + }); + if(callback) callback(gridNode, id); +} + core.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of a GridNode if(gridNode.__isLoading == true) return; gridNode.__isLoading = true; @@ -297,43 +391,12 @@ core.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of if(infos){ gridNode.title = infos.title; gridNode.image = infos.screenshot; - browser.bookmarks.update(gridNode.id, { - title: infos.title - }).then(function(bookmarkItem){}, function(){}); + delete gridNode.__isLoading; core.GridNodes.saveNode(gridNode); - } - gridNode.__isLoading = false; + } else delete gridNode.__isLoading; if(callback) callback(infos); }); } -core.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode - browser.bookmarks.create({ - parentId: gridNode.id, - title: name - }).then(callback); -} -core.GridNodes.createBookmark = function(gridNode, url, title, callback){ // Create a new Bookmark in a GridNode - browser.bookmarks.create({ - parentId: gridNode.id, - title: title || url, - url: url - }).then(callback); -} -core.GridNodes.delete = function(id, callback){ // Delete a GridNode - browser.bookmarks.removeTree(id).then(callback); -} -core.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex - while(newIndex>=gridNode.children.length){ - gridNode.children.push({ type: 'empty' }); - } - var node1 = gridNode.children[index]; - var node2 = gridNode.children[newIndex]; - gridNode.children[index] = node2; - gridNode.children[newIndex] = node1; - core.GridNodes.saveNode(gridNode); - if(callback) callback(); - browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); -} core.GridNodes.capturePage = function(gridNode, callback){ browser.tabs.create({url: gridNode.url, active: false}).then(function(tab){ browser.tabs.update(tab.id, {muted: true}).then(function(){}, function(){}); @@ -348,12 +411,8 @@ core.GridNodes.capturePage = function(gridNode, callback){ browser.tabs.remove(tab.id); gridNode.title = tab.title gridNode.image = img; - browser.bookmarks.update(gridNode.id, { - title: gridNode.title - }).then(function(bookmarkItem){}, function(){}); core.GridNodes.saveNode(gridNode); if(callback) callback(); - browser.runtime.sendMessage({ command: 'gridNodesSynced'}).then(function(){}, function(){}); }, function(){ browser.tabs.remove(tab.id); if(callback) callback(); @@ -366,17 +425,18 @@ core.GridNodes.capturePage = function(gridNode, callback){ }, function(){}); } - setTimeout(whaitLoaded, 300); + setTimeout(whaitLoaded, 1000); }, function(){ if(callback) callback(); }); } -// Public functions +// Public members +app.GridNodeType = core.GridNodes.GridNodeType; app.refreshNode = core.GridNodes.refreshNode; app.getNode = core.GridNodes.getNode; app.createFolder = core.GridNodes.createFolder; app.createBookmark = core.GridNodes.createBookmark; -app.deleteNode = core.GridNodes.delete; +app.deleteNode = core.GridNodes.deleteNode; app.setNodeIndex = core.GridNodes.setNodeIndex; app.capturePage = core.GridNodes.capturePage; \ No newline at end of file diff --git a/src/js/dial.js b/src/js/dial.js index 3ac8138..a78201d 100644 --- a/src/js/dial.js +++ b/src/js/dial.js @@ -13,7 +13,14 @@ window.onload = function(){ dial.initUI(); browser.runtime.onMessage.addListener(function(request, sender, sendResponse){ switch(request.command){ - case 'gridNodesSynced': + case 'SettingsChanged': + //if(app.settings) dial.updateGridLayout(dial.Grid, app.settings.grid, dial.styles.grid); + break; + case 'GridNodesSaved': + if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); + break; + case 'GridNodeSaved': + // request.gridNode if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); break; } @@ -118,7 +125,7 @@ dial.initMenus = function(){ dial.ItemMenuRefresh.onclick = dial.refreshNode; dial.ItemMenuCapture = document.createElement('menuitem'); - dial.ItemMenuCapture.label = 'Capture' // browser.i18n.getMessage("menuRefreshItem"); + dial.ItemMenuCapture.label = browser.i18n.getMessage("menuCapturePage"); dial.ItemMenuCapture.onclick = dial.capturePage; dial.ItemMenuDelete = document.createElement('menuitem'); @@ -173,9 +180,7 @@ dial.initGrid = function(name, settings, container){ StartIndex-=1; EndIndex-=1; } - app.setNodeIndex(dial.Node, StartIndex, EndIndex, function(){ - dial.populateGrid(grid, app.settings.grid, dial.Node); - }); + app.setNodeIndex(dial.Node, StartIndex, EndIndex); } link.draggable = true; link.ondragstart = dragstart_handler; @@ -269,13 +274,13 @@ dial.populateGrid = function(grid, settings, node){ if(dial.page > 1) iBase = (dial.page -1) * maxCells; for(var i = iBase; i - - - - - - - - \ No newline at end of file diff --git a/src/test/test.js b/src/test/test.js deleted file mode 100644 index b6284bb..0000000 --- a/src/test/test.js +++ /dev/null @@ -1,21 +0,0 @@ -var url = 'https://www.matmoul.ch'; -var xmlHttp = new XMLHttpRequest(); -xmlHttp.timeout = 10000 -xmlHttp.open('GET', url, true); -//xmlHttp.setRequestHeader('X-PINGOTHER', 'pingpong'); -//xmlHttp.setRequestHeader('Content-Type', 'text/plain'); -//xmlHttp.setRequestHeader('Access-Control-Request-Method', '*'); -//xmlHttp.setRequestHeader('Origin', url); -//xmlHttp.setRequestHeader('Access-Control-Allow-Origin', '*'); -xmlHttp.onload = function(){ - iframe = document.getElementById('iframe'); - iframe.width = 800 - iframe.height = 600 - iframe.style.position = 'absolute'; - //iframe.style.visibility = 'hidden'; - var content = xmlHttp.responseText.replace('', ''); - //iframe.onload = function(){ pageLoaded(); } - //document.body.appendChild(iframe); - iframe.srcdoc = content; -} -xmlHttp.send();