Skip to content

Commit

Permalink
Add notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
gyng committed Oct 17, 2017
1 parent d79a76f commit 4f1fa95
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 56 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"SPECIAL_DIRS": true,
"MEDIA_TYPES": true,
"replaceSpecialDirs": true,
"downloadInto": true
"downloadInto": true,
"addNotifications": true
}
}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# 1.3.0

* Added notifications for download success/failures (disabled by default)
* Added `notifications` permission

# 1.2.0

* Added option to show file dialog on save
Expand Down
4 changes: 3 additions & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_extensionName__",
"description": "__MSG_extensionDescription__",
"version": "1.2.0",
"version": "1.3.0",
"default_locale": "en",

"applications": {
Expand All @@ -22,6 +22,7 @@
"scripts": [
"src/chrome-polyfill.js",
"src/constants.js",
"src/notification.js",
"src/download.js",
"src/index.js"
]
Expand All @@ -32,6 +33,7 @@
"activeTab",
"contextMenus",
"downloads",
"notifications",
"storage"
],

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "save-in",
"version": "1.2.0",
"version": "1.3.0",
"license": "MIT",
"scripts": {
"build": "env -u WEB_EXT_API_KEY -u WEB_EXT_API_SECRET web-ext build --overwrite-dest -i test docs yarn.lock",
Expand Down
107 changes: 62 additions & 45 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
const options = {
links: true,
prompt: false,
paths: "."
paths: ".",
notifyOnSuccess: false,
notifyOnFailure: false
};

const setOption = (name, value) => {
Expand All @@ -11,58 +13,73 @@ const setOption = (name, value) => {
}
};

browser.storage.local.get(["links", "paths", "prompt"]).then(item => {
setOption("links", item.links);
setOption("paths", item.paths);
setOption("prompt", item.prompt);
browser.storage.local
.get(["links", "paths", "prompt", "notifyOnSuccess", "notifyOnFailure"])
.then(item => {
// Options page has a different scope
setOption("links", item.links);
setOption("paths", item.paths);
setOption("prompt", item.prompt);
setOption("notifyOnSuccess", item.notifyOnSuccess);
setOption("notifyOnFailure", item.notifyOnFailure);

const pathsArray = options.paths.split("\n");
const media = options.links ? MEDIA_TYPES.concat(["link"]) : MEDIA_TYPES;
let separatorCounter = 0;
addNotifications({
notifyOnSuccess: options.notifyOnSuccess,
notifyOnFailure: options.notifyOnFailure
});

pathsArray.forEach(dir => {
if (!dir || dir === ".." || dir.startsWith("../") || dir.startsWith("/")) {
return;
}
const pathsArray = options.paths.split("\n");
const media = options.links ? MEDIA_TYPES.concat(["link"]) : MEDIA_TYPES;
let separatorCounter = 0;

switch (dir) {
case SPECIAL_DIRS.SEPARATOR:
browser.contextMenus.create({
id: `separator-${separatorCounter}`,
type: "separator",
contexts: media
});
pathsArray.forEach(dir => {
if (
!dir ||
dir === ".." ||
dir.startsWith("../") ||
dir.startsWith("/")
) {
return;
}

separatorCounter += 1;
break;
default:
browser.contextMenus.create({
id: `save-in-${dir}`,
title: dir,
contexts: media
});
break;
}
});
switch (dir) {
case SPECIAL_DIRS.SEPARATOR:
browser.contextMenus.create({
id: `separator-${separatorCounter}`,
type: "separator",
contexts: media
});

browser.contextMenus.create({
id: `separator-${separatorCounter}`,
type: "separator",
contexts: media
});
separatorCounter += 1;
break;
default:
browser.contextMenus.create({
id: `save-in-${dir}`,
title: dir,
contexts: media
});
break;
}
});

browser.contextMenus.create({
id: "show-default-folder",
title: browser.i18n.getMessage("contextMenuShowDefaultFolder"),
contexts: media
});
browser.contextMenus.create({
id: `separator-${separatorCounter}`,
type: "separator",
contexts: media
});

browser.contextMenus.create({
id: "options",
title: browser.i18n.getMessage("contextMenuItemOptions"),
contexts: media
browser.contextMenus.create({
id: "show-default-folder",
title: browser.i18n.getMessage("contextMenuShowDefaultFolder"),
contexts: media
});

browser.contextMenus.create({
id: "options",
title: browser.i18n.getMessage("contextMenuItemOptions"),
contexts: media
});
});
});

browser.contextMenus.onClicked.addListener(info => {
const matchSave = info.menuItemId.match(/save-in-(.*)/);
Expand Down
53 changes: 53 additions & 0 deletions src/notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/notifications

const downloadsList = {}; // global

const addNotifications = options => {
const notifyOnSuccess = options && options.notifyOnSuccess;
const notifyOnFailure = options && options.notifyOnFailure;

browser.downloads.onCreated.addListener(item => {
downloadsList[item.id] = item;
});

browser.notifications.onClicked.addListener(notId => {
// notification ID should be set to download ID on download creation
browser.downloads.show(Number(notId));
});

browser.downloads.onChanged.addListener(downloadDelta => {
const item = downloadsList[downloadDelta.id];
const slashIdx = item.filename && item.filename.lastIndexOf("/");
const filename = item.filename && item.filename.substring(slashIdx + 1);

if (
notifyOnFailure &&
(!downloadDelta ||
!downloadDelta.state ||
downloadDelta.state.current === "interrupted")
) {
browser.notifications.create(String(downloadDelta.id), {
type: "basic",
title: "Failed to save",
message: `${filename}`
});
} else if (
notifyOnSuccess &&
downloadDelta.state.current === "complete" &&
downloadDelta.state.previous === "in_progress"
) {
browser.notifications.create(String(downloadDelta.id), {
type: "basic",
title: "Saved",
message: `${filename}`
});
}
});
};

// Export for testing
if (typeof module !== "undefined") {
module.exports = {
addNotifications
};
}
11 changes: 11 additions & 0 deletions src/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ <h4>More options</h4>
Open a save file dialog when saving
</label>

<h4>Notifications</h4>
<label>
<input type="checkbox" id="notifyOnSuccess" />
Show notification on successful download
</label>

<label>
<input type="checkbox" id="notifyOnFailure" />
Show notification on failed download
</label>

<button type="submit">Save</button>
</form>

Expand Down
32 changes: 24 additions & 8 deletions src/options/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,37 @@ const saveOptions = e => {
browser.storage.local.set({
links: document.querySelector("#links").checked,
paths: document.querySelector("#paths").value.trim(),
prompt: document.querySelector("#prompt").checked
prompt: document.querySelector("#prompt").checked,
notifyOnSuccess: document.querySelector("#notifyOnSuccess").checked,
notifyOnFailure: document.querySelector("#notifyOnFailure").checked
});

browser.contextMenus.removeAll();
browser.runtime.reload();
};

const restoreOptions = () => {
browser.storage.local.get(["links", "paths", "prompt"]).then(result => {
document.querySelector("#links").checked =
typeof result.links === "undefined" ? true : result.links;
document.querySelector("#prompt").checked =
typeof result.prompt === "undefined" ? false : result.prompt;
document.querySelector("#paths").value = result.paths || ".";
});
browser.storage.local
.get(["links", "paths", "prompt", "notifyOnSuccess", "notifyOnFailure"])
.then(result => {
document.querySelector("#links").checked =
typeof result.links === "undefined" ? true : result.links;

document.querySelector("#prompt").checked =
typeof result.prompt === "undefined" ? false : result.prompt;

document.querySelector("#paths").value = result.paths || ".";

document.querySelector("#notifyOnSuccess").checked =
typeof result.notifyOnSuccess === "undefined"
? false
: result.notifyOnSuccess;

document.querySelector("#notifyOnFailure").checked =
typeof result.notifyOnFailure === "undefined"
? false
: result.notifyOnFailure;
});
};

const addHelp = el => {
Expand Down

0 comments on commit 4f1fa95

Please sign in to comment.