From 35569e4adb082b00462a9655fd4389cc881880a0 Mon Sep 17 00:00:00 2001 From: rugk Date: Thu, 11 Apr 2019 14:34:22 +0200 Subject: [PATCH 1/8] Add feature to insert emoji into pages directly (WIP) --- src/common/modules/data/DefaultSettings.js | 1 + src/content_scripts/insertIntoPage.js | 28 ++++++++++++++ src/manifest.json | 3 +- src/popup/module/EmojiPicker.js | 18 ++++----- src/popup/module/PageHandler.js | 44 ++++++++++++++++++++++ 5 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 src/content_scripts/insertIntoPage.js create mode 100644 src/popup/module/PageHandler.js diff --git a/src/common/modules/data/DefaultSettings.js b/src/common/modules/data/DefaultSettings.js index 8778fac..ef8a689 100644 --- a/src/common/modules/data/DefaultSettings.js +++ b/src/common/modules/data/DefaultSettings.js @@ -14,5 +14,6 @@ export const DEFAULT_SETTINGS = Object.freeze({ emojiSize: 24 }, copyEmoji: "native", + automaticInsert: true, emojiMart: {} }); diff --git a/src/content_scripts/insertIntoPage.js b/src/content_scripts/insertIntoPage.js new file mode 100644 index 0000000..10218ac --- /dev/null +++ b/src/content_scripts/insertIntoPage.js @@ -0,0 +1,28 @@ +"use strict"; + +/** + * Return the username, you want to follow. + * + * @function + * @param {string} newText + * @returns {void} + */ +function insertIntoPage(newText) { // eslint-disable-line no-unused-vars + const elFocused = document.activeElement; + + // does not work in Firefox currently for text fields, only for context editable + // see https://bugzilla.mozilla.org/show_bug.cgi?id=1220696 + if (document.execCommand("insertText", false, newText)) { + return elFocused.value; + } + + const start = elFocused.selectionStart; + const end = elFocused.selectionEnd; + + if (start !== undefined && end !== undefined) { + elFocused.setRangeText(newText, start, end, "end"); + return elFocused.value; + } + + throw new Error("nothing selected"); +} diff --git a/src/manifest.json b/src/manifest.json index 7500885..70ee273 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -41,7 +41,8 @@ "default_locale": "en", "permissions": [ - "storage" + "storage", + "activeTab" ], "applications": { diff --git a/src/popup/module/EmojiPicker.js b/src/popup/module/EmojiPicker.js index ff16b72..27aa30c 100644 --- a/src/popup/module/EmojiPicker.js +++ b/src/popup/module/EmojiPicker.js @@ -5,6 +5,7 @@ */ import * as AddonSettings from "/common/modules/AddonSettings/AddonSettings.js"; +import * as PageHandler from "./PageHandler.js"; let emojiPicker = null; @@ -72,15 +73,14 @@ function getEmojiMartLocalised() { */ async function copyEmoji(emoji) { const emojiCopyOption = await AddonSettings.get("copyEmoji"); - switch (emojiCopyOption) { - case "native": - navigator.clipboard.writeText(emoji.native); - break; - case "colons": - navigator.clipboard.writeText(emoji.colons); - break; - default: - throw new Error("invalid option:", "copyEmoji", emojiCopyOption); + const emojiText = emoji[emojiCopyOption]; + + const automaticInsert = await AddonSettings.get("automaticInsert"); + + navigator.clipboard.writeText(emojiText); + + if (automaticInsert) { + PageHandler.insertIntoPage(emojiText).then(console.log); } } diff --git a/src/popup/module/PageHandler.js b/src/popup/module/PageHandler.js new file mode 100644 index 0000000..9a4a976 --- /dev/null +++ b/src/popup/module/PageHandler.js @@ -0,0 +1,44 @@ +/** + * Handling fetures for current page. + * + */ + +/** + * Insert emoji into page. + * + * @public + * @param {string} text + * @returns {void} + */ +export async function insertIntoPage(text) { + const tabs = await browser.tabs.query({ + currentWindow: true, + active: true + }); + + const promises = tabs.map(async (tab) => { + // make sure content script is inserted + await browser.tabs.executeScript(tab.id, { + code: "insertIntoPage;", + allFrames: true, + runAt: "document_end" + }).catch(() => { + // ends here if insertIntoPage == undefined + // insert function, if needed + return browser.tabs.executeScript(tab.id, { + file: "/content_scripts/insertIntoPage.js", + allFrames: true, + runAt: "document_end" + }); + }); + + // send request to insert emoji + return browser.tabs.executeScript(tab.id, { + code: `insertIntoPage("${text}");`, + allFrames: true, + runAt: "document_end" + }); + }); + + return Promise.all(promises).then((array) => array.flat()); +} From 53b5e3904a1d5c381dbea6ea6eb7611a46ea24de Mon Sep 17 00:00:00 2001 From: rugk Date: Fri, 12 Apr 2019 18:00:00 +0200 Subject: [PATCH 2/8] Remove dead code --- src/options/modules/CustomOptionTriggers.js | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/options/modules/CustomOptionTriggers.js b/src/options/modules/CustomOptionTriggers.js index 7944e4b..8e508fd 100644 --- a/src/options/modules/CustomOptionTriggers.js +++ b/src/options/modules/CustomOptionTriggers.js @@ -201,26 +201,6 @@ function updateEmojiPerLineMaxViaEmojiSize(optionValue, option, event) { console.log("Caluclated a maximum number of emojis per line of", newMaxValue, "for emojis of size", `${emojiSizeValue}px,`, "resulting in an estimated with of", `${estimatedWidth}px.`); - // switch (emojiSizeValue) { - // case 16: - // newMaxValue = 50; // theoretically ~800/16=50 - // break; - // case 24: - // newMaxValue = 20; // theoretically ~800/24=33 - // break; - // case 32: - // newMaxValue = 20; // theoretically ~800/32=25 - // break; - // case 40: - // newMaxValue = 20; // theoretically ~800/40=20 - // break; - // case 48: - // newMaxValue = 12; // theoretically ~800/48=16 - // break; - // default: - // throw new TypeError(`Emoji size value ${emojiSizeValue} is unsupported.`); - // } - // apply new max value const oldEmojisPerLineValue = elEmojisPerLine.value; elEmojisPerLine.max = newMaxValue; From 0ea9985860c76afbe786fa9c65e011d7e08cc12c Mon Sep 17 00:00:00 2001 From: rugk Date: Mon, 15 Apr 2019 20:18:08 +0200 Subject: [PATCH 3/8] WIP: Add option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Still needs translation. And has an awkward bug where it reloads the option page… --- scripts/manifests/dev.json | 4 + scripts/manifests/firefox.json | 4 + src/common/modules/data/DefaultSettings.js | 10 +- src/manifest.json | 7 +- src/options/modules/CustomOptionTriggers.js | 117 ++++++++++++++++++-- src/options/options.css | 8 ++ src/options/options.html | 32 +++++- src/options/options.js | 3 + src/popup/module/EmojiPicker.js | 51 +++++++-- src/popup/module/PageHandler.js | 4 +- 10 files changed, 216 insertions(+), 24 deletions(-) diff --git a/scripts/manifests/dev.json b/scripts/manifests/dev.json index 7500885..d4a122c 100644 --- a/scripts/manifests/dev.json +++ b/scripts/manifests/dev.json @@ -44,6 +44,10 @@ "storage" ], + "optional_permissions": [ + "clipboardWrite" + ], + "applications": { "gecko": { "id": "awesome-emoji-picker@rugk.github.io", diff --git a/scripts/manifests/firefox.json b/scripts/manifests/firefox.json index 5bc3e83..9f85756 100644 --- a/scripts/manifests/firefox.json +++ b/scripts/manifests/firefox.json @@ -43,6 +43,10 @@ "storage" ], + "optional_permissions": [ + "clipboardWrite" + ], + "applications": { "gecko": { "id": "awesome-emoji-picker@rugk.github.io", diff --git a/src/common/modules/data/DefaultSettings.js b/src/common/modules/data/DefaultSettings.js index ef8a689..9a3b019 100644 --- a/src/common/modules/data/DefaultSettings.js +++ b/src/common/modules/data/DefaultSettings.js @@ -13,7 +13,13 @@ export const DEFAULT_SETTINGS = Object.freeze({ emojiTooltip: false, emojiSize: 24 }, - copyEmoji: "native", - automaticInsert: true, + pickerResult: { + automaticInsert: true, + emojiCopy: true, + // emojiCopyOnlyFallback MUST NOT be true, as optional clipboardWrite + // permission is required for this + emojiCopyOnlyFallback: true, + resultType: "native", + }, emojiMart: {} }); diff --git a/src/manifest.json b/src/manifest.json index 70ee273..d4a122c 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -41,8 +41,11 @@ "default_locale": "en", "permissions": [ - "storage", - "activeTab" + "storage" + ], + + "optional_permissions": [ + "clipboardWrite" ], "applications": { diff --git a/src/options/modules/CustomOptionTriggers.js b/src/options/modules/CustomOptionTriggers.js index 8e508fd..37e36a5 100644 --- a/src/options/modules/CustomOptionTriggers.js +++ b/src/options/modules/CustomOptionTriggers.js @@ -5,10 +5,20 @@ */ import * as AutomaticSettings from "/common/modules/AutomaticSettings/AutomaticSettings.js"; +import * as CommonMessages from "/common/modules/MessageHandler/CommonMessages.js"; +import * as CustomMessages from "/common/modules/MessageHandler/CustomMessages.js"; // used to apply options import * as IconHandler from "/common/modules/IconHandler.js"; +const CLIPBOARD_WRITE_PERMISSION = { + permissions: ["clipboardWrite"] +}; +const MESSAGE_EMOJI_COPY_PERMISSION = "emojiCopyOnlyFallbackPermissionInfo"; + +let addonHasClipboardWritePermission = false; +let clipboardWriteRequestMessageIsShown = false; + /** * Adjust UI if QR code size option is changed. * @@ -43,6 +53,85 @@ function saveEmojiSet(param) { return AutomaticSettings.Trigger.overrideContinue(param.optionValue); } +/** + * Requests the permission for pickerResult settings. + * + * @private + * @param {Object} optionValue + * @param {string} [option] + * @param {Object} [event] + * @returns {Promise} + */ +function applyPickerResultPermissions(optionValue, option, event) { + let retPromise; + const isUserInteractionHandler = event.type === "input" || event.type === "click" || event.type === "change"; + + if (optionValue.emojiCopyOnlyFallback && // if we require a permission + !addonHasClipboardWritePermission // and not already granted + ) { + // no action button by default + let actionButton = {}; + // if we cannot actually request the permission, let's show a useful + // message, at least + if (!isUserInteractionHandler) { + clipboardWriteRequestMessageIsShown = true; + + actionButton = { + text: "Grant permission", + action: (param) => { + return applyPickerResultPermissions(optionValue, option, param.event); + } + }; + } + + CustomMessages.showMessage(MESSAGE_EMOJI_COPY_PERMISSION, + "We need the permission to copy data into the clipboard for this feature.", + false, + actionButton); + + // if we were called from an input handler, we can request the permission + // otherwise, we return now + if (!isUserInteractionHandler) { + return Promise.resolve(); + } + + retPromise = browser.permissions.request(CLIPBOARD_WRITE_PERMISSION).catch((error) => { + console.error(error); + // convert error to negative return value + return null; + }).then((permissionSuccessful) => { + switch (permissionSuccessful) { + case true: + // permission has been granted + addonHasClipboardWritePermission = true; + return; + case null: + CommonMessages.showError("Requesting clipboard permission failed.", true); + break; + case false: + // CommonMessages.showError("This feature cannot be used without the clipboard permission.", true); + break; + default: + console.error("Unknown value for permissionSuccessful:", permissionSuccessful); + } + + optionValue.emojiCopyOnlyFallback = false; + document.getElementById("emojiCopyOnlyFallback").checked = false; + + throw new Error("permission request error"); + }).finally(() => { + CustomMessages.hideMessage(MESSAGE_EMOJI_COPY_PERMISSION, {animate: true}); + }); + } else if (clipboardWriteRequestMessageIsShown) { + CustomMessages.hideMessage(MESSAGE_EMOJI_COPY_PERMISSION, {animate: true}); + // only needs to be reset here, as it is only about the message with an + // action button + clipboardWriteRequestMessageIsShown = false; + } + + return retPromise; +} + /** * Adjusts the emoji size setting for saving. * @@ -62,7 +151,7 @@ function adjustEmojiSize(param) { } /** - * Adjusts the copyEmojiColons setting for saving. + * Adjusts the pickerResult->resultType setting for saving. * * @private * @param {Object} param @@ -76,7 +165,7 @@ function adjustEmojiSize(param) { * always contain a value here. * @returns {Promise} */ -function prepareEmojiCopyOptionForInput(param) { +function preparePickerResultTypeOptionForInput(param) { switch (param.optionValue) { case "colons": param.optionValue = true; @@ -92,7 +181,7 @@ function prepareEmojiCopyOptionForInput(param) { } /** - * Adjusts the copyEmojiColons setting for saving. + * Adjusts the pickerResult->resultType setting for saving. * * @private * @param {Object} param @@ -102,11 +191,11 @@ function prepareEmojiCopyOptionForInput(param) { * previously run safe triggers * @returns {Promise} */ -function adjustEmojiCopyOption(param) { - if (param.optionValue) { - param.optionValue = "colons"; +function adjustPickerResultTypeOption(param) { + if (param.optionValue.resultType) { + param.optionValue.resultType = "colons"; } else { - param.optionValue = "native"; + param.optionValue.resultType = "native"; } return AutomaticSettings.Trigger.overrideContinue(param.optionValue); @@ -229,18 +318,28 @@ function updateEmojiPerLineMaxViaEmojiSize(optionValue, option, event) { * @returns {void} */ export function registerTrigger() { + // query permission values, so they can be accessed syncronously + browser.permissions.contains(CLIPBOARD_WRITE_PERMISSION).then((hasPermission) => { + addonHasClipboardWritePermission = hasPermission; + }); + // override load/safe behaviour for custom fields AutomaticSettings.Trigger.addCustomSaveOverride("emojiPicker", saveEmojiSet); AutomaticSettings.Trigger.addCustomSaveOverride("emojiPicker", adjustEmojiSize); - AutomaticSettings.Trigger.addCustomLoadOverride("copyEmoji", prepareEmojiCopyOptionForInput); - AutomaticSettings.Trigger.addCustomSaveOverride("copyEmoji", adjustEmojiCopyOption); + + AutomaticSettings.Trigger.addCustomLoadOverride("resultType", preparePickerResultTypeOptionForInput); + AutomaticSettings.Trigger.addCustomSaveOverride("pickerResult", adjustPickerResultTypeOption); // loading does not need to be overwritten, as we are fine with an extra string saved // update slider status + AutomaticSettings.Trigger.registerSave("pickerResult", applyPickerResultPermissions); AutomaticSettings.Trigger.registerSave("popupIconColored", applyPopupIconColor); AutomaticSettings.Trigger.registerSave("emojiPicker", updatePerLineStatus); AutomaticSettings.Trigger.registerSave("emojiPicker", updateEmojiPerLineMaxViaEmojiSize); // handle loading of options correctly AutomaticSettings.Trigger.registerAfterLoad(AutomaticSettings.Trigger.RUN_ALL_SAVE_TRIGGER); + + // register custom messages + CustomMessages.registerMessageType(MESSAGE_EMOJI_COPY_PERMISSION, document.getElementById("emojiCopyOnlyFallbackPermissionInfo")); } diff --git a/src/options/options.css b/src/options/options.css index 6a3cd0f..42c6d0b 100644 --- a/src/options/options.css +++ b/src/options/options.css @@ -24,6 +24,10 @@ ul { margin: 0px; padding: 0px; } +/* still show padding if ul is used for indentation */ +ul ul { + padding-left: 40px; +} li { list-style-type: none; margin-top: 10px; @@ -79,3 +83,7 @@ input[type=radio] ~ .helper-text { border-radius: 2px; /* looks better on GNOME, at least */ box-shadow: 0 0 0 2px var(--red-60-light-shadow); } + +.message-inside-options { + margin-top: 10px; +} diff --git a/src/options/options.html b/src/options/options.html index 4625885..f1b13b2 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -92,12 +92,38 @@ Shows a tooltip with the name of the Emoji when hovering over it. + +

Behaviour

  • - - - Only useful to enable on specific sites that support this kind of text. + + +
  • +
  • + + +
      +
    • + + +
    • + +
      + +
      +
  • +
  • + + + Only useful to enable on specific sites that support this kind of text. +
  • diff --git a/src/options/options.js b/src/options/options.js index 5563625..7ff3790 100644 --- a/src/options/options.js +++ b/src/options/options.js @@ -9,6 +9,9 @@ import * as AutomaticSettings from "/common/modules/AutomaticSettings/AutomaticS import * as CustomOptionTriggers from "./modules/CustomOptionTriggers.js"; // init modules +window.trigger = window.trigger || 0; +window.trigger++; +console.error("OPTIONS PAGE INIT CODE TRIGGERED", window.trigger); CustomOptionTriggers.registerTrigger(); AutomaticSettings.setDefaultOptionProvider(AddonSettings.getDefaultValue); AutomaticSettings.init(); diff --git a/src/popup/module/EmojiPicker.js b/src/popup/module/EmojiPicker.js index 27aa30c..809432e 100644 --- a/src/popup/module/EmojiPicker.js +++ b/src/popup/module/EmojiPicker.js @@ -8,6 +8,7 @@ import * as AddonSettings from "/common/modules/AddonSettings/AddonSettings.js"; import * as PageHandler from "./PageHandler.js"; let emojiPicker = null; +let optionPickerResult = {}; const EMOJI_SHEET_DIR = "/popup/img/emoji-images"; @@ -72,16 +73,48 @@ function getEmojiMartLocalised() { * @returns {void} */ async function copyEmoji(emoji) { - const emojiCopyOption = await AddonSettings.get("copyEmoji"); - const emojiText = emoji[emojiCopyOption]; + // destructure config + const { + resultType, + automaticInsert, + emojiCopyOnlyFallback + } = optionPickerResult; + let emojiCopy = optionPickerResult.emojiCopy; + + // get type to use + const emojiText = emoji[resultType]; + + // insert emoji + let emojiInsertResult = Promise.resolve(); // successful by default + if (automaticInsert) { + emojiInsertResult = PageHandler.insertIntoPage(emojiText).then(console.log); + } - const automaticInsert = await AddonSettings.get("automaticInsert"); + // wait for successful execution, if wanted + if (emojiCopyOnlyFallback) { + await (emojiInsertResult.then(() => { + // if successful, do not copy emoji + emojiCopy = false; + }).catch(() => { + console.error("Insertion into page failed. Use emoji copy fallback."); - navigator.clipboard.writeText(emojiText); + emojiCopy = true; - if (automaticInsert) { - PageHandler.insertIntoPage(emojiText).then(console.log); + // resolve promise, so await continues + })); } + + // copy to clipboard + let emojiCopyResult = Promise.resolve(); // successful by default + if (emojiCopy) { + // WARNING: If there is an asyncronous waiting (await) before, we need to + // request the clipboardWrite permission to be able to do this, as the + // function call is then not anymore assigned to a click handler + // TODO: rejection with undefined error -> MOZILA BUG + emojiCopyResult = navigator.clipboard.writeText(emojiText); + } + + return Promise.all([emojiInsertResult, emojiCopyResult]); } /** @@ -119,9 +152,13 @@ export function setAttribute(properties) { * @param {Object} settings * @returns {Promise} */ -export function init(settings) { +export async function init(settings) { const initProperties = Object.assign(settings, hardcodedSettings); + // request it/preload it here, so we need no async request to access it + // later + optionPickerResult = await AddonSettings.get("pickerResult"); + console.debug("Using these emoji-mart settings:", initProperties); const promiseCreateElement = window.emojiMart.definePicker("emoji-picker", initProperties); diff --git a/src/popup/module/PageHandler.js b/src/popup/module/PageHandler.js index 9a4a976..7439717 100644 --- a/src/popup/module/PageHandler.js +++ b/src/popup/module/PageHandler.js @@ -6,9 +6,11 @@ /** * Insert emoji into page. * + * Returns a Promise that results in the text that has been modified. + * * @public * @param {string} text - * @returns {void} + * @returns {Promise} */ export async function insertIntoPage(text) { const tabs = await browser.tabs.query({ From 7f8c5a3eb079a506b8c68225f903df6dca3b4c8a Mon Sep 17 00:00:00 2001 From: rugk Date: Tue, 16 Apr 2019 08:13:45 +0200 Subject: [PATCH 4/8] Add accidentially removed active tab permission --- scripts/manifests/dev.json | 3 ++- scripts/manifests/firefox.json | 3 ++- src/manifest.json | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/manifests/dev.json b/scripts/manifests/dev.json index d4a122c..8473e37 100644 --- a/scripts/manifests/dev.json +++ b/scripts/manifests/dev.json @@ -41,7 +41,8 @@ "default_locale": "en", "permissions": [ - "storage" + "storage", + "activeTab" ], "optional_permissions": [ diff --git a/scripts/manifests/firefox.json b/scripts/manifests/firefox.json index 9f85756..fc8950d 100644 --- a/scripts/manifests/firefox.json +++ b/scripts/manifests/firefox.json @@ -40,7 +40,8 @@ "default_locale": "en", "permissions": [ - "storage" + "storage", + "activeTab" ], "optional_permissions": [ diff --git a/src/manifest.json b/src/manifest.json index d4a122c..8473e37 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -41,7 +41,8 @@ "default_locale": "en", "permissions": [ - "storage" + "storage", + "activeTab" ], "optional_permissions": [ From e439c61aceef9a0779dd17690f0b9d2e982aa784 Mon Sep 17 00:00:00 2001 From: rugk Date: Tue, 16 Apr 2019 08:42:37 +0200 Subject: [PATCH 5/8] Fix buttons not explicitly marked as not-submit buttons Otherwise they are submit buttons and submit the form/reload the site. --- src/options/options.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/options/options.html b/src/options/options.html index f1b13b2..53972ae 100644 --- a/src/options/options.html +++ b/src/options/options.html @@ -17,28 +17,28 @@ @@ -111,7 +111,7 @@

    Behaviour

    From 2062bb033b8b5c1da194237059aecedba7aed591 Mon Sep 17 00:00:00 2001 From: rugk Date: Sun, 21 Apr 2019 19:26:38 +0200 Subject: [PATCH 6/8] Actually make options work The fallback option requires the clipboardWrite though. This required much code to handle different cases, when the permission is there already or not, etc. Also some AddonSettings adjustments, so it all works. (settings are now frozen e.g.) --- scripts/manifests/dev.json | 2 +- src/common/modules/AddonSettings | 2 +- src/common/modules/data/DefaultSettings.js | 28 +++++++++++++++++++--- src/manifest.json | 2 +- src/options/modules/.gitkeep | 0 src/options/options.js | 3 --- src/popup/module/EmojiPicker.js | 19 ++++++++++++++- src/tests/run.js | 2 +- 8 files changed, 47 insertions(+), 11 deletions(-) delete mode 100644 src/options/modules/.gitkeep diff --git a/scripts/manifests/dev.json b/scripts/manifests/dev.json index 8473e37..1ba9c9d 100644 --- a/scripts/manifests/dev.json +++ b/scripts/manifests/dev.json @@ -32,7 +32,7 @@ }, // testing version allows loading unit test libraries from CDNs - "content_security_policy": "default-src 'self'; img-src data: https://unpkg.com", + "content_security_policy": "default-src 'self'; img-src data:; style-src 'self' https://unpkg.com; script-src 'self' https://unpkg.com", "icons": { "32": "icons/icon_32.png", "64": "icons/icon_64.png", diff --git a/src/common/modules/AddonSettings b/src/common/modules/AddonSettings index 192c833..b3da318 160000 --- a/src/common/modules/AddonSettings +++ b/src/common/modules/AddonSettings @@ -1 +1 @@ -Subproject commit 192c833bfdc8a2d75b876b6eb9b1a14cd57c4b42 +Subproject commit b3da318002a1fbbdf15aa93be8b0e062b9c6ff69 diff --git a/src/common/modules/data/DefaultSettings.js b/src/common/modules/data/DefaultSettings.js index 9a3b019..9490920 100644 --- a/src/common/modules/data/DefaultSettings.js +++ b/src/common/modules/data/DefaultSettings.js @@ -4,7 +4,14 @@ * @module data/DefaultSettings */ -export const DEFAULT_SETTINGS = Object.freeze({ +/** + * An object of all default settings. + * + * @private + * @const + * @type {Object} + */ +const defaultSettings = { popupIconColored: true, emojiPicker: { set: "native", @@ -18,8 +25,23 @@ export const DEFAULT_SETTINGS = Object.freeze({ emojiCopy: true, // emojiCopyOnlyFallback MUST NOT be true, as optional clipboardWrite // permission is required for this - emojiCopyOnlyFallback: true, + // (As it leads to an error, that may happen in reality with sync, however, + // it is anyway, handled in the options, but not really nice to see it + // directly after installing the add-on) + emojiCopyOnlyFallback: false, resultType: "native", }, emojiMart: {} -}); +}; + +// freeze the inner objects, this is strongly recommend +Object.values(defaultSettings).map(Object.freeze); + +/** + * Export the default settings to be used. + * + * @public + * @const + * @type {Object} + */ +export const DEFAULT_SETTINGS = Object.freeze(defaultSettings); diff --git a/src/manifest.json b/src/manifest.json index 8473e37..1ba9c9d 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -32,7 +32,7 @@ }, // testing version allows loading unit test libraries from CDNs - "content_security_policy": "default-src 'self'; img-src data: https://unpkg.com", + "content_security_policy": "default-src 'self'; img-src data:; style-src 'self' https://unpkg.com; script-src 'self' https://unpkg.com", "icons": { "32": "icons/icon_32.png", "64": "icons/icon_64.png", diff --git a/src/options/modules/.gitkeep b/src/options/modules/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/options/options.js b/src/options/options.js index 7ff3790..5563625 100644 --- a/src/options/options.js +++ b/src/options/options.js @@ -9,9 +9,6 @@ import * as AutomaticSettings from "/common/modules/AutomaticSettings/AutomaticS import * as CustomOptionTriggers from "./modules/CustomOptionTriggers.js"; // init modules -window.trigger = window.trigger || 0; -window.trigger++; -console.error("OPTIONS PAGE INIT CODE TRIGGERED", window.trigger); CustomOptionTriggers.registerTrigger(); AutomaticSettings.setDefaultOptionProvider(AddonSettings.getDefaultValue); AutomaticSettings.init(); diff --git a/src/popup/module/EmojiPicker.js b/src/popup/module/EmojiPicker.js index 809432e..9f9d4ff 100644 --- a/src/popup/module/EmojiPicker.js +++ b/src/popup/module/EmojiPicker.js @@ -11,6 +11,11 @@ let emojiPicker = null; let optionPickerResult = {}; const EMOJI_SHEET_DIR = "/popup/img/emoji-images"; +const CLIPBOARD_WRITE_PERMISSION = { + permissions: ["clipboardWrite"] +}; + +let addonHasClipboardWritePermission = false; /** * Hardcoded settings for emoji-mart picker @@ -81,6 +86,8 @@ async function copyEmoji(emoji) { } = optionPickerResult; let emojiCopy = optionPickerResult.emojiCopy; + console.log("Action triggered for emoji:", emoji); + // get type to use const emojiText = emoji[resultType]; @@ -98,7 +105,15 @@ async function copyEmoji(emoji) { }).catch(() => { console.error("Insertion into page failed. Use emoji copy fallback."); - emojiCopy = true; + if (addonHasClipboardWritePermission) { + emojiCopy = true; + } else { + console.error("Well, actually…, we cannot fallback, as we miss the clipboardWrite permission"); + // Note: We cannot request the permission now, because of the same reason why we cannot actually + // copy without clipboardWrite permission (this is no user action anymore) + + // TODO: show visible error to the user!! + } // resolve promise, so await continues })); @@ -158,6 +173,8 @@ export async function init(settings) { // request it/preload it here, so we need no async request to access it // later optionPickerResult = await AddonSettings.get("pickerResult"); + // query permission values, so they can be accessed syncronously + addonHasClipboardWritePermission = await browser.permissions.contains(CLIPBOARD_WRITE_PERMISSION); console.debug("Using these emoji-mart settings:", initProperties); diff --git a/src/tests/run.js b/src/tests/run.js index e3d68ae..4244d65 100644 --- a/src/tests/run.js +++ b/src/tests/run.js @@ -1,7 +1,7 @@ import "https://unpkg.com/mocha@5.2.0/mocha.js"; /* globals mocha */ /* tests */ -import "./module.test.js"; +import "/common/modules/AddonSettings/tests/dataTest/defaultSettings.test.js"; mocha.checkLeaks(); mocha.run(); From cdd27fb02a9e54527460c6f2370274474787fe49 Mon Sep 17 00:00:00 2001 From: rugk Date: Sun, 21 Apr 2019 19:29:43 +0200 Subject: [PATCH 7/8] Fix privacy text in German --- assets/texts/de/privacy.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/texts/de/privacy.txt b/assets/texts/de/privacy.txt index 24a3bd5..c232a3a 100644 --- a/assets/texts/de/privacy.txt +++ b/assets/texts/de/privacy.txt @@ -1,9 +1,9 @@ Dieses Add-on sendet keine Informationen zum Add-on-Autor oder einer Drittpartei. -Eine Erklärung aller Berechtigungen, die dieses Add-on erfragt kann auf https://github.com/rugk/awesome-emoji-picker/blob/master/assets/texts/de/permissions.md gefunden werden. +Eine Erklärung aller Berechtigungen, die dieses Add-on erfragt, kann auf https://github.com/rugk/awesome-emoji-picker/blob/master/assets/texts/de/permissions.md gefunden werden. == DIENSTE VON DRITTEN == -Dieses ADD-ON nutzt den „Sync storage” des Browser's um die Einstellungen zu speicheren. Wenn der NUTZER “Sync” im Browser aktiviert, werden die Einstellungen des Add-ons hoch geladen und zwischen den Geräten, die mit dem (Mozilla) Account des Browsers verbunden sind, synchronisiert. Wenn dies nicht gemacht wird, werden die Daten lokal auf dem Gerät gespeichert. +Dieses ADD-ON nutzt den „Sync storage” des Browser's um die Einstellungen zu speicheren. Wenn der NUTZER „Sync” im Browser aktiviert, werden die Einstellungen des Add-ons hoch geladen und zwischen den Geräten, die mit dem (Mozilla) Account des Browsers verbunden sind, synchronisiert. Wenn dies nicht gemacht wird, werden die Daten lokal auf dem Gerät gespeichert. In Mozilla Firefox werden die Daten Ende-zu-Ende-verschlüsselt bevor sie hoch geladen und auf den Servern von Mozilla gespeichert werden. Siehe https://accounts.firefox.com/legal/privacy und https://www.mozilla.org/privacy/firefox/#c-privacy-topic-8 für Mozilla's Datenschutzerklärung über dieses Thema. From dae2ed05728e856ab18b86f539f176eefbea29f7 Mon Sep 17 00:00:00 2001 From: rugk Date: Sun, 21 Apr 2019 19:30:39 +0200 Subject: [PATCH 8/8] Fix learn more link --- src/options/options.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/options/options.css b/src/options/options.css index 42c6d0b..5622de0 100644 --- a/src/options/options.css +++ b/src/options/options.css @@ -71,8 +71,8 @@ input[type=radio] ~ .helper-text { margin-left: 28px; } -/* when a link is used in a helper text, add margin */ -.helper-text > a { +/* when a "Learn more" link is used in a helper text, add margin */ +.learn-more { margin-left: 4px; overflow-wrap: none; }