1
0
mirror of https://github.com/MatMoul/quickdial-webext.git synced 2025-12-16 17:03:12 +00:00

45 Commits

Author SHA1 Message Date
0b59809758 Version 0.1.6 2017-11-03 21:21:12 +01:00
f387c3662f Feature: Add page up and page down to change page 2017-11-03 21:11:57 +01:00
dbbf5ff718 Feature: Add page up and page down to change page 2017-11-03 21:02:57 +01:00
33c227a5a4 Merge branch 'patch-1' of https://github.com/Alexey71/quickdial-webext into Alexey71-patch-1 2017-11-03 20:54:11 +01:00
351d043094 Improvement: Limit sync bookmark surcharge 2017-11-03 20:52:41 +01:00
Alexey
b99ee356f0 Add Russian string 2017-11-01 15:35:47 +03:00
340a84730e Merge pull request #22 from mrprobot/develop
add german translation
2017-10-26 21:10:41 +02:00
mrprobot
ddd57dd446 add german translation 2017-10-25 13:04:20 +02:00
mrprobot
4a510a1a86 add german translation 2017-10-25 12:55:37 +02:00
170b1a7dc6 Improvement: Add new capture method (Capture here) 2017-10-22 16:36:06 +02:00
3c79e9e38f Version 0.1.5 2017-10-21 18:13:26 +02:00
5e61b65e82 Bug: (Properties) Image is lost when clicking OK and Unlock title don't work 2017-10-21 18:03:30 +02:00
cebdb32c35 Feature: Add a setting to lock title from update 2017-10-21 17:51:35 +02:00
1e5e450565 Improvement: Add escape support on popup 2017-10-21 17:10:51 +02:00
5a2c30e00f Feature: Root folder path customization 2017-10-21 16:53:39 +02:00
938f1a0fde Improvement: Don't send setNodeIndex if new index is the same than older index 2017-10-21 16:08:38 +02:00
4019c0cf77 Improvement: Use backgroundpage for data if possible 2017-10-21 14:43:56 +02:00
152506f463 Merge branch 'acolombo25-master' into develop 2017-10-18 20:12:17 +02:00
Andrea Colombo
cf0ed2bf69 Add Italian translation 2017-10-18 12:07:29 +02:00
121da31400 Version 0.1.4 2017-10-15 13:58:41 +02:00
7c9a1bb624 Project: Update TODO, README, Screenshots 2017-10-15 13:42:06 +02:00
550757a186 Bug: Prevent dragdrop on back node 2017-10-15 13:20:18 +02:00
dbe7751b77 Improvement: Old styles and old grid are removed after redrawing the new 2017-10-15 12:18:10 +02:00
957f468c59 Improvement: Add bookmark without sheme add http:// 2017-10-15 12:04:40 +02:00
325fdc8c83 Bug: Add to Quick Dial menu is missing 2017-10-15 11:53:33 +02:00
245d70a6eb Bug: Somme node are empty and make data unusable 2017-10-15 11:28:21 +02:00
4a3072bbdc Version 0.1.3 2017-10-15 01:14:23 +02:00
9c907f37e0 Improvement: Update thumbnails when url has changed 2017-10-15 00:51:50 +02:00
39f96b015b Feature: Add Default button on node properties 2017-10-15 00:25:12 +02:00
d3cc6cf68f Bug: Custom image are not displayed in properties window 2017-10-15 00:10:53 +02:00
b91255375f Bug: Custom image are not displayed in properties window 2017-10-15 00:02:41 +02:00
c00b227599 Version 0.1.2 2017-10-14 23:12:38 +02:00
73152dedd0 Feature: Add settings to set custom image on nodes 2017-10-14 23:11:33 +02:00
0f956667a0 Code: Rename var core to app 2017-10-14 22:43:48 +02:00
feafd8449e Feature: Add first support to editing nodes 2017-10-14 22:41:28 +02:00
20ca231945 Feature: Add Capture in a new Tab support for folder 2017-10-14 20:51:38 +02:00
30b432d1b8 Features: Add toolbar button 2017-10-14 19:33:20 +02:00
7e11b0b7da Stability: Encode url path 2017-10-14 19:00:15 +02:00
420f356136 Bug reported by Scienmind: Background color flickering on subfolder 2017-10-14 18:53:59 +02:00
d6ee45da30 Version 0.1.1 2017-10-14 17:20:59 +02:00
45a5bd5d44 Bug: Sync from bookmark is disabed 2017-10-14 17:13:57 +02:00
55521d2d53 Improvement: Speed start 2017-10-14 16:51:39 +02:00
1dd5409dd0 Version 0.1.0 2017-10-14 12:57:14 +02:00
039c3566ea Bug reported by Scienmind and Acid Crash: Private Window and Contextual Identities don't work 2017-10-14 12:44:56 +02:00
1413464149 Update screenshot 2017-10-08 19:10:46 +02:00
22 changed files with 1371 additions and 474 deletions

View File

