From 75a23e8d5660fec612ab75a185598f9850a49e8d Mon Sep 17 00:00:00 2001 From: Alexis Degrugillier Date: Wed, 30 May 2018 22:28:33 +0200 Subject: [PATCH] Copy to clipboard is now available See #9 --- _locales/en/messages.json | 21 ++++++++-------- _locales/fr/messages.json | 21 ++++++++-------- background.js | 24 +++++++++++++++++- manifest.json | 3 ++- package.json | 2 +- popup/load.content.css | 7 +++--- popup/load.content.html | 22 ++++++++++------ popup/load.content.js | 53 ++++++++++++++++++++++++++++----------- 8 files changed, 102 insertions(+), 51 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 41c61f6..0119a3c 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -15,23 +15,22 @@ "message": "Storage cleared", "description": "Notify the user that the storage has been cleared." }, - "popupButtonClear": { + "notificationStorageCopied": { + "message": "Storage copied", + "description": "Notify the user that the storage has been copied to the clipboard." + }, + "popupButtonActionClear": { "message": "Clear dump", "description": "Label for the clear dump button" }, - "popupButtonDefaultDownload": { + "popupButtonActionCopy": { + "message": "Copy to clipboard", + "description": "Label for the default copy button" + }, + "popupButtonActionDownload": { "message": "Download", "description": "Label for the default download button" }, - "popupButtonDownload": { - "message": "Download as $TYPE$", - "description": "Label for the typed download buttons", - "placeholders": { - "type": { - "content": "$1" - } - } - }, "popupContentEmpty": { "message": "The dump is empty!", "description": "Default content when there is no link in the dump." diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 04513f3..b535414 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -15,23 +15,22 @@ "message": "Entrepôt nettoyé", "description": "Notify the user that the storage has been cleared." }, - "popupButtonClear": { + "notificationStorageCopied": { + "message": "Entrepôt copié", + "description": "Notify the user that the storage has been copied to the clipboard." + }, + "popupButtonActionClear": { "message": "Nettoyer l'entrepôt", "description": "Label for the clear dump button" }, - "popupButtonDefaultDownload": { + "popupButtonActionCopy": { + "message": "Copier dans le presse-papier", + "description": "Label for the default copy button" + }, + "popupButtonActionDownload": { "message": "Télécharger", "description": "Label for the default download button" }, - "popupButtonDownload": { - "message": "Télécharger en $TYPE$", - "description": "Label for the typed download buttons", - "placeholders": { - "type": { - "content": "$1" - } - } - }, "popupContentEmpty": { "message": "L'entrepôt est vide !", "description": "Default content when there is no link in the dump." diff --git a/background.js b/background.js index a90015c..86e6c81 100644 --- a/background.js +++ b/background.js @@ -24,7 +24,7 @@ async function addLink(link) { async function addBookmark(id) { const bookmarks = await browser.bookmarks.get(id); - for (let bookmark of bookmarks) { + for (const bookmark of bookmarks) { switch (bookmark.type) { case 'bookmark': await addLink({ url: bookmark.url, title: bookmark.title}); @@ -62,6 +62,19 @@ function getDownloadOptions(format) { } } +function copy(downloadOptions) { + browser.storage.local.get('urls').then(obj => { + if (!obj.urls) return; + + const content = obj.urls.reduce(downloadOptions.reducer, ''); + + browser.runtime.sendMessage({ + action: 'copy', + payload: content + }) + }); +} + function download(downloadOptions) { browser.storage.local.get('urls').then(obj => { if (!obj.urls) return; @@ -116,6 +129,15 @@ function handleMessage(message) { download(options); break; } + case 'copy': { + const options = getDownloadOptions(message.payload); + copy(options); + break; + } + case 'copied': { + notification('notificationStorageCopied'); + break; + } case 'delete': deleteLink(message.payload); break; diff --git a/manifest.json b/manifest.json index 1687668..64fd8b7 100644 --- a/manifest.json +++ b/manifest.json @@ -7,7 +7,7 @@ "manifest_version": 2, "name": "LinkDump", - "version": "1.2", + "version": "1.3", "description": "__MSG_extensionDescription__", "icons": { "48": "icons/linkdump-48.png" @@ -16,6 +16,7 @@ "permissions": [ "activeTab", "bookmarks", + "clipboardWrite", "downloads", "menus", "notifications", diff --git a/package.json b/package.json index 7a40efe..f63cd6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "linkdump", - "version": "1.0.0", + "version": "1.3.0", "description": "Store links and dump them", "main": "background.js", "scripts": { diff --git a/popup/load.content.css b/popup/load.content.css index 578a528..8f7882d 100644 --- a/popup/load.content.css +++ b/popup/load.content.css @@ -11,13 +11,14 @@ body { font-size: 0.75rem; } div { - margin: 0.5rem; + margin: 0 0.5rem 0.5rem; } -div:last-of-type { - margin-left: 0; +div.btn-group { + margin-right: 0; } #popup-content { width: 100%; + margin-top: 0.5rem; } .delete { background-color: transparent; diff --git a/popup/load.content.html b/popup/load.content.html index dd97d8c..98518a7 100644 --- a/popup/load.content.html +++ b/popup/load.content.html @@ -9,14 +9,20 @@ -
- - - +
+ + +
+
+ + +
diff --git a/popup/load.content.js b/popup/load.content.js index cb0f2a1..f6749a9 100644 --- a/popup/load.content.js +++ b/popup/load.content.js @@ -6,12 +6,12 @@ function deleteItem(event) { } function drawContent() { - document.querySelector('#clear').textContent = browser.i18n.getMessage('popupButtonClear'); - document.querySelector('button[data-type="text"]').textContent = browser.i18n.getMessage('popupButtonDefaultDownload'); - document.querySelector('a[data-type="html"]').textContent = browser.i18n.getMessage('popupButtonDownload', 'HTML'); - document.querySelector('a[data-type="text"]').textContent = browser.i18n.getMessage('popupButtonDownload', 'text'); - document.querySelector('a[data-type="markdown"]').textContent = browser.i18n.getMessage('popupButtonDownload', 'markdown'); + document.querySelector('#clear').textContent = browser.i18n.getMessage('popupButtonActionClear'); document.querySelector('#popup-content').innerHTML = ''; + document.querySelectorAll('[data-action]').forEach(item => { + const action = item.dataset.action[0].toUpperCase() + item.dataset.action.slice(1); + item.textContent = browser.i18n.getMessage(`popupButtonAction${action}`); + }); browser.storage.local.get('urls').then(obj => { if (obj.urls && obj.urls.length !== 0) { @@ -46,11 +46,38 @@ function drawContent() { }); } -document.querySelectorAll('.download').forEach(item => { +function copyToClipboard(content) { + const textarea = document.createElement('textarea'); + textarea.textContent = content; + document.body.appendChild(textarea); + textarea.select(); + document.execCommand('copy'); + document.body.removeChild(textarea); + browser.runtime.sendMessage({ + action: 'copied' + }).then(window.close()); +} + +document.querySelectorAll('[data-action]').forEach(item => { item.addEventListener('click', (event) => { browser.runtime.sendMessage({ - action: 'download', - payload: event.target.dataset.type + action: event.target.dataset.action, + payload: event.target.dataset.format + }); + }); +}); + +document.querySelectorAll('[name="formats"]').forEach(item => { + item.addEventListener('click', (event) => { + document.querySelectorAll('[name="formats"]').forEach(current => { + if (current === event.target) { + current.parentNode.classList.add('active'); + } else { + current.parentNode.classList.remove('active'); + }; + }); + document.querySelectorAll('[data-action]').forEach(current => { + current.dataset.format = event.target.dataset.format; }); }); }); @@ -61,18 +88,14 @@ document.querySelector('#clear').addEventListener('click', () => { }).then(window.close()); }); -document.querySelector('.dropdown-toggle').addEventListener('click', (event) => { - event.target.parentNode.classList.toggle('show'); - event.target.nextElementSibling.classList.toggle('show'); - const expanded = event.target.getAttribute('aria-expanded') === 'true' ? 'false' : 'true'; - event.target.setAttribute('aria-expanded', expanded); -}); - function handleMessage(message) { switch (message.action) { case 'reload': drawContent(); break; + case 'copy': + copyToClipboard(message.payload); + break; default: // Do nothing on purpose }