├── LICENSE ├── README.md └── content ├── background.js ├── bookmarklet.js ├── ico-128.png ├── ico-48.png ├── manifest.json ├── options.html └── options.js /LICENSE: -------------------------------------------------------------------------------- 1 | ISC License 2 | 3 | Copyright (c) 2014-2019 Lapo Luchini 4 | 5 | Permission to use, copy, modify, and/or distribute this software for any 6 | purpose with or without fee is hereby granted, provided that the above 7 | copyright notice and this permission notice appear in all copies. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 10 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 12 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 | OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 | PERFORMANCE OF THIS SOFTWARE. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Add to Pinry 2 | ============ 3 | 4 | This is a Chrome and Firefox Extension to ease adding content to [Pinry](https://github.com/pinry/pinry/). 5 | 6 | Compile your own or install from [Google Play Store](https://chrome.google.com/webstore/detail/pinry-chrome/jmhdcnmfkglikfjafdmdikoonedgijpa) or [Mozilla Addons](https://addons.mozilla.org/it/firefox/addon/add-to-pinry/). 7 | 8 | credits 9 | ------- 10 | 11 | - context menu and Firefox support by [winkidney](https://github.com/winkidney) ([GitHub PR 2](https://github.com/lapo-luchini/chrome-pinry/pull/2)). 12 | -------------------------------------------------------------------------------- /content/background.js: -------------------------------------------------------------------------------- 1 | chrome.browserAction.onClicked.addListener(function (tab) { 2 | chrome.tabs.executeScript(tab.id, { file: 'bookmarklet.js' }) 3 | }); 4 | 5 | function updateContextMenu() { 6 | chrome.storage.local.get('contextMenu', function (obj) { 7 | console.log('Context menu: ' + (obj.contextMenu ? 'enabled' : 'disabled')); 8 | chrome.contextMenus.removeAll(); 9 | if (obj.contextMenu) 10 | chrome.contextMenus.create({ 11 | title: 'Add to Pinry', 12 | contexts: [ 'page', 'selection', 'link', 'editable', 'image', 'video', 'audio' ], 13 | onclick: function (info, tab) { 14 | chrome.tabs.executeScript(tab.id, { file: 'bookmarklet.js' }) 15 | } 16 | }); 17 | }); 18 | } 19 | 20 | updateContextMenu(); 21 | chrome.runtime.onMessage.addListener(updateContextMenu); 22 | -------------------------------------------------------------------------------- /content/bookmarklet.js: -------------------------------------------------------------------------------- 1 | void((function (d) { 2 | var prev = d.getElementById('pinry-bookmarklet'); 3 | if (prev) // remove previous instance 4 | try { 5 | prev.remove(); 6 | d.getElementById('pinry-images').remove(); 7 | } finally { 8 | return; 9 | } 10 | // load new instance 11 | chrome.storage.local.get('pinryUrl', function (obj) { 12 | var s = d.createElement('script'); 13 | s.id = 'pinry-bookmarklet'; 14 | s.src = obj.pinryUrl + '/static/js/bookmarklet.js?' + Math.random() * 10000000000000000; 15 | d.body.appendChild(s); 16 | }); 17 | })(document)); 18 | -------------------------------------------------------------------------------- /content/ico-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lapo-luchini/browser-pinry/820e80dbae79865954ba7f4db6650ad8bb04aee7/content/ico-128.png -------------------------------------------------------------------------------- /content/ico-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lapo-luchini/browser-pinry/820e80dbae79865954ba7f4db6650ad8bb04aee7/content/ico-48.png -------------------------------------------------------------------------------- /content/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Add to Pinry", 3 | "version": "0.2.1", 4 | "description": "Pins images from current page to a Pinry installation.", 5 | "manifest_version": 2, 6 | "icons": { 7 | "48": "ico-48.png", 8 | "128": "ico-128.png" 9 | }, 10 | "permissions": [ 11 | "contextMenus", 12 | "activeTab", 13 | "storage" 14 | ], 15 | "browser_action": { 16 | "default_icon": "ico-128.png", 17 | "default_title": "Add to Pinry" 18 | }, 19 | "background": { 20 | "scripts": [ "background.js" ] 21 | }, 22 | "options_ui": { 23 | "page": "options.html", 24 | "browser_style": true, 25 | "chrome_style": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /content/options.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Pinry Options 6 | 15 | 16 | 17 |
18 |

22 |

26 |
27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /content/options.js: -------------------------------------------------------------------------------- 1 | // Show and save changes to browser extension settings. 2 | 3 | const 4 | defaultURL = 'http://demo.getpinry.com/', 5 | url = document.getElementById('pinryUrl'), 6 | menu = document.getElementById('contextMenu'), 7 | re = /[/]+(static[/]js[/]bookmarklet[.]js)?$/; 8 | 9 | function checkIMG(url) { 10 | return new Promise((resolve, reject) => { 11 | // we can avoid extra permissions and CORS this way 12 | const img = new Image(); 13 | img.onload = resolve; 14 | img.onerror = reject; 15 | img.src = url; 16 | }); 17 | } 18 | 19 | function check() { 20 | const img1 = checkIMG(url.value + '/static/img/logo-dark.png'); // Pinry pre-SPA 21 | const img2 = checkIMG(url.value + '/img/icons/android-chrome-192x192.png'); // Pinry SPA 22 | img1.catch(() => img2 // waiting for Promise.any: https://github.com/tc39/proposal-promise-any 23 | ).then(() => { url.style.backgroundColor = '#9F9' } 24 | ).catch(() => { url.style.backgroundColor = '#F99' }); 25 | } 26 | 27 | function load() { 28 | chrome.storage.local.get(null, function (obj) { 29 | url.value = obj.pinryUrl || defaultURL; 30 | menu.checked = (obj.contextMenu === false) ? false : true; // default true 31 | check(); 32 | }); 33 | } 34 | 35 | function save() { 36 | url.value = url.value.trim().replace(re, ''); 37 | check(); 38 | const cfg = { 39 | pinryUrl: url.value, 40 | contextMenu: menu.checked, 41 | }; 42 | chrome.storage.local.set(cfg, load); 43 | chrome.runtime.sendMessage(null, 'updateContextMenu'); 44 | console.log('Saved:', cfg); 45 | } 46 | 47 | document.addEventListener('DOMContentLoaded', load); 48 | url.addEventListener('change', save); 49 | menu.addEventListener('change', save); 50 | --------------------------------------------------------------------------------