@@ -1,2 +1,9 @@
# quickdial-webext # quickdial-webext
QuickDial is a WebExt Dial page for Firefox QuickDial is a WebExt Dial page for Firefox
[QuickDial on addons.mozilla.org](https://addons.mozilla.org/fr/firefox/addon/quick-dial/?src=search)
## Contribute and evolution :</br>
* [CONTRIBUTING.md](https://github.com/MatMoul/quickdial-webext/blob/develop/CONTRIBUTING.md)

3
TODO
View File

@@ -1,6 +1,5 @@
Add node settings popup
Add custom image (thumbnails)
Create style for popup Create style for popup
Add a visual hint for multipage
Need a best solution to update folder and bookmark when it are updated from Firefox Need a best solution to update folder and bookmark when it are updated from Firefox
Improve screenshot result Improve screenshot result
Add favicon support Add favicon support

Binary file not shown.

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 535 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 KiB

After

Width:  |  Height:  |  Size: 532 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 369 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 364 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 430 KiB

View File

@@ -0,0 +1,72 @@
{
"extensionDescription": {
"message": "Quick Dial, eine Schnellwahl-Seite inspiriert von Fast Dial.",
"description": "Description of the extension."
},
"menuAddToQuickDial": {
"message": "Zu Quick Dial hinzufügen",
"description": "Text of add bookmark menu item."
},
"menuNew": {
"message": "Neu",
"description": "Text of new menu item."
},
"menuNewBookmark": {
"message": "Lesezeichen",
"description": "Text of add bookmark menu item."
},
"AddBookmarkPrompt": {
"message": "Neue Lesezeichen URL eingeben:",
"description": "Text of the add bookmark prompt."
},
"menuNewFolder": {
"message": "Ordner",
"description": "Text of add folder menu item."
},
"AddFolderPrompt": {
"message": "Neuen Ordner Namen eingeben:",
"description": "Text of the add folder prompt."
},
"menuProperties": {
"message": "Bearbeiten",
"description": "Text of properties menu item."
},
"menuRefreshItem": {
"message": "Neu laden",
"description": "Text of refresh menu item."
},
"menuCaptureHere": {
"message": "Hier aufnehmen",
"description": "Text of capture here menu item."
},
"menuCapturePage": {
"message": "In einem neuen Tab aufnehmen",
"description": "Text of capture menu item."
},
"menuDeleteItem": {
"message": "Löschen",
"description": "Text of delete menu item."
},
"deleteItemConfimation": {
"message": "Löschen $1?",
"description": "Text of delete confirmation."
},
"menuSettings": {
"message": "Quick Dial Einstellungen",
"description": "Text of settings menu item."
}
}

View File

@@ -34,11 +34,21 @@
"description": "Text of the add folder prompt." "description": "Text of the add folder prompt."
}, },
"menuProperties": {
"message": "Properties",
"description": "Text of properties menu item."
},
"menuRefreshItem": { "menuRefreshItem": {
"message": "Refresh", "message": "Refresh",
"description": "Text of refresh menu item." "description": "Text of refresh menu item."
}, },
"menuCaptureHere": {
"message": "Capture here",
"description": "Text of capture here menu item."
},
"menuCapturePage": { "menuCapturePage": {
"message": "Capture in a new tab", "message": "Capture in a new tab",
"description": "Text of capture menu item." "description": "Text of capture menu item."

View File

@@ -34,11 +34,21 @@
"description": "Text of the add folder prompt." "description": "Text of the add folder prompt."
}, },
"menuProperties": {
"message": "Propriétés",
"description": "Text of properties menu item."
},
"menuRefreshItem": { "menuRefreshItem": {
"message": "Actualiser", "message": "Actualiser",
"description": "Text of refresh menu item." "description": "Text of refresh menu item."
}, },
"menuCaptureHere": {
"message": "Capturer ici",
"description": "Text of capture here menu item."
},
"menuCapturePage": { "menuCapturePage": {
"message": "Capturer dans un nouvel onglet", "message": "Capturer dans un nouvel onglet",
"description": "Text of capture menu item." "description": "Text of capture menu item."

View File

@@ -0,0 +1,67 @@
{
"extensionDescription": {
"message": "Quick Dial, una dial page inspirata a fast dial.",
"description": "Description of the extension."
},
"menuAddToQuickDial": {
"message": "Aggiungi a Quick Dial",
"description": "Text of add bookmark menu item."
},
"menuNew": {
"message": "Nuovo",
"description": "Text of new menu item."
},
"menuNewBookmark": {
"message": "Segnalibro",
"description": "Text of add bookmark menu item."
},
"AddBookmarkPrompt": {
"message": "Scrivi l'url del nuovo segnalibro:",
"description": "Text of the add bookmark prompt."
},
"menuNewFolder": {
"message": "Cartella",
"description": "Text of add folder menu item."
},
"AddFolderPrompt": {
"message": "Scrivi il nome della nuova cartella:",
"description": "Text of the add folder prompt."
},
"menuProperties": {
"message": "Proprietà",
"description": "Text of properties menu item."
},
"menuRefreshItem": {
"message": "Aggiorna",
"description": "Text of refresh menu item."
},
"menuCapturePage": {
"message": "Cattura in una nuova scheda",
"description": "Text of capture menu item."
},
"menuDeleteItem": {
"message": "Elimina",
"description": "Text of delete menu item."
},
"deleteItemConfimation": {
"message": "Eliminare $1?",
"description": "Text of delete confirmation."
},
"menuSettings": {
"message": "Impostazioni Quick Dial",
"description": "Text of settings menu item."
}
}

View File

@@ -0,0 +1,72 @@
{
"extensionDescription": {
"message": "Quick Dial, вдохновление умершим расширением Fast Dial.",
"description": "Description of the extension."
},
"menuAddToQuickDial": {
"message": "Добавить в Quick Dial",
"description": "Text of add bookmark menu item."
},
"menuNew": {
"message": "Добавить",
"description": "Text of new menu item."
},
"menuNewBookmark": {
"message": "Закладку",
"description": "Text of add bookmark menu item."
},
"AddBookmarkPrompt": {
"message": "Введите URL-адрес новой закладки:",
"description": "Text of the add bookmark prompt."
},
"menuNewFolder": {
"message": "Папку",
"description": "Text of add folder menu item."
},
"AddFolderPrompt": {
"message": "Введите имя новой папки:",
"description": "Text of the add folder prompt."
},
"menuProperties": {
"message": "Свойства",
"description": "Text of properties menu item."
},
"menuRefreshItem": {
"message": "Обновить",
"description": "Text of refresh menu item."
},
"menuCaptureHere": {
"message": "Захватить здесь",
"description": "Text of capture here menu item."
},
"menuCapturePage": {
"message": "Захватить на новой вкладке",
"description": "Text of capture menu item."
},
"menuDeleteItem": {
"message": "Удалить",
"description": "Text of delete menu item."
},
"deleteItemConfimation": {
"message": "Удалить $1?",
"description": "Text of delete confirmation."
},
"menuSettings": {
"message": "Настройки Quick Dial",
"description": "Text of settings menu item."
}
}

View File

@@ -1 +1 @@
<!DOCTYPE html><html><head id="head"><meta charset="utf-8" /><link rel="shortcut icon" type="image/png" href="img/24.png" /><title id="title"></title><script type="text/javascript" src="js/dial.js"></script></head><body id="body"></body></html> <!DOCTYPE html><html><head><meta charset="utf-8" /><link rel="shortcut icon" type="image/png" href="img/24.png" /><script type="text/javascript" src="js/dial.js"></script></head><body></body></html>

73
src/html/properties.html Normal file
View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" type="image/png" href="img/24.png" />
<title id="title">Quick Dial Node Propoerties</title>
<script type="text/javascript" src="/js/properties.js"></script>
<style>
body { margin: 0px; padding: 4px; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
h1 { font-size: 11pt; text-decoration: underline; }
input[type=number] { width: 56px; }
input[type=color] { width: 60px; }
.hidden { display: none; }
.Tab>table { width: 100%; border-collapse: collapse; }
.Tab .TabSpace { width: 100%; border-bottom: solid 1px #505050; }
.Tab .TabButton { border: solid 1px #505050; padding: 2px 6px 2px 6px; cursor: default; }
.Tab .TabButtonActive { border: solid 1px #505050; border-bottom: none; padding: 2px 6px 2px 6px; cursor: default; }
.Tab>div { padding: 8px; height: 330px; border-left: solid 1px #505050; border-bottom: solid 1px #505050; border-right: solid 1px #505050; }
</style>
</head>
<body>
<div id="Tabs" class="Tab">
<table>
<tr>
<td class="TabButtonActive">Main</td>
<td class="TabButton" style="display:none">Temp</td>
<td class="TabSpace"></td>
</tr>
</table>
<div>
<div>
<table style="width:100%">
<tr>
<td><span>Title :</span></td>
<td><input id="Title" type="text" style="width:100%"></td>
<td style="width:20px"><input id="TitleLocked" type="checkbox" title="Lock title"></td>
</tr>
<tr>
<td><span>Url :</span></td>
<td colspan="2"><input id="Url" type="text" style="width:100%"></td>
</tr>
<tr>
<td><span>Image :</span></td>
<td colspan="2">
<button id="ImageReset">Reset</button>
<button id="ImageDefault">Default</button>
<button class="hidden" id="ImageRefresh">Refresh</button>
<button class="hidden" id="ImageCapture">Capture</button>
<input id="ImageFile" type="file" style="width:180px;">
</td>
</tr>
<tr>
<td></td>
<td colspan="2"><div id="ImagePreview" style="width: 300px; height: 180px;"></div></td>
</tr>
</table>
</div>
<div class="hidden">
</div>
</div>
</div>
<div style="text-align: right; margin-top: 14px;">
<button id="BtnOk">OK</button>
<button id="BtnApply">Apply</button>
<button id="BtnCancel">Cancel</button>
</div>
</body>
</html>

View File

@@ -15,7 +15,7 @@
.Tab .TabSpace { width: 100%; border-bottom: solid 1px #505050; } .Tab .TabSpace { width: 100%; border-bottom: solid 1px #505050; }
.Tab .TabButton { border: solid 1px #505050; padding: 2px 6px 2px 6px; cursor: default; } .Tab .TabButton { border: solid 1px #505050; padding: 2px 6px 2px 6px; cursor: default; }
.Tab .TabButtonActive { border: solid 1px #505050; border-bottom: none; padding: 2px 6px 2px 6px; cursor: default; } .Tab .TabButtonActive { border: solid 1px #505050; border-bottom: none; padding: 2px 6px 2px 6px; cursor: default; }
.Tab>div { padding: 8px; height: 330px; border-left: solid 1px #505050; border-bottom: solid 1px #505050; border-right: solid 1px #505050; } .Tab>div { padding: 8px; height: 350px; border-left: solid 1px #505050; border-bottom: solid 1px #505050; border-right: solid 1px #505050; }
</style> </style>
</head> </head>
<body id="body"> <body id="body">
@@ -82,6 +82,12 @@
</td> </td>
</tr> </tr>
</table> </table>
<table style="width:100%;">
<tr>
<td><span>Root Folder :</span></td>
<td><input id="GridRoot" type="text" style="width:100%;"></td>
</tr>
</table>
</div> </div>
<div class="hidden"> <div class="hidden">
<table> <table>

View File

@@ -1,19 +1,109 @@
var core = {}; // Main app object in background.js var app = {}; // App object
var app = {}; // Shared app object with pages
core.init = function(){ // Init module app.init = function(){ // Init module
core.Settings.load(function(){ app.Settings.init(function(){
core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root, function(){ // Sync bookmarks with stored data app.Messages.init();
core.ContextMenus.initMenu(); browser.runtime.sendMessage({ cmd: app.Messages.Commands.settingsChanged });
core.Bookmarks.initListener(); browser.browserAction.onClicked.addListener(function(){
browser.tabs.create({});
});
app.GridNodes.sync(app.node, app.settings.grid.root, function(){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded });
app.Bookmarks.initListener();
app.ContextMenus.initMenu();
}); });
}); });
};
app.Messages = {}; // Messages helper object
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.init = function(){ // Init Messages Listeners
browser.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch(request.cmd){
case app.Messages.Commands.getSettings:
sendResponse(app.settings);
break;
case app.Messages.Commands.setSettings:
let rootChanged = (app.settings.grid.root!=request.settings.grid.root);
app.settings = request.settings;
app.Settings.save();
sendResponse(app.settings);
browser.runtime.sendMessage( { cmd: app.Messages.Commands.settingsChanged } );
if(rootChanged){
app.node = { children: [] };
app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); });
} else {
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
} }
break;
case app.Messages.Commands.getNodeByID:
var nodes = app.GridNodes.getNodeWithParents(request.id);
if(nodes) sendResponse(nodes[nodes.length-1]);
else sendResponse(null);
break;
case app.Messages.Commands.updateNode:
app.GridNodes.updateNode(app.GridNodes.getNodeById(request.id), request.value, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.getNode:
sendResponse(app.GridNodes.getNode(app.node, request.path.substr(1)));
break;
case app.Messages.Commands.setNodeIndex:
app.GridNodes.setNodeIndex(app.GridNodes.getNode(app.node, request.path.substr(1)), request.index, request.newIndex, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.createBookmark:
app.GridNodes.createBookmark(app.GridNodes.getNode(app.node, request.path.substr(1)), request.url, request.title, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.createFolder:
app.GridNodes.createFolder(app.GridNodes.getNode(app.node, request.path.substr(1)), request.name, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.deleteNode:
app.GridNodes.deleteNode(app.GridNodes.getNode(app.node, request.path.substr(1)), request.id, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.refreshNode:
app.GridNodes.refreshNode(app.GridNodes.getChildNode(app.GridNodes.getNode(app.node, request.path.substr(1)), request.id), function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
case app.Messages.Commands.capturePage:
app.GridNodes.capturePage(app.GridNodes.getChildNode(app.GridNodes.getNode(app.node, request.path.substr(1)), request.id), function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
break;
}
});
};
core.Settings = {}; // Settings helper object app.Settings = {}; // Settings helper object
core.Settings.load = function(callback){ // Load settings app.Settings.init = function(callback){ // Load settings and nodes
browser.storage.local.get({ browser.storage.local.get().then(function(data){
version: 2, if(Object.keys(data).length == 0) {
data = {
version: 3,
settings: {
backgroundColor: '#3c4048', backgroundColor: '#3c4048',
backgroundImage: null, backgroundImage: null,
grid: { grid: {
@@ -27,8 +117,6 @@ core.Settings.load = function(callback){ // Load settings
cells: { cells: {
margin: 4, margin: 4,
marginHover: 4, marginHover: 4,
ratioX: 4,
ratioY: 3,
backgroundColor: null, backgroundColor: null,
backgroundColorHover: null, backgroundColorHover: null,
borderColor: '#333333', borderColor: '#333333',
@@ -42,66 +130,97 @@ core.Settings.load = function(callback){ // Load settings
titleColor: '#ffffff', titleColor: '#ffffff',
titleColorHover: '#33ccff', titleColorHover: '#33ccff',
titleBackgroundColor: null, titleBackgroundColor: null,
titleBackgroundColorHover: null titleBackgroundColorHover: null,
previewWidth: 1200,
previewHeight: 710
}, },
root: 'Quick Dial', root: 'Quick Dial',
}
},
node: { children: [] } node: { children: [] }
} }
}).then(function(obj){
if(obj.grid.cells.backIcon){ // Upgrade Data Version
obj.version = 2;
obj.grid.backNode = true;
obj.grid.backIcon = 'url(/img/back.png)';
obj.grid.folderIcon = 'url(/img/folder.png)';
obj.grid.loadingIcon = 'url(/img/throbber.gif)';
obj.grid.cells.backgroundColor = null;
obj.grid.cells.backgroundColorHover = null;
obj.grid.cells.titleBackgroundColor = null;
obj.grid.cells.titleBackgroundColorHover = null;
delete obj.grid.cells.backIcon;
delete obj.grid.cells.folderIcon;
delete obj.grid.cells.loadingIcon;
delete obj.grid.cells.backPanel;
} }
app.settings = obj; if(!data.version){ // Upgrade Data Version
if(callback) callback(); data.version = 2;
data.grid.backNode = true;
data.grid.backIcon = 'url(/img/back.png)';
data.grid.folderIcon = 'url(/img/folder.png)';
data.grid.loadingIcon = 'url(/img/throbber.gif)';
data.grid.cells.backgroundColor = null;
data.grid.cells.backgroundColorHover = null;
data.grid.cells.titleBackgroundColor = null;
data.grid.cells.titleBackgroundColorHover = null;
delete data.grid.cells.backIcon;
delete data.grid.cells.folderIcon;
delete data.grid.cells.loadingIcon;
delete data.grid.cells.backPanel;
}
if(data.version == 2){ // Upgrade Data Version
var oldData = data;
data = {};
data.version = 3;
data.settings = oldData;
data.node = oldData.grid.node;
delete data.settings.version;
delete data.settings.grid.node;
app.settings = data.settings;
app.node = data.node;
browser.storage.local.clear().then(function(){
app.Settings.save();
}); });
} }
core.Settings.save = function(){ // Save settings app.settings = data.settings;
browser.storage.local.set(app.settings); app.node = data.node;
browser.runtime.sendMessage({ command: 'SettingsChanged' }); if(callback) callback();
}, function(){ console.log('Error loading data'); });
};
app.Settings.update = function(settings, callback){ // Save new settings
app.settings = settings;
app.Settings.save(callback);
};
app.Settings.save = function(callback){ // Save settings
var data = { version: 3 };
data.settings = app.settings;
data.node = app.node;
browser.storage.local.set(data).then(function(){
if(callback) callback();
}, function(){ console.log('Error saving settings'); });
} }
core.init(); app.init();
core.ContextMenus = {} // ContextMenu helper Object app.ContextMenus = {} // ContextMenu helper Object
core.ContextMenus.initMenu = function(){ // (Called from core.init) Init context menu in all pages app.ContextMenus.initMenu = function(){ // (Called from app.init) Init context menu in all pages
browser.contextMenus.create({ // Create Context menu browser.contextMenus.create({ // Create Context menu
id: 'AddToQuickDial', id: 'AddToQuickDial',
title: browser.i18n.getMessage("menuAddToQuickDial"), title: browser.i18n.getMessage("menuAddToQuickDial"),
contexts: ["all"], contexts: ["all"],
documentUrlPatterns: [ 'http://*/*', 'https://*/*', 'file://*/*' ] documentUrlPatterns: [ 'http://*/*', 'https://*/*', 'file://*/*', 'ftp://*/*' ]
}, function(){}); }, function(){});
browser.contextMenus.onClicked.addListener(function(info, tab) { // Context menu click event browser.contextMenus.onClicked.addListener(function(info, tab) { // Context menu click event
if (info.menuItemId == "AddToQuickDial") if (info.menuItemId == "AddToQuickDial")
core.GridNodes.createBookmark(app.settings.grid.node, info.pageUrl, tab.title, function(){}); app.GridNodes.createBookmark(app.node, info.pageUrl, tab.title, function(){
browser.runtime.sendMessage( { cmd: app.Messages.Commands.gridNodesLoaded } );
});
}); });
} }
core.Bookmarks = {} // Bookmarks helper object app.Bookmarks = {} // Bookmarks helper object
core.Bookmarks._onCreated = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onCreated = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks._onChanged = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onChanged = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks._onMoved = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onMoved = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks._onRemoved = function(){ core.GridNodes.sync(app.settings.grid.node, app.settings.grid.root); } app.Bookmarks._onRemoved = function(){ app.GridNodes.sync(app.node, app.settings.grid.root, function(){ browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded }); }); }
core.Bookmarks.initListener = function(){ // (Called from core.init) (/!\ Need filter to root tree only) Init listener of bookmarks app.Bookmarks.initListener = function(){ // (Called from app.init) (/!\ Need filter to root tree only) Init listener of bookmarks
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
//browser.bookmarks.onChanged.addListener(core.Bookmarks._onChanged); browser.bookmarks.onChanged.addListener(app.Bookmarks._onChanged);
browser.bookmarks.onMoved.addListener(core.Bookmarks._onMoved); browser.bookmarks.onMoved.addListener(app.Bookmarks._onMoved);
browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.addListener(app.Bookmarks._onRemoved);
} }
core.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and create it if not exist app.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and create it if not exist
if(!callback) return; if(!callback) return;
browser.bookmarks.getSubTree('menu________').then(function(bookmarkItems){ var root = 'menu________';
if(rootPath.substr(0,1)=='/') root = 'root________';
browser.bookmarks.getSubTree(root).then(function(bookmarkItems){
function getChildItem(bookmarkItem, path, callback){ function getChildItem(bookmarkItem, path, callback){
if(path.length == 0){ if(path.length == 0){
callback(bookmarkItem); callback(bookmarkItem);
@@ -117,35 +236,13 @@ core.Bookmarks.load = function(rootPath, callback){ // Load root bookmark and cr
return getChildItem(bookmarkItem, path.substr(bookmarkItem.title.length + 1), callback); return getChildItem(bookmarkItem, path.substr(bookmarkItem.title.length + 1), callback);
}, function(){ callback(); }); }, function(){ callback(); });
} }
getChildItem(bookmarkItems[0], rootPath, callback); if(rootPath.substr(0,1)=='/') getChildItem(bookmarkItems[0], rootPath.substr(1), callback);
else getChildItem(bookmarkItems[0], rootPath, callback);
}, function(){ callback(); }); }, function(){ callback(); });
} }
core.SiteInfos = {} // Siteinfos helper object app.SiteInfos = {} // Siteinfos helper object
core.SiteInfos.fromTab = function(callback){ // Retrieve infos from current tab. callback( { url, title, icon, screenshot } || error: callback() ) app.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a new tab. callback( { url, title, icon, screenshot } || error: callback() )
browser.tabs.getCurrent().then(function(tab){
function whaitLoaded(){
browser.tabs.get(tab.id).then(function(tab){
if(tab.status == 'loading') setTimeout(whaitLoaded, 300);
else {
browser.tabs.update(tab.id, {active: true}).then(function(){
setTimeout(function(){
browser.tabs.captureVisibleTab().then(function(img){
browser.tabs.remove(tab.id);
if(callback) callback( { url: tab.url, title: tab.title, icon: tab.favIconUrl, screenshot: img } );
}, function(){
browser.tabs.remove(tab.id);
if(callback) callback();
});
}, 300);
}, function(){ if(callback) callback(); });
}
}, function(){ if(callback) callback(); });
}
setTimeout(whaitLoaded, 300);
}, 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){ browser.tabs.create({url: url, active: false}).then(function(tab){
browser.tabs.update(tab.id, {muted: true}).then(); browser.tabs.update(tab.id, {muted: true}).then();
function whaitLoaded(){ function whaitLoaded(){
@@ -185,12 +282,12 @@ core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a n
ctx.restore(); ctx.restore();
img = canvas.toDataURL(); img = canvas.toDataURL();
if(callback) callback( { url: tab.url, title: tab.title, icon: tab.favIconUrl, screenshot: img } ); if(callback) callback( { url: tab.url, title: tab.title, icon: tab.favIconUrl, screenshot: img } );
}, 1); }, 100);
}, function(){ }, function(){
browser.tabs.remove(tab.id); browser.tabs.remove(tab.id);
if(callback) callback(); if(callback) callback();
}); });
}, 300); }, 500);
}, function(){ if(callback) callback(); }); }, function(){ if(callback) callback(); });
} }
}, function(){ if(callback) callback(); }); }, function(){ if(callback) callback(); });
@@ -198,7 +295,7 @@ core.SiteInfos.fromNewTab = function(url, callback){ // Retrieve infos from a n
setTimeout(whaitLoaded, 300); 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() ) app.SiteInfos.fromFrame = function(url, callback){ // Retrieve infos from an iframe. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() )
function pageLoaded(){ function pageLoaded(){
if(!iframe) return; if(!iframe) return;
var docTitle = iframe.contentWindow.document.title; var docTitle = iframe.contentWindow.document.title;
@@ -249,46 +346,39 @@ core.SiteInfos.fromFrame = function(url, callback){ // Retrieve infos from an if
xmlHttp.ontimeout = function(){ if(callback) callback(); } xmlHttp.ontimeout = function(){ if(callback) callback(); }
xmlHttp.send(); xmlHttp.send();
} }
core.SiteInfos.fromWS = function(url, callback){ // Retrieve infos from a Web Service. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() ) app.SiteInfos.fromWS = function(url, callback){ // Retrieve infos from a Web Service. callback( { url, title, (/!\ Not handled now)icon, screenshot } || error: callback() )
console.log('Not implemented'); console.log('Not implemented');
return core.SiteInfos.fromFrame(url, callback); return app.SiteInfos.fromFrame(url, callback);
} }
/* app.GridNodes = {}; // GridNodes helper object
core.GridNodes.GridNode = function(){ app.GridNodes.GridNodeType = { // GridNodeType
this.id = null; // 0
//this.lastUpdate = new Date(0);
this.type = core.GridNodes.GridNodeType.empty;
//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, back: -1,
empty: 0, empty: 0,
folder: 1, folder: 1,
bookmark: 2 bookmark: 2
} }
core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes with Bookmarks app.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes with Bookmarks
core.Bookmarks.load(rootPath, function(bookmarkItem){ if(app.GridNodes._syncing) {
app.GridNodes._needSync = true;
return;
}
app.GridNodes._syncing = true;
app.Bookmarks.load(rootPath, function(bookmarkItem){
function syncNode(gridNode, bookmarkItem){ function syncNode(gridNode, bookmarkItem){
gridNode.id = bookmarkItem.id; gridNode.id = bookmarkItem.id;
if(!gridNode.title) gridNode.title = bookmarkItem.title; if(!gridNode.title) gridNode.title = bookmarkItem.title;
if(bookmarkItem.url){ if(bookmarkItem.url){
gridNode.type = core.GridNodes.GridNodeType.bookmark; gridNode.type = app.GridNodes.GridNodeType.bookmark;
if(!gridNode.url) gridNode.url = bookmarkItem.url; if(!gridNode.url) gridNode.url = bookmarkItem.url;
} else if(bookmarkItem.children){ } else if(bookmarkItem.children){
gridNode.type = core.GridNodes.GridNodeType.folder; gridNode.type = app.GridNodes.GridNodeType.folder;
var EmptyNodes = []; var EmptyNodes = [];
if(! gridNode.children) gridNode.children = []; if(! gridNode.children) gridNode.children = [];
else { else {
for(var i=gridNode.children.length-1; i>=0; i--){ for(var i=gridNode.children.length-1; i>=0; i--){
if(gridNode.children[i].type==core.GridNodes.GridNodeType.empty){ if(!gridNode.children[i]) gridNode.children[i] = { type: app.GridNodes.GridNodeType.empty };
if(gridNode.children[i].type==app.GridNodes.GridNodeType.empty){
EmptyNodes.unshift(gridNode.children[i]); EmptyNodes.unshift(gridNode.children[i]);
} else { } else {
var found = false; var found = false;
@@ -300,7 +390,7 @@ core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes
} }
if(! found){ if(! found){
if(i<gridNode.children.length - 1){ if(i<gridNode.children.length - 1){
gridNode.children[i] = { type: core.GridNodes.GridNodeType.empty }; gridNode.children[i] = { type: app.GridNodes.GridNodeType.empty };
EmptyNodes.unshift(gridNode.children[i]); EmptyNodes.unshift(gridNode.children[i]);
} else { } else {
gridNode.children.pop(); gridNode.children.pop();
@@ -310,7 +400,7 @@ core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes
} }
} }
for(var child of bookmarkItem.children){ for(var child of bookmarkItem.children){
var childGridNode = core.GridNodes.getChildNode(gridNode, child.id); var childGridNode = app.GridNodes.getChildNode(gridNode, child.id);
if(!childGridNode){ if(!childGridNode){
if(EmptyNodes.length>0){ if(EmptyNodes.length>0){
childGridNode = EmptyNodes[0]; childGridNode = EmptyNodes[0];
@@ -324,152 +414,228 @@ core.GridNodes.sync = function(gridNode, rootPath, callback){ // Sync GridNodes
} }
EmptyNodes.length = 0; EmptyNodes.length = 0;
} else { } else {
gridNode.type = core.GridNodes.GridNodeType.empty; gridNode.type = app.GridNodes.GridNodeType.empty;
} }
} }
syncNode(gridNode, bookmarkItem); syncNode(gridNode, bookmarkItem);
core.GridNodes.save(); delete app.GridNodes._syncing;
if(app.GridNodes._needSync == true) {
delete app.GridNodes._needSync;
app.GridNodes.sync(gridNode, rootPath, callback);
} else {
app.GridNodes.save();
if(callback) callback(); if(callback) callback();
}
}); });
} }
core.GridNodes.save = function(){ // Save GridNode app.GridNodes.save = function(callback){ // Save GridNodes
browser.storage.local.set(app.settings); app.Settings.save(callback);
browser.runtime.sendMessage({ command: 'GridNodesSaved'});
} }
core.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootGridNode path app.GridNodes.getNode = function(gridNode, path){ // Return GridNode from RootGridNode path
if(path.length == 0 || path == '/') return gridNode; if(path.length == 0 || path == '/') return gridNode;
for(var child of gridNode.children) for(var child of gridNode.children)
if(path.startsWith(child.title + '/')) if(path.startsWith(child.title + '/'))
return core.GridNodes.getNode(child, path.substr(child.title.length + 1)); return app.GridNodes.getNode(child, path.substr(child.title.length + 1));
return null; return null;
} }
core.GridNodes.getChildNode = function(gridNode, id){ // Return child node by ID app.GridNodes.getNodeById = function(id){
var nodes = app.GridNodes.getNodeWithParents(id);
if(nodes) return nodes[nodes.length-1];
return null;
}
app.GridNodes.getNodeWithParents = function(id){
var parents = [];
function findNode(gridNode){
if(gridNode.id == id){
parents.unshift(gridNode);
return gridNode;
}
if(gridNode.children){
for(var i=0; i<gridNode.children.length; i++){
var result = findNode(gridNode.children[i]);
if(result){
parents.unshift(gridNode);
return result;
}
}
}
return null;
}
findNode(app.node, id);
if(parents.length>0) return parents;
return null;
}
app.GridNodes.updateNode = function(gridNode, value, callback){
if(value){
if(value.title) gridNode.title = value.title;
if(value.titleLocked!=null) gridNode.titleLocked = value.titleLocked;
if(value.image) gridNode.image = value.image;
else delete gridNode.image;
if(gridNode.type == app.GridNodes.GridNodeType.bookmark && value.url && gridNode.url != value.url){
gridNode.url = value.url;
app.GridNodes.refreshNode(gridNode, function(){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.gridNodesLoaded });
});
}
app.GridNodes.saveNode(gridNode);
}
if(callback) callback(gridNode);
}
app.GridNodes.getChildNode = function(gridNode, id){ // Return child node by ID
for(var child of gridNode.children) if(child.id == id) return child; for(var child of gridNode.children) if(child.id == id) return child;
return null; return null;
} }
core.GridNodes.saveNode = function(gridNode){ // Save GridNode app.GridNodes.saveNode = function(gridNode, callback){ // Save GridNode
browser.storage.local.set(app.settings); app.Settings.save(callback);
browser.runtime.sendMessage({ command: 'GridNodeSaved', gridNode: gridNode });
} }
core.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex. callback(gridNode, node1, node2) app.GridNodes.setNodeIndex = function(gridNode, index, newIndex, callback){ // Set Child GridNodeIndex. callback(gridNode, node1, node2)
while(newIndex>=gridNode.children.length) while(newIndex>=gridNode.children.length)
gridNode.children.push({ type: core.GridNodes.GridNodeType.empty }); gridNode.children.push({ type: app.GridNodes.GridNodeType.empty });
var node1 = gridNode.children[index]; var node1 = gridNode.children[index];
var node2 = gridNode.children[newIndex]; var node2 = gridNode.children[newIndex];
gridNode.children[index] = node2; gridNode.children[index] = node2;
gridNode.children[newIndex] = node1; gridNode.children[newIndex] = node1;
for(var i=gridNode.children.length-1; i>=0; i--){ for(var i=gridNode.children.length-1; i>=0; i--){
if(gridNode.children[i].type != core.GridNodes.GridNodeType.empty) break; if(gridNode.children[i].type != app.GridNodes.GridNodeType.empty) break;
gridNode.children.pop(); gridNode.children.pop();
} }
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
if(callback) callback(gridNode, node1, node2); if(callback) callback(gridNode, node1, node2);
} }
core.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode. callback(gridNode, newGridNode) app.GridNodes.createBookmark = function(gridNode, url, title, callback){ // Create a new Bookmark in a GridNode. callback(gridNode, newGridNode)
browser.bookmarks.onCreated.removeListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.removeListener(app.Bookmarks._onCreated);
var prefix = '';
if(url.indexOf('://')<0) prefix = 'http://';
browser.bookmarks.create({
parentId: gridNode.id,
title: title || url,
url: prefix + url
}).then(function(bookmarkItem){
if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ???
browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
var newGridNode = { id: bookmarkItem.id, type: app.GridNodes.GridNodeType.bookmark, url: prefix + url, title };
var EmptyCellFound = false;
for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].type == app.GridNodes.GridNodeType.empty){
EmptyCellFound = true;
gridNode.children[i] = newGridNode;
break;
}
}
if(EmptyCellFound == false) gridNode.children.push(newGridNode);
app.GridNodes.saveNode(newGridNode);
if(callback) callback(gridNode, newGridNode);
}, function(){
browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
});
}
app.GridNodes.createFolder = function(gridNode, name, callback){ // Create a new folder in a GridNode. callback(gridNode, newGridNode)
browser.bookmarks.onCreated.removeListener(app.Bookmarks._onCreated);
browser.bookmarks.create({ browser.bookmarks.create({
parentId: gridNode.id, parentId: gridNode.id,
title: name title: name
}).then(function(bookmarkItem){ }).then(function(bookmarkItem){
if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ??? if(!gridNode) return; // ??? Why this method are called a second time with gridNode = null ???
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
var newGridNode = { id: bookmarkItem.id, type: core.GridNodes.GridNodeType.folder, title: name, children: [] }; var newGridNode = { id: bookmarkItem.id, type: app.GridNodes.GridNodeType.folder, title: name, children: [] };
var EmptyCellFound = false; var EmptyCellFound = false;
for(var i=0; i<gridNode.children.length; i++){ for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].type == core.GridNodes.GridNodeType.empty){ if(gridNode.children[i].type == app.GridNodes.GridNodeType.empty){
EmptyCellFound = true; EmptyCellFound = true;
gridNode.children[i] = newGridNode; gridNode.children[i] = newGridNode;
break; break;
} }
} }
if(EmptyCellFound == false) gridNode.children.push(newGridNode); if(EmptyCellFound == false) gridNode.children.push(newGridNode);
core.GridNodes.saveNode(newGridNode); app.GridNodes.saveNode(newGridNode);
if(callback) callback(gridNode, newGridNode); if(callback) callback(gridNode, newGridNode);
}, function(){ }, function(){
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated); browser.bookmarks.onCreated.addListener(app.Bookmarks._onCreated);
}); });
} }
core.GridNodes.createBookmark = function(gridNode, url, title, callback){ // Create a new Bookmark in a GridNode. callback(gridNode, newGridNode) app.GridNodes.deleteNode = function(gridNode, id, callback){ // Delete a GridNode. callback(gridNode, id)
browser.bookmarks.onCreated.removeListener(core.Bookmarks._onCreated);
browser.bookmarks.create({
parentId: gridNode.id,
title: title || url,
url: url
}).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.bookmark, url: url, title };
var EmptyCellFound = false;
for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].type == core.GridNodes.GridNodeType.empty){
EmptyCellFound = true;
gridNode.children[i] = newGridNode;
break;
}
}
if(EmptyCellFound == false) gridNode.children.push(newGridNode);
core.GridNodes.saveNode(newGridNode);
if(callback) callback(gridNode, newGridNode);
}, function(){
browser.bookmarks.onCreated.addListener(core.Bookmarks._onCreated);
});
}
core.GridNodes.deleteNode = function(gridNode, id, callback){ // Delete a GridNode. callback(gridNode, id)
for(var i=0; i<gridNode.children.length; i++){ for(var i=0; i<gridNode.children.length; i++){
if(gridNode.children[i].id == id){ if(gridNode.children[i].id == id){
gridNode.children[i] = { type: core.GridNodes.GridNodeType.empty }; gridNode.children[i] = { type: app.GridNodes.GridNodeType.empty };
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
break; break;
} }
} }
for(var i=gridNode.children.length-1; i>=0; i--){ for(var i=gridNode.children.length-1; i>=0; i--){
if(gridNode.children[i].type != core.GridNodes.GridNodeType.empty) break; if(gridNode.children[i].type != app.GridNodes.GridNodeType.empty) break;
gridNode.children.pop(); gridNode.children.pop();
} }
browser.bookmarks.onRemoved.removeListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.removeListener(app.Bookmarks._onRemoved);
browser.bookmarks.removeTree(id).then(function(){ browser.bookmarks.removeTree(id).then(function(){
browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.addListener(app.Bookmarks._onRemoved);
}, function(){ }, function(){
browser.bookmarks.onRemoved.addListener(core.Bookmarks._onRemoved); browser.bookmarks.onRemoved.addListener(app.Bookmarks._onRemoved);
}); });
if(callback) callback(gridNode, id); if(callback) callback(gridNode, id);
} }
core.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of a GridNode app.GridNodes.refreshNode = function(gridNode, callback){ // Refresh content of a GridNode
if(gridNode.__isLoading == true) return; if(gridNode.__isLoading == true) return;
gridNode.__isLoading = true; gridNode.__isLoading = true;
core.SiteInfos.fromFrame(gridNode.url, function(infos){ switch(gridNode.type){
if(infos){ case app.GridNodes.GridNodeType.folder:
gridNode.title = infos.title; delete gridNode.image;
gridNode.image = infos.screenshot;
delete gridNode.__isLoading; delete gridNode.__isLoading;
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
} else delete gridNode.__isLoading; if(callback) callback({ title: gridNode.title, screenshot: gridNode.image });
break;
case app.GridNodes.GridNodeType.bookmark:
app.SiteInfos.fromFrame(gridNode.url, function(infos){
if(infos){
if(gridNode.titleLocked!=true) gridNode.title = infos.title;
gridNode.image = infos.screenshot;
} else {
gridNode.image = '0';
}
delete gridNode.__isLoading;
app.GridNodes.saveNode(gridNode);
if(callback) callback(infos); if(callback) callback(infos);
}); });
break;
} }
core.GridNodes.capturePage = function(gridNode, callback){ }
app.GridNodes.capturePage = function(gridNode, callback){
if(gridNode.__isLoading == true) return; if(gridNode.__isLoading == true) return;
gridNode.__isLoading = true; gridNode.__isLoading = true;
core.SiteInfos.fromNewTab(gridNode.url, function(infos){ switch(gridNode.type){
case app.GridNodes.GridNodeType.folder:
var nodes = app.GridNodes.getNodeWithParents(gridNode.id);
if(nodes){
var path = '';
for(var i=1; i<nodes.length; i++) path = path + '/' + nodes[i].title;
app.SiteInfos.fromNewTab('/dial?path=' + path, function(infos){
if(infos){ if(infos){
gridNode.title = infos.title;
gridNode.image = infos.screenshot; gridNode.image = infos.screenshot;
} else {
delete gridNode.image;
}
delete gridNode.__isLoading; delete gridNode.__isLoading;
core.GridNodes.saveNode(gridNode); app.GridNodes.saveNode(gridNode);
} else delete gridNode.__isLoading; if(callback) callback({ title: gridNode.title, screenshot: gridNode.image });
if(callback) callback(infos);
}); });
} }
break;
// Public members case app.GridNodes.GridNodeType.bookmark:
app.GridNodeType = core.GridNodes.GridNodeType; app.SiteInfos.fromNewTab(gridNode.url, function(infos){
app.refreshNode = core.GridNodes.refreshNode; if(infos){
app.getNode = core.GridNodes.getNode; if(gridNode.titleLocked!=true) gridNode.title = infos.title;
app.createFolder = core.GridNodes.createFolder; gridNode.image = infos.screenshot;
app.createBookmark = core.GridNodes.createBookmark; } else {
app.deleteNode = core.GridNodes.deleteNode; gridNode.image = '0';
app.setNodeIndex = core.GridNodes.setNodeIndex; }
app.capturePage = core.GridNodes.capturePage; delete gridNode.__isLoading;
app.saveSettings = core.Settings.save; app.GridNodes.saveNode(gridNode);
if(callback) callback(infos);
});
break;
}
}

View File

@@ -1,94 +1,257 @@
var app = {} var utils = {};
var app = {};
var dial = { var dial = {
styles: {},
page: 1, page: 1,
maxpage: 1 maxpage: 1,
capture: 0
}; };
window.onload = function(){ document.addEventListener("DOMContentLoaded", function(event) {
function initPage(){ document.body.style.backgroundColor = utils.getBackgroundColor();
browser.runtime.getBackgroundPage().then(function(page){ app.init();
if(page.app.settings){ dial.init();
app = page.app; });
dial.initUI();
browser.runtime.onMessage.addListener(function(request, sender, sendResponse){ window.addEventListener('resize', function(){
switch(request.command){ if(app && app.settings) dial.updateGridLayout();
case 'SettingsChanged': });
if(app.settings){ window.addEventListener('wheel', function(e){
dial.Head.removeChild(dial.Style); if(app && app.settings){
dial.Body.removeChild(dial.Grid); if(e.deltaY > 0){
dial.initStyles(); if(dial.page < dial.maxpage){
dial.Grid = dial.initGrid('Grid', app.settings.grid, dial.Body); dial.page += 1;
var url = new URL(window.location); dial.populateGrid();
dial.path = url.searchParams.get('path');
if(url.searchParams.get('path')) {
dial.Node = app.getNode(app.settings.grid.node, dial.path + '/');
} else {
dial.Node = app.getNode(app.settings.grid.node, '/');
} }
dial.Title.innerText = dial.Node.title; } else if(e.deltaY < 0){
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); if(dial.page > 1){
dial.page -= 1;
dial.populateGrid();
}
}
}
});
window.addEventListener('keyup', function(e){
switch(e.key){
case 'PageDown':
if(dial.page < dial.maxpage){
dial.page += 1;
dial.populateGrid();
} }
break; break;
case 'GridNodesSaved': case 'PageUp':
if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node); if(dial.page > 1){
break; dial.page -= 1;
case 'GridNodeSaved': dial.populateGrid();
// request.gridNode }
if(app.settings) dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
break; break;
} }
}); });
utils.getBackgroundColor = function(){
return new URL(window.location).searchParams.get('bg');
};
utils.getPath = function(){
var path = new URL(window.location).searchParams.get('path');
if(path) return path + '/';
else return '/';
};
app.init = function(){
app.Messages.getSettings(function(settings){
if(settings && settings.grid) app.Settings._changed(settings);
dial.path = utils.getPath();
app.Messages.getNode(dial.path, app.GridNodes._changed);
app.Messages.init();
});
};
app.Messages = {};
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.init = function(){
browser.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch(request.cmd){
case app.Messages.Commands.settingsChanged:
app.Messages.getSettings(app.Settings._changed);
break;
case app.Messages.Commands.gridNodesLoaded:
if(dial.skipUpdate!=true) app.Messages.getNode(dial.path, app.GridNodes._changed);
break;
}
});
};
app.Messages.getSettings = function(callback){
browser.runtime.getBackgroundPage().then(function(page){
if(page){
if(callback) callback(page.app.settings);
} else { } else {
setTimeout(initPage, 100); browser.runtime.sendMessage({ cmd: app.Messages.Commands.getSettings }).then(callback, callback);
}
}, function(){});
}
initPage();
}
window.onresize = function(){
if(app && app.settings) dial.updateGridLayout(dial.Grid, app.settings.grid, dial.styles.grid);
}
window.onwheel = function(ev){
if(app && app.settings){
if(ev.deltaY > 0){
if(dial.page < dial.maxpage){
dial.page += 1;
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
}
} else if(ev.deltaY < 0){
if(dial.page > 1){
dial.page -= 1;
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
} }
});
};
app.Messages.getNode = function(path, callback){
browser.runtime.getBackgroundPage().then(function(page){
if(page){
if(callback) callback(page.app.GridNodes.getNode(page.app.node, dial.path.substr(1)));
} else {
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getNode, path: path }).then(callback);
} }
});
};
app.Messages.updateNode = function(id, value, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.updateNode, id: id, value: value }).then(callback);
};
app.Messages.setNodeIndex = function(index, newIndex, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.setNodeIndex, path: dial.path, index: index, newIndex: newIndex }).then(callback);
};
app.Messages.createBookmark = function(url, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.createBookmark, path: dial.path, url: url, title: url }).then(callback);
};
app.Messages.createFolder = function(name, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.createFolder, path: dial.path, name: name }).then(callback);
};
app.Messages.deleteNode = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.deleteNode, path: dial.path, id: id }).then(callback);
};
app.Messages.refreshNode = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.refreshNode, path: dial.path, id: id }).then(callback);
} }
app.Messages.capturePage = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.capturePage, path: dial.path, id: id }).then(callback);
} }
dial.initUI = function(){ app.Settings = {};
dial.Head = document.getElementById('head'); app.Settings._changed = function(settings){
dial.Title = document.getElementById('title'); app.settings = settings;
dial.Body = document.getElementById('body');
dial.Body.setAttribute('contextmenu', 'page');
dial.Body.setAttribute('contextmenu', 'page');
dial.initStyles(); dial.initStyles();
dial.initMenus(); dial.initGrid();
dial.Grid = dial.initGrid('Grid', app.settings.grid, dial.Body); };
var url = new URL(window.location);
dial.path = url.searchParams.get('path');
if(url.searchParams.get('path')) {
dial.Node = app.getNode(app.settings.grid.node, dial.path + '/');
} else {
dial.Node = app.getNode(app.settings.grid.node, '/');
}
dial.Title.innerText = dial.Node.title;
dial.populateGrid(dial.Grid, app.settings.grid, dial.Node);
}
app.GridNodes = {};
app.GridNodes.GridNodeType = { // GridNodeType
back: -1,
empty: 0,
folder: 1,
bookmark: 2
}
app.GridNodes._changed = function(node){
app.node = node;
dial.Title.innerText = app.node.title;
dial.populateGrid();
};
dial.init = function(){
dial.initMenus();
dial.Title = document.createElement('title');
document.head.appendChild(dial.Title);
};
dial.initMenus = function(){
document.body.setAttribute('contextmenu', 'page');
dial.PageMenu = document.createElement('menu');
dial.PageMenu.type = 'context';
dial.PageMenu.id = 'page'
dial.PageMenuNew = document.createElement('menu');
dial.PageMenuNew.label = browser.i18n.getMessage("menuNew");
dial.PageMenuCreateBookmark = document.createElement('menuitem');
dial.PageMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.PageMenuCreateBookmark.onclick = dial.createBookmark;
dial.PageMenuCreateFolder = document.createElement('menuitem');
dial.PageMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.PageMenuCreateFolder.onclick = dial.createFolder;
dial.PageMenuSettings = document.createElement('menuitem');
dial.PageMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.PageMenuSettings.onclick = dial.editSettings;
dial.PageMenu.appendChild(dial.PageMenuNew);
dial.PageMenuNew.appendChild(dial.PageMenuCreateBookmark);
dial.PageMenuNew.appendChild(dial.PageMenuCreateFolder);
dial.PageMenu.appendChild(document.createElement('hr'));
dial.PageMenu.appendChild(dial.PageMenuSettings);
document.body.appendChild(dial.PageMenu);
dial.ItemMenu = document.createElement('menu');
dial.ItemMenu.type = 'context';
dial.ItemMenu.id = 'item'
dial.ItemMenuNew = document.createElement('menu');
dial.ItemMenuNew.label = browser.i18n.getMessage("menuNew");
dial.ItemMenuCreateBookmark = document.createElement('menuitem');
dial.ItemMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.ItemMenuCreateBookmark.onclick = dial.createBookmark;
dial.ItemMenuCreateFolder = document.createElement('menuitem');
dial.ItemMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.ItemMenuCreateFolder.onclick = dial.createFolder;
dial.ItemMenuProperties = document.createElement('menuitem');
dial.ItemMenuProperties.label = browser.i18n.getMessage("menuProperties");
dial.ItemMenuProperties.onclick = function(){
dial.editProperties(dial._selectedItem);
};
dial.ItemMenuRefresh = document.createElement('menuitem');
dial.ItemMenuRefresh.label = browser.i18n.getMessage("menuRefreshItem");
dial.ItemMenuRefresh.onclick = function(){
dial.refreshNode(dial._selectedItem);
};
dial.ItemMenuCaptureHere = document.createElement('menuitem');
dial.ItemMenuCaptureHere.label = browser.i18n.getMessage("menuCaptureHere");
dial.ItemMenuCaptureHere.onclick = function(){
dial.captureHere(dial._selectedItem);
};
dial.ItemMenuCapture = document.createElement('menuitem');
dial.ItemMenuCapture.label = browser.i18n.getMessage("menuCapturePage");
dial.ItemMenuCapture.onclick = function(){
dial.capturePage(dial._selectedItem);
};
dial.ItemMenuDelete = document.createElement('menuitem');
dial.ItemMenuDelete.label = browser.i18n.getMessage("menuDeleteItem");
dial.ItemMenuDelete.onclick = dial.deleteNode;
dial.ItemMenuSettings = document.createElement('menuitem');
dial.ItemMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.ItemMenuSettings.onclick = dial.editSettings;
dial.ItemMenu.appendChild(dial.ItemMenuNew);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateBookmark);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateFolder);
dial.ItemMenu.appendChild(document.createElement('hr'));
dial.ItemMenu.appendChild(dial.ItemMenuProperties);
dial.ItemMenu.appendChild(dial.ItemMenuRefresh);
dial.ItemMenu.appendChild(dial.ItemMenuCaptureHere);
dial.ItemMenu.appendChild(dial.ItemMenuCapture);
dial.ItemMenu.appendChild(dial.ItemMenuDelete);
dial.ItemMenu.appendChild(document.createElement('hr'));
dial.ItemMenu.appendChild(dial.ItemMenuSettings);
document.body.appendChild(dial.ItemMenu);
}
dial.initStyles = function(){ dial.initStyles = function(){
var oldStyle = dial.Style;
dial.Style = document.createElement('style'), StyleSheet; dial.Style = document.createElement('style'), StyleSheet;
document.head.appendChild(dial.Style); document.head.appendChild(dial.Style);
dial.styles = {};
dial.styles.html = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('html { height: 100%; }')].style; dial.styles.html = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('html { height: 100%; }')].style;
dial.styles.body = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('body { user-select: none; -moz-user-select: none; display: flex; width: 100%; height: 100%; margin: 0px; padding: 0px; background-color: ' + app.settings.backgroundColor + '; background-image: ' + app.settings.backgroundImage + '; background-repeat: no-repeat; background-size: 100% 100%; }')].style; dial.styles.body = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('body { user-select: none; -moz-user-select: none; display: flex; width: 100%; height: 100%; margin: 0px; padding: 0px; background-color: ' + app.settings.backgroundColor + '; background-image: ' + app.settings.backgroundImage + '; background-repeat: no-repeat; background-size: 100% 100%; }')].style;
dial.styles.grid = {}; dial.styles.grid = {};
@@ -110,105 +273,61 @@ dial.initStyles = function(){
dial.styles.grid.linkFolder = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Folder :first-child { background-image: ' + app.settings.grid.folderIcon + '; background-repeat: no-repeat; background-size: 100% 100%; }')].style; dial.styles.grid.linkFolder = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Folder :first-child { background-image: ' + app.settings.grid.folderIcon + '; background-repeat: no-repeat; background-size: 100% 100%; }')].style;
dial.styles.grid.linkBookmark = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Bookmark :first-child { background-repeat: no-repeat; background-size: 100% 100%; }')].style; dial.styles.grid.linkBookmark = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.Bookmark :first-child { background-repeat: no-repeat; background-size: 100% 100%; }')].style;
dial.styles.grid.linkBookmarkLoading = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.BookmarkLoading :first-child { background-image: url("' + app.settings.grid.cells.loadingIcon + '"); background-repeat: no-repeat; background-position: center center; }')].style; dial.styles.grid.linkBookmarkLoading = dial.Style.sheet.cssRules[dial.Style.sheet.insertRule('.Grid td>a.BookmarkLoading :first-child { background-image: url("' + app.settings.grid.cells.loadingIcon + '"); background-repeat: no-repeat; background-position: center center; }')].style;
} if(oldStyle) document.head.removeChild(oldStyle);
};
dial.initMenus = function(){ dial.initGrid = function(){
dial.PageMenu = document.createElement('menu'); var oldGrid = dial.Grid;
dial.PageMenu.type = 'context'; dial.Grid = document.createElement('table');
dial.PageMenu.id = 'page'
dial.PageMenuNew = document.createElement('menu');
dial.PageMenuNew.label = browser.i18n.getMessage("menuNew");
dial.PageMenuCreateBookmark = document.createElement('menuitem');
dial.PageMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.PageMenuCreateBookmark.onclick = dial.createBookmark;
dial.PageMenuCreateFolder = document.createElement('menuitem');
dial.PageMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.PageMenuCreateFolder.onclick = dial.createFolder;
dial.PageMenuSettings = document.createElement('menuitem');
dial.PageMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.PageMenuSettings.onclick = dial.editSettings;
dial.PageMenu.appendChild(dial.PageMenuNew);
dial.PageMenuNew.appendChild(dial.PageMenuCreateBookmark);
dial.PageMenuNew.appendChild(dial.PageMenuCreateFolder);
dial.PageMenu.appendChild(document.createElement('hr'));
dial.PageMenu.appendChild(dial.PageMenuSettings);
dial.Body.appendChild(dial.PageMenu);
dial.ItemMenu = document.createElement('menu');
dial.ItemMenu.type = 'context';
dial.ItemMenu.id = 'item'
dial.ItemMenuNew = document.createElement('menu');
dial.ItemMenuNew.label = browser.i18n.getMessage("menuNew");
dial.ItemMenuCreateBookmark = document.createElement('menuitem');
dial.ItemMenuCreateBookmark.label = browser.i18n.getMessage("menuNewBookmark");
dial.ItemMenuCreateBookmark.onclick = dial.createBookmark;
dial.ItemMenuCreateFolder = document.createElement('menuitem');
dial.ItemMenuCreateFolder.label = browser.i18n.getMessage("menuNewFolder");
dial.ItemMenuCreateFolder.onclick = dial.createFolder;
/*
dial.ItemMenuEdit = document.createElement('menuitem');
dial.ItemMenuEdit.label = 'Edit';
//dial.ItemMenuEdit.onclick = dial.test;
*/
dial.ItemMenuRefresh = document.createElement('menuitem');
dial.ItemMenuRefresh.label = browser.i18n.getMessage("menuRefreshItem");
dial.ItemMenuRefresh.onclick = dial.refreshNode;
dial.ItemMenuCapture = document.createElement('menuitem');
dial.ItemMenuCapture.label = browser.i18n.getMessage("menuCapturePage");
dial.ItemMenuCapture.onclick = dial.capturePage;
dial.ItemMenuDelete = document.createElement('menuitem');
dial.ItemMenuDelete.label = browser.i18n.getMessage("menuDeleteItem");
dial.ItemMenuDelete.onclick = dial.deleteNode;
dial.ItemMenuSettings = document.createElement('menuitem');
dial.ItemMenuSettings.label = browser.i18n.getMessage("menuSettings");
dial.ItemMenuSettings.onclick = dial.editSettings;
dial.ItemMenu.appendChild(dial.ItemMenuNew);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateBookmark);
dial.ItemMenuNew.appendChild(dial.ItemMenuCreateFolder);
dial.ItemMenu.appendChild(document.createElement('hr'));
//dial.ItemMenu.appendChild(dial.ItemMenuEdit);
dial.ItemMenu.appendChild(dial.ItemMenuRefresh);
dial.ItemMenu.appendChild(dial.ItemMenuCapture);
dial.ItemMenu.appendChild(dial.ItemMenuDelete);
dial.ItemMenu.appendChild(document.createElement('hr'));
dial.ItemMenu.appendChild(dial.ItemMenuSettings);
dial.Body.appendChild(dial.ItemMenu);
}
dial.initGrid = function(name, settings, container){
var grid = document.createElement('table'); var grid = document.createElement('table');
grid.className = name; dial.Grid.className = 'Grid';
grid.getLink = function(index){ dial.Grid.getLink = function(index){
var num_columns = grid.rows[0].cells.length; var num_columns = dial.Grid.rows[0].cells.length;
return grid.rows[Math.floor(index/num_columns)].cells[index % num_columns].childNodes[0]; return dial.Grid.rows[Math.floor(index/num_columns)].cells[index % num_columns].childNodes[0];
} }
for(var i=0; i<settings.rows; i++){ for(var i=0; i<app.settings.grid.rows; i++){
var row = grid.insertRow(); var row = dial.Grid.insertRow();
for(var j=0; j<settings.columns; j++){ for(var j=0; j<app.settings.grid.columns; j++){
var cell = row.insertCell(); var cell = row.insertCell();
var link = document.createElement('a'); var link = document.createElement('a');
cell.setAttribute('gridindex', (i * settings.columns + j)); cell.setAttribute('gridindex', (i * app.settings.grid.columns + j));
cell.appendChild(link); cell.appendChild(link);
link.className = 'Empty';
link.appendChild(document.createElement('div')); link.appendChild(document.createElement('div'));
link.appendChild(document.createElement('div')); link.appendChild(document.createElement('div'));
link.onmousedown = function(){ dial._selectedItem = this; }; link.onmousedown = function(){
dial._selectedItem = this;
if(dial._selectedItem.Node){
switch(dial._selectedItem.Node.type){
case app.GridNodes.GridNodeType.folder:
dial.ItemMenuCaptureHere.hidden = true;
break;
case app.GridNodes.GridNodeType.bookmark:
dial.ItemMenuCaptureHere.hidden = false;
break;
}
}
};
function dragstart_handler(ev) { function dragstart_handler(ev) {
if(!ev.target.Node){
ev.preventDefault();
return;
}
var index = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.parentElement.getAttribute('gridindex')); var index = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.parentElement.getAttribute('gridindex'));
if(settings.backNode && dial.path) index -= dial.page; if(app.settings.grid.backNode && dial.path != '/') index -= dial.page;
console.log(index);
ev.dataTransfer.setData("text/plain", index); ev.dataTransfer.setData("text/plain", index);
} }
function dragover_handler(ev) { function dragover_handler(ev) {
ev.preventDefault(); ev.preventDefault();
ev.dataTransfer.dropEffect = "move" if(app.settings.grid.backNode && dial.path != '/'){
var gridIndex = 0;
if(ev.target.tagName == 'DIV') gridIndex = +(ev.target.parentElement.parentElement.getAttribute('gridindex'));
else gridIndex = +(ev.target.getAttribute('gridindex'));
if(gridIndex==0) ev.dataTransfer.dropEffect = "none";
else ev.dataTransfer.dropEffect = "move";
} else {
ev.dataTransfer.dropEffect = "move";
}
} }
function drop_handler(ev) { function drop_handler(ev) {
ev.preventDefault(); ev.preventDefault();
@@ -220,42 +339,40 @@ dial.initGrid = function(name, settings, container){
} else{ } else{
EndIndex = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.getAttribute('gridindex')); EndIndex = (dial.page - 1) * (app.settings.grid.rows * app.settings.grid.columns) + +(ev.target.getAttribute('gridindex'));
} }
if(settings.backNode && dial.path) EndIndex -= dial.page; if(app.settings.grid.backNode && dial.path != '/') EndIndex -= dial.page;
app.setNodeIndex(dial.Node, StartIndex, EndIndex); if(StartIndex != EndIndex) app.Messages.setNodeIndex(StartIndex, EndIndex);
} }
link.draggable = true; link.draggable = true;
link.ondragstart = dragstart_handler; link.ondragstart = dragstart_handler;
cell.ondragover = dragover_handler; cell.ondragover = dragover_handler;
cell.ondrop = drop_handler; cell.ondrop = drop_handler;
} }
} }
container.appendChild(grid); document.body.appendChild(dial.Grid);
dial.updateGridLayout(grid, settings, dial.styles.grid); dial.updateGridLayout();
return grid; if(oldGrid) document.body.removeChild(oldGrid);
} return dial.Grid;
};
dial.updateGridLayout = function(){
var fullWidth = dial.Grid.parentElement.offsetWidth - 2 * app.settings.grid.margin;
var fullHeight = dial.Grid.parentElement.offsetHeight - 2 * app.settings.grid.margin;
var linkWidth = fullWidth / app.settings.grid.columns;
var linkHeight = fullHeight / app.settings.grid.rows;
if(linkWidth <= linkHeight * 4 / 3) linkHeight = linkWidth / 4 * 3;
else linkWidth = linkHeight / 3 * 4;
dial.updateGridLayout = function(grid, settings, styles){ dial.styles.grid.cell.width = linkWidth.toString() + 'px';
var fullWidth = grid.parentElement.offsetWidth - 2 * settings.margin; dial.styles.grid.cell.height = linkHeight.toString() + 'px';
var fullHeight = grid.parentElement.offsetHeight - 2 * settings.margin;
var linkWidth = fullWidth / settings.columns;
var linkHeight = fullHeight / settings.rows;
if(linkWidth <= linkHeight * settings.cells.ratioX / settings.cells.ratioY) linkHeight = linkWidth / settings.cells.ratioX * settings.cells.ratioY;
else linkWidth = linkHeight / settings.cells.ratioY * settings.cells.ratioX;
styles.cell.width = linkWidth.toString() + 'px'; linkWidth = linkWidth - 2 * (app.settings.grid.cells.margin + 1);
styles.cell.height = linkHeight.toString() + 'px'; linkHeight = linkHeight - 2 * (app.settings.grid.cells.margin + 1);
linkWidth = linkWidth - 2 * (settings.cells.margin + 1); dial.styles.grid.link.width = linkWidth.toString() + 'px';
linkHeight = linkHeight - 2 * (settings.cells.margin + 1); dial.styles.grid.link.height = linkHeight.toString() + 'px';
if(app.settings.grid.cells.title) dial.styles.grid.linkPanel.height = (linkHeight - app.settings.grid.cells.titleHeight - 1).toString() + 'px';
styles.link.width = linkWidth.toString() + 'px'; else dial.styles.grid.linkPanel.height = linkHeight.toString() + 'px';
styles.link.height = linkHeight.toString() + 'px'; };
if(settings.cells.title) styles.linkPanel.height = (linkHeight - settings.cells.titleHeight - 1).toString() + 'px'; dial.populateGrid = function(){
else styles.linkPanel.height = linkHeight.toString() + 'px';
}
dial.populateGrid = function(grid, settings, node){
populateEmpty = function(link){ populateEmpty = function(link){
link.Node = null; link.Node = null;
link.className = 'Empty'; link.className = 'Empty';
@@ -276,10 +393,13 @@ dial.populateGrid = function(grid, settings, node){
populateFolder = function(link, node){ populateFolder = function(link, node){
link.Node = node; link.Node = node;
link.className = 'Folder'; link.className = 'Folder';
link.childNodes[0].style.backgroundImage = ''; if(node.image){
if(node.image.indexOf('url(')>=0) link.childNodes[0].style.backgroundImage = node.image;
else link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')';
} else link.childNodes[0].style.backgroundImage = '';
link.childNodes[1].innerText = node.title; link.childNodes[1].innerText = node.title;
if(dial.path) link.href = '?path=' + dial.path + '/' + node.title; if(dial.path) link.href = '?' + 'bg=' + encodeURIComponent(app.settings.backgroundColor) + '&path=' + encodeURIComponent(dial.path + node.title);
else link.href = '?path=' + node.title; else link.href = '?' + 'bg=' + encodeURIComponent(app.settings.backgroundColor) + '&path=' + encodeURIComponent(node.title);
link.onclick = null; link.onclick = null;
link.setAttribute('contextmenu', 'item'); link.setAttribute('contextmenu', 'item');
} }
@@ -287,15 +407,12 @@ dial.populateGrid = function(grid, settings, node){
link.Node = node; link.Node = node;
if(node.image){ if(node.image){
link.className = 'Bookmark'; link.className = 'Bookmark';
link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')'; if(node.image.indexOf('url(')>=0) link.childNodes[0].style.backgroundImage = node.image;
else link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')';
} else { } else {
link.className = 'BookmarkLoading'; link.className = 'BookmarkLoading';
link.childNodes[0].style.backgroundImage = ''; link.childNodes[0].style.backgroundImage = '';
app.refreshNode(node, function(){ dial.refreshNode(link);
link.className = 'Bookmark';
link.childNodes[0].style.backgroundImage = 'url(' + node.image + ')';
link.childNodes[1].innerText = node.title;
});
} }
link.childNodes[1].innerText = node.title; link.childNodes[1].innerText = node.title;
link.href = node.url; link.href = node.url;
@@ -305,69 +422,141 @@ dial.populateGrid = function(grid, settings, node){
var iBase = 0; var iBase = 0;
var linkItem = 0; var linkItem = 0;
var allCells = settings.rows * settings.columns; var allCells = app.settings.grid.rows * app.settings.grid.columns;
var maxCells = allCells; var maxCells = allCells;
if(settings.backNode && dial.path){ if(app.settings.grid.backNode && dial.path != '/'){
populateBack(grid.getLink(linkItem)); populateBack(dial.Grid.getLink(linkItem));
linkItem++; linkItem++;
maxCells -= 1; maxCells -= 1;
} }
dial.maxpage = Math.floor(node.children.length / maxCells); dial.maxpage = Math.floor(app.node.children.length / maxCells);
if(dial.maxpage != node.children.length / maxCells) dial.maxpage += 1; if(dial.maxpage != app.node.children.length / maxCells) dial.maxpage += 1;
if(dial.page > dial.maxpage) dial.page = dial.maxpage; if(dial.page > dial.maxpage) dial.page = dial.maxpage;
if(dial.page > 1) iBase = (dial.page -1) * maxCells; if(dial.page > 1) iBase = (dial.page -1) * maxCells;
for(var i = iBase; i<node.children.length && i<maxCells + iBase; i++) { for(var i = iBase; i<app.node.children.length && i<maxCells + iBase; i++) {
switch(node.children[i].type){ switch(app.node.children[i].type){
case app.GridNodeType.empty: case app.GridNodes.GridNodeType.empty:
populateEmpty(grid.getLink(linkItem)); populateEmpty(dial.Grid.getLink(linkItem));
break; break;
case app.GridNodeType.folder: case app.GridNodes.GridNodeType.folder:
populateFolder(grid.getLink(linkItem), node.children[i]); populateFolder(dial.Grid.getLink(linkItem), app.node.children[i]);
break; break;
case app.GridNodeType.bookmark: case app.GridNodes.GridNodeType.bookmark:
populateBookmark(grid.getLink(linkItem), node.children[i]); populateBookmark(dial.Grid.getLink(linkItem), app.node.children[i]);
break; break;
} }
linkItem++; linkItem++;
} }
while(linkItem<allCells){ while(linkItem<allCells){
populateEmpty(grid.getLink(linkItem)); populateEmpty(dial.Grid.getLink(linkItem));
linkItem++; linkItem++;
} }
} };
dial.createBookmark = function(){ dial.createBookmark = function(){
var url = prompt(browser.i18n.getMessage("AddBookmarkPrompt"), 'https://'); var url = prompt(browser.i18n.getMessage("AddBookmarkPrompt"), 'https://');
if(url) app.createBookmark(dial.Node, url); if(url) app.Messages.createBookmark(url);
}; };
dial.createFolder = function(){ dial.createFolder = function(){
var name = prompt(browser.i18n.getMessage("AddFolderPrompt"), 'New Folder'); var name = prompt(browser.i18n.getMessage("AddFolderPrompt"), 'New Folder');
if(name) app.createFolder(dial.Node, name); if(name) app.Messages.createFolder(name);
}; };
dial.refreshNode = function(){
if(dial._selectedItem.Node.type == app.GridNodeType.bookmark){
var link = dial._selectedItem;
link.className = 'BookmarkLoading';
link.childNodes[0].style.backgroundImage = '';
app.refreshNode(link.Node, function(){
link.className = 'Bookmark';
link.childNodes[0].style.backgroundImage = 'url(' + link.Node.image + ')';
link.childNodes[1].innerText = link.Node.title;
});
}
}
dial.deleteNode = function(){ dial.deleteNode = function(){
if(confirm(browser.i18n.getMessage("deleteItemConfimation", dial._selectedItem.Node.title))) if(confirm(browser.i18n.getMessage("deleteItemConfimation", dial._selectedItem.Node.title)))
app.deleteNode(dial.Node, dial._selectedItem.Node.id); app.Messages.deleteNode(dial._selectedItem.Node.id);
}
dial.refreshNode = function(selectedItem){
selectedItem.className = 'BookmarkLoading';
selectedItem.childNodes[0].style.backgroundImage = app.settings.grid.loadingIcon;
app.Messages.refreshNode(selectedItem.Node.id);
}
dial.captureHere = function(selectedItem){
function headersReceived(e){
for (let i = e.responseHeaders.length - 1; i >= 0; i--) {
switch(e.responseHeaders[i].name.toLowerCase()){
case 'x-frame-options':
case 'frame-options':
case 'content-security-policy':
e.responseHeaders.splice(i, 1);
break;
}
}
return { responseHeaders: e.responseHeaders };
};
function pageLoaded(){
if(!iframe) return;
function clean(){
if(!iframe) return;
selectedItem.children[0].removeChild(iframe);
dial.capture -= 1;
if(dial.capture == 0){
browser.webRequest.onHeadersReceived.removeListener(headersReceived);
browser.tabs.update(tab.id, {muted: false}).then();
}
iframe = null;
}
setTimeout(function(){
browser.tabs.captureVisibleTab().then(function(img){
var imgObj = new Image;
imgObj.src = img;
var canvas = document.createElement('canvas');
canvas.style.width = rect.width.toString() + 'px';
canvas.style.height = rect.height.toString() + 'px';
canvas.width = rect.width;
canvas.height = rect.height;
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, rect.width, rect.height);
ctx.save();
setTimeout(function(){
ctx.drawImage(imgObj, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
ctx.restore();
img = canvas.toDataURL();
selectedItem.children[0].style.backgroundImage = 'url(' + img + ')';
clean();
app.Messages.updateNode(selectedItem.Node.id, { image: img }, function(){
setTimeout(function(){
if(dial.capture == 0) dial.skipUpdate = false;
}, 500);
});
}, 500);
}, clean);
}, 3000);
};
var tab = null;
var previewWidth = 1200; // Need to be linked to settings
var previewHeight = 710; // Need to be linked to settings
var iframe = document.createElement('iframe');
var rect = selectedItem.children[0].getBoundingClientRect();
browser.tabs.getCurrent().then(function(currentTab){
tab = currentTab;
var ratioX = previewWidth / selectedItem.children[0].offsetWidth;
var ratioY = previewHeight / selectedItem.children[0].offsetHeight;
iframe.style.width = ratioX * selectedItem.children[0].offsetWidth + 'px';
iframe.style.height = ratioY * selectedItem.children[0].offsetHeight + 'px';
iframe.style.position = 'absolute';
iframe.style.MozTransform = 'scale(' + (1/ratioX) + ', ' + (1/ratioY) + ')';
iframe.style.MozTransformOrigin = 'top left';
iframe.sandbox = 'allow-scripts allow-same-origin';
iframe.onload = function(){ pageLoaded(); }
dial.capture += 1;
if(dial.capture == 1){
dial.skipUpdate = true;
browser.webRequest.onHeadersReceived.addListener(headersReceived, { urls:['*://*/*'], types:['sub_frame'] }, ['blocking', 'responseHeaders']);
browser.tabs.update(tab.id, {muted: true}).then();
}
iframe.src = selectedItem.Node.url;
selectedItem.children[0].appendChild(iframe);
//setTimeout(function(){ pageLoaded(); }, 6000);
});
}
dial.capturePage = function(selectedItem){
selectedItem.className = 'BookmarkLoading';
selectedItem.childNodes[0].style.backgroundImage = app.settings.grid.loadingIcon;
app.Messages.capturePage(selectedItem.Node.id);
} }
dial.capturePage = function(){
if(dial._selectedItem.Node.type == app.GridNodeType.bookmark)
app.capturePage(dial._selectedItem.Node);
}
@@ -399,26 +588,26 @@ dial.PopupPanel = function(width, height, modal){ // PopupPanel Object
this._contextMenuHandler = function(e){ e.preventDefault(); } this._contextMenuHandler = function(e){ e.preventDefault(); }
this.popup = function(){ this.popup = function(){
window.addEventListener('contextmenu', this._contextMenuHandler, false); window.addEventListener('contextmenu', this._contextMenuHandler, false);
dial.Body.appendChild(this.modal); document.body.appendChild(this.modal);
dial.Body.appendChild(this.panelContainer); document.body.appendChild(this.panelContainer);
} }
this.close = function(){ this.close = function(){
dial.Body.removeChild(this.modal); document.body.removeChild(this.modal);
dial.Body.removeChild(this.panelContainer); document.body.removeChild(this.panelContainer);
window.removeEventListener('contextmenu', this._contextMenuHandler, false); window.removeEventListener('contextmenu', this._contextMenuHandler, false);
} }
} else { } else {
this.popup = function(){ this.popup = function(){
dial.Body.appendChild(this.panelContainer); document.body.appendChild(this.panelContainer);
} }
this.close = function(){ this.close = function(){
dialBody.removeChild(this.panelContainer); document.body.removeChild(this.panelContainer);
} }
} }
} }
dial.editSettings = function(){ dial.editSettings = function(){
var popup = new dial.PopupPanel(500, 420, true); var popup = new dial.PopupPanel(500, 440, true);
var iframe = document.createElement('iframe'); var iframe = document.createElement('iframe');
iframe.style.width = '100%'; iframe.style.width = '100%';
iframe.style.height = '100%'; iframe.style.height = '100%';
@@ -430,4 +619,21 @@ dial.editSettings = function(){
iframe.src = '/html/settings.html'; iframe.src = '/html/settings.html';
iframe.popup = popup; iframe.popup = popup;
popup.popup(); popup.popup();
iframe.focus();
}
dial.editProperties = function(selectedItem){
var popup = new dial.PopupPanel(500, 420, true);
var iframe = document.createElement('iframe');
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.backgroundColor = 'transparent';
iframe.style.border = '0px none transparent';
iframe.style.padding = '0px';
iframe.style.overflow = 'hidden';
popup.frame.appendChild(iframe);
iframe.src = '/html/properties.html?id=' + selectedItem.Node.id;
iframe.popup = popup;
popup.popup();
iframe.focus();
} }

161
src/js/properties.js Normal file
View File

@@ -0,0 +1,161 @@
var app = {};
var Image = null;
document.addEventListener("DOMContentLoaded", function(event) {
app.init();
});
app.init = function(){
document.addEventListener('keyup', function(e){
switch(e.key){
case 'Escape':
window.frameElement.popup.close();
break;
}
});
app.Messages.getSettings(function(settings){
app.settings = settings;
app.Messages.getNodeByID(new URL(window.location).searchParams.get('id'), function(node){
app.node = node;
Title.value = node.title;
ImagePreview.style.backgroundRepeat = 'no-repeat';
ImagePreview.style.backgroundSize = '100% 100%';
switch(node.type){
case app.GridNodes.GridNodeType.folder:
TitleLocked.parentNode.style.display = 'none';
Url.parentNode.parentNode.style.display = 'none';
if(node.image){
if(node.image.indexOf('url(')>=0) Image = node.image;
else Image = 'url(' + node.image + ')';
} else Image = null;
if(Image==null) ImagePreview.style.backgroundImage = app.settings.grid.folderIcon;
else ImagePreview.style.backgroundImage = Image;
break;
case app.GridNodes.GridNodeType.bookmark:
TitleLocked.checked = (node.titleLocked==true);
ImageDefault.style.display = 'none';
Url.value = node.url;
if(node.image.indexOf('url(')>=0) Image = node.image;
else Image = 'url(' + node.image + ')';
ImagePreview.style.backgroundImage = Image;
break;
}
ImageReset.onclick = function(){
switch(node.type){
case app.GridNodes.GridNodeType.folder:
if(node.image){
Image = node.image;
ImagePreview.style.backgroundImage = 'url(' + Image + ')';
} else {
Image = null;
ImagePreview.style.backgroundImage = app.settings.grid.folderIcon;
}
break;
case app.GridNodes.GridNodeType.bookmark:
Image = node.image;
ImagePreview.style.backgroundImage = 'url(' + Image + ')';
break;
}
};
ImageDefault.onclick = function(){
switch(node.type){
case app.GridNodes.GridNodeType.folder:
Image = null;
ImagePreview.style.backgroundImage = app.settings.grid.folderIcon;
break;
case app.GridNodes.GridNodeType.bookmark:
break;
}
};
ImageFile.onclick = function(){
this.value = null;
}
ImageFile.onchange = function(){
var fileReader = new FileReader();
fileReader.onload = function(e){
Image = e.target.result;
ImageFile.value = null;
ImagePreview.style.backgroundImage = 'url(' + Image + ')';
}
fileReader.readAsDataURL(ImageFile.files[0]);
}
});
});
BtnOk.onclick = function(){
BtnApply.onclick();
window.frameElement.popup.close();
}
BtnApply.onclick = function(){
switch(app.node.type){
case app.GridNodes.GridNodeType.folder:
app.Messages.updateNode(app.node.id, { title: Title.value, image: Image })
break;
case app.GridNodes.GridNodeType.bookmark:
app.Messages.updateNode(app.node.id, { title: Title.value, titleLocked: TitleLocked.checked, url: Url.value, image: Image })
break;
}
}
BtnCancel.onclick = function(){
window.frameElement.popup.close();
}
var tabButtons = Tabs.children[0].children[0].children[0];
for(var i=0; i<tabButtons.children.length-1; i++){
tabButtons.children[i].index = i;
tabButtons.children[i].onclick = function(){
for(var j=0; j<tabButtons.children.length-1; j++){
if(j==this.index){
tabButtons.children[j].className = 'TabButtonActive';
Tabs.children[1].children[j].className = '';
} else {
tabButtons.children[j].className = 'TabButton';
Tabs.children[1].children[j].className = 'hidden';
}
}
}
}
};
app.Messages = {};
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.getSettings = function(callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getSettings }).then(callback);
};
app.Messages.getNodeByID = function(id, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getNodeByID, id: id }).then(callback);
};
app.Messages.updateNode = function(id, value, callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.updateNode, id: id, value: value }).then(callback);
};
app.GridNodes = {};
app.GridNodes.GridNodeType = { // GridNodeType
back: -1,
empty: 0,
folder: 1,
bookmark: 2
}

