Skip to content

Commit

Permalink
Merge pull request #337 from BrandonTuTwo2/master
Browse files Browse the repository at this point in the history
Allowed extension to use clipboard content to generate QR code when permission given
  • Loading branch information
rugk authored Oct 31, 2024
2 parents 7443054 + afd48c5 commit 520ef02
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 23 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@
[submodule "src/common/modules/CommonCss"]
path = src/common/modules/CommonCss
url = https://github.com/TinyWebEx/CommonCss
[submodule "src/common/modules/PermissionRequest"]
path = src/common/modules/PermissionRequest
url = https://github.com/TinyWebEx/PermissionRequest
1 change: 1 addition & 0 deletions assets/texts/en/Changelog/next.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
* **New:** An option for using the clipboard content when opening the popup has been added, thanks [@BrandonTuTwo2](https://github.com/BrandonTuTwo2)
* **New:** The translation for Urdu has been added, thanks to [@Toprun123](https://github.com/Toprun123).
* **New:** Added a context menu item for generating QR codes for the current page, with a settings option to enable or disable the context menu item, thanks to [@mahmoudhusam](https://github.com/mahmoudhusam)
3 changes: 2 additions & 1 deletion scripts/manifests/dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"menus"
],
"optional_permissions": [
"downloads"
"downloads",
"clipboardRead"
],
"applications": {
"gecko": {
Expand Down
3 changes: 2 additions & 1 deletion scripts/manifests/firefox.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
"menus"
],
"optional_permissions": [
"downloads"
"downloads",
"clipboardRead"
],
"applications": {
"gecko": {
Expand Down
19 changes: 18 additions & 1 deletion src/_locales/de/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@
"message": "Konnte Optionen nicht zurück setzen!",
"description": "The message shown, when the options of the settings could not have been reset."
},
"permissionRequiredClipboardRead": {
"message": "Die Berechtigung Daten in die Zwischenablage zu kopieren, wird für diese Funktionalität benötigt.",
"description": "The message shown, when the user wants to use the clipboard to read from"
},
"buttonRequestPermission": {
"message": "Berechtigung erteilen",
"description": "The button label, used for requesting a permission that is missing."
},
"couldNotRequestPermission": {
"message": "Konnte Berechtigung nicht erfragen.",
"description": "When the permission request fails."
},

// errors or other messages
"unknownError": {
Expand Down Expand Up @@ -254,7 +266,7 @@
"description": "This label refers to an option in the add-on settings. It allows users to toggle the visibility of the context menu item for generating a QR code from the current page."
},
"optionContextMenuEnabledDescr": {
"message": "Zeigt einen Kontextmenü-Eintrag um QR-Codes für die aktuelle Seite zu erstellen, zusätzlich zu denen für Links und ausgewählten Text.",
"message": "Zeigt einen Kontextmenü-Eintrag, um QR-Codes für die aktuelle Seite zu erstellen, zusätzlich zu denen für Links und ausgewählten Text.",
"description": "This is the helper text for the context menu toggle option. It explains that enabling this option will show the QR code generation context menu for the current page."
},

Expand Down Expand Up @@ -367,6 +379,11 @@
"description": "This is an option shown in the add-on settings."
},

"optionAutoGetClipboardContent": {
"message": "Benutze den Inhalt der Zwischenablage wenn der Popup geöffnet wird",
"description": "This is an option shown in the add-on settings."
},

"optionDebugMode": {
"message": "Aktiviere den Debug-Modus",
"description": "This is an option shown in the add-on settings."
Expand Down
17 changes: 17 additions & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@
"message": "Could not reset options!",
"description": "The message shown, when the options of the settings could not have been reset."
},
"permissionRequiredClipboardRead": {
"message": "The permission to copy data from the clipboard is required for this feature.",
"description": "The message shown, when the user wants to use the clipboard to read from"
},

// errors or other messages
"unknownError": {
Expand Down Expand Up @@ -369,6 +373,19 @@
"description": "This is an option shown in the add-on settings."
},

"optionAutoGetClipboardContent": {
"message": "Use clipboard content when opening popup",
"description": "This is an option shown in the add-on settings."
},
"buttonRequestPermission": {
"message": "Grant permission",
"description": "The button label, used for requesting a permission that is missing."
},
"couldNotRequestPermission": {
"message": "Requesting permission failed.",
"description": "When the permission request fails."
},

"optionDebugMode": {
"message": "Enable debug mode",
"description": "This is an option shown in the add-on settings."
Expand Down
2 changes: 1 addition & 1 deletion src/common/modules/AutomaticSettings
2 changes: 1 addition & 1 deletion src/common/modules/CommonCss
Submodule CommonCss updated 1 files
+14 −0 common.css
1 change: 1 addition & 0 deletions src/common/modules/PermissionRequest
Submodule PermissionRequest added at 2c2dff
1 change: 1 addition & 0 deletions src/common/modules/data/DefaultSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const defaultSettings = Object.freeze({
qrColor: "#0c0c0d",
qrBackgroundColor: (isDarkTheme ? "#d7d7db" : "#ffffff"), // dark uses Firefox Photon's grey-30
qrErrorCorrection: "Q",
autoGetClipboardContent: false,
autoGetSelectedText: false,
monospaceFont: false,
qrCodeSize: {
Expand Down
3 changes: 2 additions & 1 deletion src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"menus"
],
"optional_permissions": [
"downloads"
"downloads",
"clipboardRead"
],
"applications": {
"gecko": {
Expand Down
41 changes: 39 additions & 2 deletions src/options/modules/CustomOptionTriggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as AutomaticSettings from "/common/modules/AutomaticSettings/AutomaticS
import * as CommonMessages from "/common/modules/MessageHandler/CommonMessages.js";
import * as CustomMessages from "/common/modules/MessageHandler/CustomMessages.js";
import { MESSAGE_LEVEL } from "/common/modules/data/MessageLevel.js";
import * as PermissionRequest from "/common/modules/PermissionRequest/PermissionRequest.js";

// used to apply options
import * as Colors from "/common/modules/Colors.js";
Expand All @@ -17,6 +18,13 @@ import * as IconHandler from "/common/modules/IconHandler.js";
const REMEBER_SIZE_INTERVAL = 500; // sec
const CONTRAST_MESSAGE_ID = "contrast";

const CLIPBOARD_READ_PERMISSION = {
permissions: ["clipboardRead"]
};

const MESSAGE_CLIPBOARD_READ_PERMISSION = "getClipboardContentPermissionInfo";


let updateRemberedSizeInterval = null;

/**
Expand Down Expand Up @@ -254,6 +262,27 @@ function resetOnBeforeLoad() {
elQrCodeSize.removeAttribute("disabled");
}

/**
* Adjust options page when copy from clipboard is changed
*
* @private
* @param {Boolean} optionValue
* @param {Object} [event]
* @returns {Promise}
*/
function applyClipboardContent(optionValue, event={}) {
if (optionValue && !PermissionRequest.isPermissionGranted(CLIPBOARD_READ_PERMISSION)) {
return PermissionRequest.requestPermission(
CLIPBOARD_READ_PERMISSION,
MESSAGE_CLIPBOARD_READ_PERMISSION,
event,
{retry: true}
);
}
PermissionRequest.cancelPermissionPrompt(CLIPBOARD_READ_PERMISSION,MESSAGE_CLIPBOARD_READ_PERMISSION);
return Promise.resolve();
}

/**
* Binds the triggers.
*
Expand All @@ -262,7 +291,7 @@ function resetOnBeforeLoad() {
* @function
* @returns {void}
*/
export function registerTrigger() {
export async function registerTrigger() {
// register custom message
CustomMessages.registerMessageType(CONTRAST_MESSAGE_ID, document.getElementById("messageContrast"));

Expand All @@ -273,6 +302,7 @@ export function registerTrigger() {
AutomaticSettings.Trigger.registerSave("qrColor", applyQrCodeColors);
AutomaticSettings.Trigger.registerSave("qrBackgroundColor", applyQrCodeColors);
AutomaticSettings.Trigger.registerSave("qrQuietZone", updateQrQuietZoneStatus);
AutomaticSettings.Trigger.registerSave("autoGetClipboardContent", applyClipboardContent);

// Register trigger for contextMenuEnabled
AutomaticSettings.Trigger.registerSave("contextMenuEnabled", applyContextMenuEnabled);
Expand All @@ -284,4 +314,11 @@ export function registerTrigger() {
// handle loading of options correctly
AutomaticSettings.Trigger.registerBeforeLoad(resetOnBeforeLoad);
AutomaticSettings.Trigger.registerAfterLoad(AutomaticSettings.Trigger.RUN_ALL_SAVE_TRIGGER);
}

await PermissionRequest.registerPermissionMessageBox(
CLIPBOARD_READ_PERMISSION,
MESSAGE_CLIPBOARD_READ_PERMISSION,
document.getElementById("getClipboardContentPermissionInfo"),
"permissionRequiredClipboardRead"
);
}
17 changes: 16 additions & 1 deletion src/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ <h2 data-i18n="__MSG_subtitleMisc__">Miscellaneous settings</h2>
</div>
</li>

<li class="message-container">
<li class="line">
<div id="messageContrast" aria-label="info message" data-i18n data-i18n-aria-label="__MSG_ariaMessageInfo__" class="message-box info invisible fade-hide">
<span class="message-text"></span>
<a href="#">
Expand Down Expand Up @@ -188,6 +188,21 @@ <h1 data-i18n="__MSG_titleAddonBehavior__">Addon behavior</h1>
</div>
</li>

<li>
<div class="line">
<input class="setting save-on-change" type="checkbox" id="autoGetClipboardContent" name="autoGetClipboardContent">
<label data-i18n="__MSG_optionAutoGetClipboardContent__" for="autoGetClipboardContent">Use clipboard content when opening popup</label>
</div>
<div class="line">
<div id="getClipboardContentPermissionInfo" aria-label="info message" data-i18n data-i18n-aria-label="__MSG_ariaMessageInfo__" class="message-box info invisible fade-hide">
<span class="message-text">Permission requested.</span>
<a href="#">
<button type="button" class="message-action-button micro-button info invisible"></button>
</a>
<img class="icon-dismiss invisible" src="/common/img/close.svg" width="24" height="24" tabindex="0" data-i18n data-i18n-aria-label="__MSG_dismissIconDescription__"></span>
</div>
</div>
</li>
<li>
<div class="line">
<input class="setting save-on-change" type="checkbox" id="debugMode" name="debugMode">
Expand Down
60 changes: 46 additions & 14 deletions src/popup/modules/InitQrCode.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const userInterfaceInit = UserInterface.init().then(() => {
console.info("UserInterface module loaded.");
});

const CLIPBOARD_READ_PERMISSION = {
permissions: ["clipboardRead"]
};

// check for selected text
// current tab is used by default
const gettingSelection = AddonSettings.get("autoGetSelectedText").then((autoGetSelectedText) => {
Expand All @@ -51,11 +55,29 @@ const gettingSelection = AddonSettings.get("autoGetSelectedText").then((autoGetS
if (!selection) {
throw new Error("nothing selected");
}

return selection;
});
});

// check for clipboard text if option is enabled and if extension has permission to read from clipboard
// if the clipboard is empty it rejects the promise
const gettingClipboard = AddonSettings.get("autoGetClipboardContent").then((autoGetClipboardContent) => {
if (autoGetClipboardContent !== true || !browser.permissions.contains(CLIPBOARD_READ_PERMISSION)) {
return Promise.reject(new Error("using clipboard content is disabled"));
}

return navigator.clipboard.readText().then((text) => {
if (text && text !== "") {
return Promise.resolve(text);
} else {
return Promise.reject(new Error("clipboard is empty"));
}
}).catch(err => {
return Promise.reject(err);
});
});


// generate QR code from tab or selected text or message, if everything is set up
export const initiationProcess = Promise.all([qrCreatorInit, userInterfaceInit]).then(() => {
// do not use tab URL as text if text is already overwritten
Expand All @@ -64,7 +86,6 @@ export const initiationProcess = Promise.all([qrCreatorInit, userInterfaceInit])

return Promise.resolve();
}

// get text from selected text, if possible
return gettingSelection.then((selection) => {
try {
Expand All @@ -75,18 +96,29 @@ export const initiationProcess = Promise.all([qrCreatorInit, userInterfaceInit])
UserInterface.handleQrError(e);
}
}).catch(() => {
// …or fallback to tab URL
return queryBrowserTabs.then(QrCreator.generateFromTabs)
.catch(UserInterface.handleQrError)
.catch((error) => {
console.error(error);

// show generic error, likely a tab URL error
CommonMessages.showError("couldNotReceiveActiveTab", false);

// re-throw error
throw error;
});
// try getting text from the clipboard
return gettingClipboard.then((clipboard) => {
try {
QrCreator.setText(clipboard);
QrCreator.generate();
UserInterface.postInitGenerate();
} catch (e) {
UserInterface.handleQrError(e);
}
}).catch(() => {
// …or fallback to tab URL
return queryBrowserTabs.then(QrCreator.generateFromTabs)
.catch(UserInterface.handleQrError)
.catch((error) => {
console.error(error);

// show generic error, likely a tab URL error
CommonMessages.showError("couldNotReceiveActiveTab", false);

// re-throw error
throw error;
});
});
});
}).finally(() => {
// post-initiation code should still run, even if errors happen
Expand Down

0 comments on commit 520ef02

Please sign in to comment.