-
Notifications
You must be signed in to change notification settings - Fork 21
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
Use the built-in keyboard commands system #73
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ function assertNoResponse(response) { | |
} | ||
|
||
function notifyError(error) { | ||
browser.notifications.create({ | ||
browser.notifications?.create({ | ||
type: "basic", | ||
title: "Textern", | ||
message: "Error: " + error + "." | ||
|
@@ -126,3 +126,16 @@ function onMessage(message, sender, respond) { | |
} | ||
|
||
browser.runtime.onMessage.addListener(onMessage); | ||
|
||
browser.commands.onCommand.addListener(function(command) { | ||
if (command === 'textern') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I wonder if the shortcut name should be something more specific, in case we add others in the future. Though if I understand correctly the API docs, we should be free to change this identifier in a future version, so maybe that's OK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think these names are internally namespaced to each extension to avoid such collisions. If you want to make it more reflective of the action, that's fine. |
||
browser.tabs.query({ | ||
currentWindow: true, | ||
active: true | ||
}).then(function(tabs) { | ||
if (tabs?.length && tabs[0].id != browser.tabs.TAB_ID_NONE) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need the |
||
browser.tabs.sendMessage(tabs[0].id, {type: 'shortcut'}).then(assertNoResponse, logError); | ||
} | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not |
||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we log to the console here if we received any other commands we don't know? |
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,7 @@ function assertNoResponse(response) { | |
} | ||
|
||
function notifyError(error) { | ||
browser.notifications.create({ | ||
browser.notifications?.create({ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here too. |
||
type: "basic", | ||
title: "Textern", | ||
message: "Error: " + error + "." | ||
|
@@ -91,8 +91,7 @@ function slackSetText(e, text) { | |
} | ||
} | ||
|
||
function registerText(event) { | ||
var e = event.target; | ||
function registerText(e) { | ||
if (e.nodeName == "TEXTAREA") { | ||
var id = watchElement(e); | ||
/* don't use href directly to not bring in e.g. url params */ | ||
|
@@ -171,43 +170,37 @@ function setText(id, text) { | |
fadeBackground(e); | ||
} | ||
|
||
function getActiveElement(element = document.activeElement) { | ||
if (element.nodeName === 'IFRAME' || element.nodeName === 'FRAME') | ||
return null; // skip to allow child documents to handle shortcut | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Quite possibly, I don't recall if I tried that approach. |
||
|
||
const shadowRoot = element.shadowRoot | ||
const contentDocument = element.contentDocument | ||
|
||
if (shadowRoot && shadowRoot.activeElement) { | ||
return getActiveElement(shadowRoot.activeElement) | ||
} | ||
Comment on lines
+180
to
+182
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Interesting, didn't know about shadow roots before. Do you have an example page where a textarea on which you'd want to use Textern is actually nested under a shadow root? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it was only to ensure we attach to the right element. I read this answer on SO, and didn't want neglect pages that used more complex DOMs. |
||
|
||
if (contentDocument && contentDocument.activeElement) { | ||
return getActiveElement(contentDocument.activeElement) | ||
} | ||
|
||
return element | ||
} | ||
|
||
function onMessage(message, sender, respond) { | ||
if (sender.id != "textern@jlebon.com") | ||
return; | ||
if (message.type == "set_text") | ||
if (message.type == 'shortcut') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's call this message There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's already effectively namespaced by |
||
const activeElement = getActiveElement(); | ||
if (activeElement) | ||
registerText(activeElement); | ||
} | ||
else if (message.type == "set_text") | ||
setText(message.id, message.text); | ||
else { | ||
console.log(`Unknown message type: ${message.type}`); | ||
} | ||
} | ||
|
||
browser.runtime.onMessage.addListener(onMessage); | ||
|
||
var currentShortcut = undefined; | ||
function registerShortcut(force) { | ||
browser.storage.local.get({shortcut: "Ctrl+Shift+D"}).then(val => { | ||
if ((val.shortcut == currentShortcut) && !force) | ||
return; /* no change */ | ||
if (currentShortcut != undefined) | ||
shortcut.remove(currentShortcut); | ||
currentShortcut = val.shortcut; | ||
shortcut.add(currentShortcut, registerText); | ||
}); | ||
} | ||
|
||
registerShortcut(true); | ||
|
||
/* meh, we just re-apply the shortcut -- XXX: should check what actually changed */ | ||
browser.storage.onChanged.addListener(function(changes, areaName) { | ||
registerShortcut(false); | ||
}); | ||
|
||
/* we also want to make sure we re-register whenever the number of iframes changes */ | ||
var lastNumFrames = window.frames.length; | ||
const observer = new MutationObserver(function() { | ||
if (window.frames.length != lastNumFrames) { | ||
registerShortcut(true); | ||
lastNumFrames = window.frames.length; | ||
} | ||
}); | ||
observer.observe(document, {childList: true, subtree: true}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
"description": "Edit text in your favourite external editor!", | ||
"homepage_url": "https://github.com/jlebon/textern", | ||
"manifest_version": 2, | ||
"version": "0.8", | ||
"version": "0.9b1", | ||
|
||
"browser_specific_settings": { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was updating the manifest to use the shortcut APIs, it made sense to me to use the recommended keys for the whole document. |
||
"gecko": { | ||
|
@@ -17,15 +17,32 @@ | |
}, | ||
|
||
"content_scripts": [ | ||
{ | ||
"matches": ["<all_urls>"], | ||
"js": ["shortcut.js", "content.js"] | ||
} | ||
{ | ||
"matches": ["<all_urls>"], | ||
"js": [ | ||
"content.js" | ||
], | ||
"all_frames": true | ||
} | ||
], | ||
|
||
"commands": { | ||
"textern": { | ||
"suggested_key": { | ||
"default": "Shift+Alt+D" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about "Ctrl+Shift+F"? Looks like that's not taken by Firefox already, and is close to the current default. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wary of any specifying any shortcut with a Ctrl in it. They are regularly commandeered by both applications, and software running at the desktop level. There aren't many spare Ctrl + Shift + Letter keys available to begin with, so you're practically guaranteed to annoy some of your users. |
||
}, | ||
"description": "Edit externally" | ||
} | ||
}, | ||
|
||
"options_ui": { | ||
"page": "options.html" | ||
}, | ||
|
||
"permissions": ["notifications", "nativeMessaging", "storage"] | ||
"permissions": [ | ||
"tabs", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we reduce this permission to https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#activetab_permission only? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're welcome to try it. the |
||
"notifications", | ||
"nativeMessaging", | ||
"storage" | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like an unrelated change. Can you either remove it or add it as a separate commit with a commit message explaining it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When testing, and constantly reloading the add-on from the dev directory, the extension console did not work flawlessly. I added optional chaining in several places when some things did not appear to be working in the debugger.