Skip to content

Commit 47deeb4

Browse files
authored
Add option to open in new tab or window (#105)
1 parent 6f3a55e commit 47deeb4

File tree

12 files changed

+167
-8
lines changed

12 files changed

+167
-8
lines changed

package-lock.json

Lines changed: 63 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"devDependencies": {
5353
"@rollup/plugin-commonjs": "^24.0.1",
5454
"@rollup/plugin-node-resolve": "^15.0.1",
55+
"@types/chrome": "^0.0.234",
5556
"eslint": "^8.35.0",
5657
"eslint-config-prettier": "^8.6.0",
5758
"eslint-config-xo": "^0.43.1",

rollup.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const config = {
1010
input: {
1111
main: 'source/main.js',
1212
'options/options': 'source/options/options.js',
13+
background: 'source/background.js',
1314
},
1415
output: {
1516
sourcemap: !production,

source/App.svelte

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@
2323
showExtras = true;
2424
}
2525
26-
if (width.trim()) {
27-
const cleanWidth = /[a-z]/i.test(width) ? width : width.trim() + 'px';
28-
document.body.style.width = cleanWidth;
26+
if (new URLSearchParams(location.search).get('type') !== 'window') {
27+
document.body.style.width = (width || 400) + 'px';
2928
}
3029
});
3130
$: {

source/background.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import optionsStorage, {matchOptions} from './options-storage';
2+
3+
// TODO: https://github.com/fregante/webext-options-sync/issues/63
4+
chrome.storage.onChanged.addListener(async (changes, areaName) => {
5+
if (areaName === 'sync' && 'options' in changes) {
6+
matchOptions();
7+
}
8+
});
9+
10+
// Must be registered on the top level
11+
chrome.action.onClicked.addListener(async () => {
12+
let {position, width} = await optionsStorage.getAll();
13+
if (position === 'popup') {
14+
return;
15+
}
16+
17+
if (position === 'tab') {
18+
chrome.tabs.create({url: chrome.runtime.getURL('index.html?type=tab')});
19+
return;
20+
}
21+
22+
if (position === 'window') {
23+
width = width === '' ? 400 : Number.parseInt(width, 10); // Must be an integer
24+
const height = 600;
25+
const currentWindow = await chrome.windows.getCurrent();
26+
await chrome.windows.create({
27+
type: 'popup',
28+
url: chrome.runtime.getURL('index.html?type=window'),
29+
width,
30+
height,
31+
top: currentWindow.top + Math.round((currentWindow.height - height) / 2),
32+
left: currentWindow.left + Math.round((currentWindow.width - width) / 2),
33+
});
34+
}
35+
});
36+
37+
matchOptions();

source/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
<!DOCTYPE html>
2-
<title>Extension Manager</title>
2+
<title>One Click Extensions Manager</title>
33
<link href="style.css" rel="stylesheet" />
44
<script type="module" src="main.js"></script>

source/lib/fit-window.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
function fitWindowToContentHeight() {
2+
// Sigh, the innerHeight is wildly off while loading
3+
const uiHeight = Math.min(50, window.outerHeight - window.innerHeight);
4+
const height = document.body.scrollHeight + uiHeight;
5+
window.resizeTo(window.outerWidth, height);
6+
}
7+
8+
export default function fitWindow() {
9+
new ResizeObserver(fitWindowToContentHeight).observe(document.body);
10+
}

source/main.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import App from './App.svelte';
2+
import fitWindow from './lib/fit-window';
23

34
new App({
45
target: document.body,
56
});
67

7-
// Move to App.svelte once this is supported: https://github.com/sveltejs/svelte/issues/3105
8-
document.body.dataset.type = new URLSearchParams(location.search).get('type');
8+
const type = new URLSearchParams(location.search).get('type');
9+
document.body.dataset.type = type;
10+
if (type === 'window') {
11+
fitWindow();
12+
}

source/manifest.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
"options_ui": {
1919
"page": "options/options.html"
2020
},
21+
"background": {
22+
"service_worker": "background.js",
23+
"type": "module"
24+
},
2125
"commands": {
2226
"_execute_action": {}
2327
}

source/options-storage.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,31 @@ import OptionsSync from 'webext-options-sync';
22

33
const optionsStorage = new OptionsSync({
44
defaults: {
5+
position: 'popup',
56
showButtons: 'on-demand', // Or 'always'
67
width: '',
78
},
9+
migrations: [
10+
options => {
11+
let {width} = options;
12+
// Ignore if unset
13+
if (!width) {
14+
return;
15+
}
16+
17+
// Parse them and clamp the value
18+
width = Math.min(Math.max(250, Number.parseInt(width, 10)), 1000);
19+
20+
options.width = Number.isNaN(width) ? '' : width;
21+
},
22+
],
823
});
924

1025
export default optionsStorage;
26+
27+
const defaultPopup = chrome.runtime.getManifest().action.default_popup;
28+
29+
export async function matchOptions() {
30+
const {position} = await optionsStorage.getAll();
31+
chrome.action.setPopup({popup: position === 'popup' ? defaultPopup : ''});
32+
}

0 commit comments

Comments
 (0)