Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added feature to copy QR to clipboard #304

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,15 @@
"message": "Save QR code as an &SVG…",
"description": "The context menu entry shown for saving SVG images in the popup with an access key."
},
"contextMenuSaveImageClipboard": {
"message": "Save QR code to clipboard…",
"description": "The context menu entry shown for saving PNG images (to the clipboard) in the popup"
},
"contextMenuSaveImageClipboardAccessKey": {
"message": "Save QR code to &clipboard…",
"description": "The context menu entry shown for saving PNG images (to the clipboard) in the popup with an access key."
},


// options
"someSettingsAreManaged": {
Expand Down Expand Up @@ -353,6 +362,11 @@
"description": "This is an option shown in the add-on settings."
},

"optionOverrideCopy": {
"message": "CTRL+C/⌘+C to copy QR code",
"description": "This is an option shown in the add-on"
},

"optionDebugMode": {
"message": "Enable debug mode",
"description": "This is an option shown in the add-on settings."
Expand Down
3 changes: 2 additions & 1 deletion src/common/modules/data/DefaultSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ const defaultSettings = Object.freeze({
qrQuietZone: 1,
randomTips: {
tips: {}
}
},
overrideCopy: true
});

// freeze the inner objects, this is strongly recommend
Expand Down
7 changes: 7 additions & 0 deletions src/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ <h1 data-i18n="__MSG_titleAddonBehavior__">Addon behavior</h1>
</div>
</li>

<li>
<div class="line">
<input class="setting save-on-change" type="checkbox" id="overrideCopy" name="overrideCopy">
<label data-i18n="__MSG_optionOverrideCopy__" for="overrideCopy">CTRL+C/⌘+C to copy QR code</label>
</div>
</li>

<li>
<div class="line">
<input class="setting save-on-change" type="checkbox" id="debugMode" name="debugMode">
Expand Down
59 changes: 58 additions & 1 deletion src/popup/modules/UserInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const THROTTLE_SIZE_SAVING_FOR_REMEMBER = 500; // ms

const CONTEXT_MENU_SAVE_IMAGE_CANVAS = "save-image-canvas";
const CONTEXT_MENU_SAVE_IMAGE_SVG = "save-image-svg";
const CONTEXT_MENU_SAVE_IMAGE_CLIPBOARD = "save-image-clipboard";

const DOWNLOAD_PERMISSION = {
permissions: ["downloads"]
Expand Down Expand Up @@ -502,6 +503,10 @@ function menuClicked(event) {
}, "image/png");
break;
}
case CONTEXT_MENU_SAVE_IMAGE_CLIPBOARD: {
writeQRToClipboard()
break;
}
}
}

Expand All @@ -520,6 +525,8 @@ async function createContextMenu() {
// remove menu item if it has been added before
browser.menus.remove(CONTEXT_MENU_SAVE_IMAGE_CANVAS);
browser.menus.remove(CONTEXT_MENU_SAVE_IMAGE_SVG);
browser.menus.remove(CONTEXT_MENU_SAVE_IMAGE_CLIPBOARD);


// create save menus if needed
await createMenu("contextMenuSaveImageSvg", {
Expand All @@ -538,6 +545,13 @@ async function createContextMenu() {
]
}
);
await createMenu("contextMenuSaveImageClipboard", {
id: CONTEXT_MENU_SAVE_IMAGE_CLIPBOARD,
contexts: ["page"],
documentUrlPatterns: [
document.URL // only apply to own URL = popup
]
});

browser.menus.onClicked.addListener(menuClicked);
return Promise.resolve();
Expand Down Expand Up @@ -571,6 +585,43 @@ export function postInitGenerate() {
selectAllText({ target: qrCodeText });
}

/**
* Listens for the default copy commands CTRL+C (Windows/Linux) and CMD+C (macOS)
* and subsequently writes the current QR code to the clipboard
*
* @function
* @private
* @param {event} event
* @returns {void}
*/
function copyQRCodeToClipboard(event) {
const standardCopyCommand = event.ctrlKey && event.key === "c"
// CMD + C is standard for macOS
const macCopyCommand = event.metaKey && event.key === "c"

if (standardCopyCommand || macCopyCommand) {
writeQRToClipboard()
}
}

/**
* Writes the current QR code to the clipboard using the Clipboard API
*
* @function
* @private
* @returns {void}
*/
function writeQRToClipboard() {
const canvasElem = QrCreator.getQrCodeCanvasFromLib();

// Only works when you set dom.events.asyncClipboard.clipboardItem to True
canvasElem.toBlob((blob) => {
const clipboardImage = new ClipboardItem({"image/png": blob})
navigator.clipboard.write([clipboardImage])
}, "image/png")

}

/**
* Initalises the module.
*
Expand All @@ -591,6 +642,12 @@ export function init() {
qrCodeText.addEventListener("input", refreshQrCode);
qrCodeText.addEventListener("focus", selectAllText);

const applyingCopyListener = AddonSettings.get("overrideCopy").then((overrideCopy) => {
if (overrideCopy) {
window.addEventListener("keydown", copyQRCodeToClipboard)
}
})

const applyingMonospaceFont = AddonSettings.get("monospaceFont").then((monospaceFont) => {
if (monospaceFont) {
qrCodeText.style.fontFamily = "monospace";
Expand Down Expand Up @@ -646,5 +703,5 @@ export function init() {
const initQrTypespecificSettings = createContextMenu();

// return Promise chain
return Promise.all([applyingMonospaceFont, applyingQrSize, applyingQrColor, initQrTypespecificSettings]);
return Promise.all([applyingCopyListener, applyingMonospaceFont, applyingQrSize, applyingQrColor, initQrTypespecificSettings]);
}