View File

@@ -1,16 +1,31 @@
var app = {};
var BackgroundImage = null; var BackgroundImage = null;
var GridBackImage = null; var GridBackImage = null;
var GridFolderImage = null; var GridFolderImage = null;
window.onload = function(){ document.addEventListener("DOMContentLoaded", function(event) {
browser.runtime.getBackgroundPage().then(function(page){ app.init();
app = page.app; });
app.init = function(){
document.addEventListener('keyup', function(e){
switch(e.key){
case 'Escape':
window.frameElement.popup.close();
break;
}
});
app.Messages.getSettings(function(settings){
app.settings = settings;
BackgroundColor.value = app.settings.backgroundColor; BackgroundColor.value = app.settings.backgroundColor;
BackgroundImage = app.settings.backgroundImage; BackgroundImage = app.settings.backgroundImage;
BackgroundPreview.style.backgroundColor = app.settings.backgroundColor; BackgroundPreview.style.backgroundColor = app.settings.backgroundColor;
BackgroundPreview.style.backgroundImage = app.settings.backgroundImage; BackgroundPreview.style.backgroundImage = app.settings.backgroundImage;
BackgroundPreview.style.backgroundRepeat = 'no-repeat'; BackgroundPreview.style.backgroundRepeat = 'no-repeat';
BackgroundPreview.style.backgroundSize = '100% 100%'; BackgroundPreview.style.backgroundSize = '100% 100%';
GridRoot.value = app.settings.grid.root;
GridRows.value = app.settings.grid.rows; GridRows.value = app.settings.grid.rows;
GridMargins.value = app.settings.grid.margin; GridMargins.value = app.settings.grid.margin;
GridColumns.value = app.settings.grid.columns; GridColumns.value = app.settings.grid.columns;
@@ -77,7 +92,8 @@ window.onload = function(){
else app.settings.grid.cells.titleBackgroundColor = GridCellsTitleBackgroundColor.value; else app.settings.grid.cells.titleBackgroundColor = GridCellsTitleBackgroundColor.value;
if(GridCellsTitleBackgroundTransparentHover.checked == true) app.settings.grid.cells.titleBackgroundColorHover = null; if(GridCellsTitleBackgroundTransparentHover.checked == true) app.settings.grid.cells.titleBackgroundColorHover = null;
else app.settings.grid.cells.titleBackgroundColorHover = GridCellsTitleBackgroundColorHover.value; else app.settings.grid.cells.titleBackgroundColorHover = GridCellsTitleBackgroundColorHover.value;
app.saveSettings(); app.settings.grid.root = GridRoot.value;
browser.runtime.sendMessage( { cmd: app.Messages.Commands.setSettings, settings: app.settings } );
} }
BtnCancel.onclick = function(){ BtnCancel.onclick = function(){
window.frameElement.popup.close(); window.frameElement.popup.close();
@@ -152,5 +168,28 @@ window.onload = function(){
} }
fileReader.readAsDataURL(GridFolderImageFile.files[0]); fileReader.readAsDataURL(GridFolderImageFile.files[0]);
} }
};
app.Messages = {};
app.Messages.Commands = {
getSettings: 0,
setSettings: 1,
getNode: 2,
getNodeByID: 3,
updateNode: 4,
setNodeIndex: 5,
createBookmark: 6,
createFolder: 7,
deleteNode: 8,
refreshNode: 9,
capturePage: 10,
settingsChanged: 100,
gridNodesLoaded: 101
};
app.Messages.getSettings = function(callback){
browser.runtime.sendMessage({ cmd: app.Messages.Commands.getSettings }).then(callback);
};
}

View File

@@ -2,7 +2,7 @@
"manifest_version": 2, "manifest_version": 2,
"name": "Quick Dial", "name": "Quick Dial",
"version": "0.0.4", "version": "0.1.6",
"author": "MatMoul", "author": "MatMoul",
"homepage_url": "https://github.com/MatMoul/quickdial-webext", "homepage_url": "https://github.com/MatMoul/quickdial-webext",
"developer": { "developer": {
@@ -21,6 +21,8 @@
"bookmarks", "bookmarks",
"contextMenus", "contextMenus",
"tabs", "tabs",
"webRequest",
"webRequestBlocking",
"<all_urls>" "<all_urls>"
], ],
@@ -28,6 +30,13 @@
"scripts": ["js/background.js"] "scripts": ["js/background.js"]
}, },
"browser_action": {
"default_icon": {
"24": "img/24.png",
"32": "img/32.png"
}
},
"chrome_url_overrides" : { "chrome_url_overrides" : {
"newtab": "dial" "newtab": "dial"
}, },