Skip to content

Commit c047e59

Browse files
committed
Use the built-in keyboard commands system
Registration and conflict resolution is simplified. Change default to one that's unused by Firefox itself. Simplifies code but requires an extra permission to find current tab.
1 parent 41fe3de commit c047e59

File tree

6 files changed

+64
-286
lines changed

6 files changed

+64
-286
lines changed

webex/background.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function assertNoResponse(response) {
1919
}
2020

2121
function notifyError(error) {
22-
browser.notifications.create({
22+
browser.notifications?.create({
2323
type: "basic",
2424
title: "Textern",
2525
message: "Error: " + error + "."
@@ -126,3 +126,16 @@ function onMessage(message, sender, respond) {
126126
}
127127

128128
browser.runtime.onMessage.addListener(onMessage);
129+
130+
browser.commands.onCommand.addListener(function(command) {
131+
if (command === 'textern') {
132+
browser.tabs.query({
133+
currentWindow: true,
134+
active: true
135+
}).then(function(tabs) {
136+
if (tabs?.length && tabs[0].id != browser.tabs.TAB_ID_NONE) {
137+
browser.tabs.sendMessage(tabs[0].id, {type: 'shortcut'}).then(assertNoResponse, logError);
138+
}
139+
});
140+
}
141+
});

webex/content.js

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function assertNoResponse(response) {
1717
}
1818

1919
function notifyError(error) {
20-
browser.notifications.create({
20+
browser.notifications?.create({
2121
type: "basic",
2222
title: "Textern",
2323
message: "Error: " + error + "."
@@ -91,8 +91,7 @@ function slackSetText(e, text) {
9191
}
9292
}
9393

94-
function registerText(event) {
95-
var e = event.target;
94+
function registerText(e) {
9695
if (e.nodeName == "TEXTAREA") {
9796
var id = watchElement(e);
9897
/* don't use href directly to not bring in e.g. url params */
@@ -171,43 +170,37 @@ function setText(id, text) {
171170
fadeBackground(e);
172171
}
173172

173+
function getActiveElement(element = document.activeElement) {
174+
if (element.nodeName === 'IFRAME' || element.nodeName === 'FRAME')
175+
return null; // skip to allow child documents to handle shortcut
176+
177+
const shadowRoot = element.shadowRoot
178+
const contentDocument = element.contentDocument
179+
180+
if (shadowRoot && shadowRoot.activeElement) {
181+
return getActiveElement(shadowRoot.activeElement)
182+
}
183+
184+
if (contentDocument && contentDocument.activeElement) {
185+
return getActiveElement(contentDocument.activeElement)
186+
}
187+
188+
return element
189+
}
190+
174191
function onMessage(message, sender, respond) {
175192
if (sender.id != "[email protected]")
176193
return;
177-
if (message.type == "set_text")
194+
if (message.type == 'shortcut') {
195+
const activeElement = getActiveElement();
196+
if (activeElement)
197+
registerText(activeElement);
198+
}
199+
else if (message.type == "set_text")
178200
setText(message.id, message.text);
179201
else {
180202
console.log(`Unknown message type: ${message.type}`);
181203
}
182204
}
183205

184206
browser.runtime.onMessage.addListener(onMessage);
185-
186-
var currentShortcut = undefined;
187-
function registerShortcut(force) {
188-
browser.storage.local.get({shortcut: "Ctrl+Shift+D"}).then(val => {
189-
if ((val.shortcut == currentShortcut) && !force)
190-
return; /* no change */
191-
if (currentShortcut != undefined)
192-
shortcut.remove(currentShortcut);
193-
currentShortcut = val.shortcut;
194-
shortcut.add(currentShortcut, registerText);
195-
});
196-
}
197-
198-
registerShortcut(true);
199-
200-
/* meh, we just re-apply the shortcut -- XXX: should check what actually changed */
201-
browser.storage.onChanged.addListener(function(changes, areaName) {
202-
registerShortcut(false);
203-
});
204-
205-
/* we also want to make sure we re-register whenever the number of iframes changes */
206-
var lastNumFrames = window.frames.length;
207-
const observer = new MutationObserver(function() {
208-
if (window.frames.length != lastNumFrames) {
209-
registerShortcut(true);
210-
lastNumFrames = window.frames.length;
211-
}
212-
});
213-
observer.observe(document, {childList: true, subtree: true});

webex/manifest.json

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Edit text in your favourite external editor!",
44
"homepage_url": "https://github.com/jlebon/textern",
55
"manifest_version": 2,
6-
"version": "0.8",
6+
"version": "0.9b1",
77

88
"browser_specific_settings": {
99
"gecko": {
@@ -17,15 +17,32 @@
1717
},
1818

1919
"content_scripts": [
20-
{
21-
"matches": ["<all_urls>"],
22-
"js": ["shortcut.js", "content.js"]
23-
}
20+
{
21+
"matches": ["<all_urls>"],
22+
"js": [
23+
"content.js"
24+
],
25+
"all_frames": true
26+
}
2427
],
2528

29+
"commands": {
30+
"textern": {
31+
"suggested_key": {
32+
"default": "Shift+Alt+D"
33+
},
34+
"description": "Edit externally"
35+
}
36+
},
37+
2638
"options_ui": {
2739
"page": "options.html"
2840
},
2941

30-
"permissions": ["notifications", "nativeMessaging", "storage"]
42+
"permissions": [
43+
"tabs",
44+
"notifications",
45+
"nativeMessaging",
46+
"storage"
47+
]
3148
}

webex/options.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@
1313
<input type="text" id="editor" required=true
1414
pattern='\[ *"[^"]*"(, *"[^"]*")* *\]'
1515
title='Must be in the form: ["executable", "arg", "arg", ...]'>
16-
<label for="shortcut">Shortcut</label>
17-
<input type="text" id="shortcut" required=true>
1816
<label for="extension">Document extension</label>
1917
<input type="text" id="extension" required=true pattern="[.a-zA-Z0-9_-]+"
2018
title='Must be an alphanumerical string (excluding leading dot)'>
2119
<label for="backupdir">Backup files to directory (experimental)</label>
2220
<input type="text" id="backupdir">
2321
<button type="submit">Save</button><span id="saved"></span>
2422
</form>
23+
<p>Shortcut can be configured on the Manage Extension Shortcuts settings page.</p>
2524
<script src="options.js" charset="utf-8"></script>
2625
</body>
2726
</html>

webex/options.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ function saveOptions(e) {
1414
e.preventDefault();
1515
browser.storage.local.set({
1616
editor: document.querySelector("#editor").value,
17-
shortcut: document.querySelector("#shortcut").value,
1817
extension: document.querySelector("#extension").value,
1918
backupdir: document.querySelector("#backupdir").value
2019
});
@@ -32,10 +31,6 @@ function restoreOptions() {
3231
result.editor || "[\"gedit\", \"+%l:%c\"]";
3332
}, onError);
3433

35-
browser.storage.local.get("shortcut").then(result => {
36-
document.querySelector("#shortcut").value = result.shortcut || "Ctrl+Shift+D";
37-
}, onError);
38-
3934
browser.storage.local.get("extension").then(result => {
4035
document.querySelector("#extension").value = result.extension || "txt";
4136
}, onError);

0 commit comments

Comments
 (0)