user browser polyfill with Promise for options access
This commit is contained in:
parent
8dc554fd61
commit
f906728bf8
|
@ -5,6 +5,7 @@
|
|||
|
||||
[libs]
|
||||
node_modules/flow-interfaces-chrome/interfaces/
|
||||
src/js/browser_types.js
|
||||
|
||||
[lints]
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
"style-loader": "^3.3.1",
|
||||
"web-ext": "^7.4.0",
|
||||
"web-ext-submit": "^7.4.0",
|
||||
"webextension-polyfill": "^0.10.0",
|
||||
"webpack": "^5.75.0",
|
||||
"webpack-cli": "^5.0.1",
|
||||
"webpack-dev-server": "^4.11.1",
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/* @flow */
|
||||
// TODO do I really need to annotate all files with @flow??
|
||||
|
||||
|
||||
import {COMMAND_CAPTURE_SIMPLE, METHOD_CAPTURE_WITH_EXTRAS, showNotification} from './common'
|
||||
import {get_options} from './options'
|
||||
import {getOptions} from './options'
|
||||
import type {Options} from './options'
|
||||
|
||||
|
||||
|
@ -87,7 +88,7 @@ function capture(comment: ?string = null, tag_str: ?string = null) {
|
|||
// TODO await properly and handle errors
|
||||
const has_scripting = 'scripting' in chrome
|
||||
|
||||
get_options(opts => {
|
||||
getOptions().then(opts => {
|
||||
if (has_scripting) {
|
||||
// $FlowFixMe
|
||||
chrome.scripting.executeScript({
|
||||
|
|
25
extension/src/js/browser_types.js
Normal file
25
extension/src/js/browser_types.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* @flow */
|
||||
|
||||
/*
|
||||
* Based on https://github.com/Shraymonks/flow-interfaces-chrome
|
||||
* not sure if browser polyfill has flow types??
|
||||
* https://github.com/mozilla/webextension-polyfill/issues/421
|
||||
*/
|
||||
|
||||
|
||||
type browser$StorageArea = {
|
||||
get: (keys: string | Array<string> | Object | null) => Promise<Object>,
|
||||
set: (items: Object) => Promise<void>,
|
||||
}
|
||||
|
||||
|
||||
type browser$storage = {
|
||||
local: browser$StorageArea,
|
||||
managed: browser$StorageArea,
|
||||
sync: browser$StorageArea,
|
||||
}
|
||||
|
||||
|
||||
declare var browser: {
|
||||
storage: browser$storage,
|
||||
}
|
|
@ -6,31 +6,23 @@ export type Options = {
|
|||
notification: boolean;
|
||||
}
|
||||
|
||||
function default_options(): Options {
|
||||
|
||||
function defaultOptions(): Options {
|
||||
return {
|
||||
endpoint: "http://localhost:12212/capture",
|
||||
default_tags: "grasp",
|
||||
notification: true,
|
||||
};
|
||||
}
|
||||
|
||||
export function get_options(cb: (Options) => void) {
|
||||
chrome.storage.local.get(null, res => {
|
||||
res = {...default_options(), ...res};
|
||||
cb(res);
|
||||
});
|
||||
}
|
||||
|
||||
export function set_options(opts: Options, cb: () => void) {
|
||||
console.log('Saving %s', JSON.stringify(opts));
|
||||
chrome.storage.local.set(opts, cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function getOptions(): Promise<Options> {
|
||||
return new Promise((resolve) => {
|
||||
// TODO FIXME reject?
|
||||
get_options(resolve);
|
||||
});
|
||||
export async function getOptions(): Promise<Options> {
|
||||
const res = await browser.storage.local.get(null)
|
||||
return {...defaultOptions(), ...res}
|
||||
}
|
||||
|
||||
|
||||
export async function setOptions(opts: Options): Promise<void> {
|
||||
console.log('Saving %o', opts)
|
||||
await browser.storage.local.set(opts)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
/* @flow */
|
||||
import {get_options, set_options} from './options';
|
||||
import {ensurePermissions, hasPermissions} from './permissions';
|
||||
import {getOptions, setOptions} from './options'
|
||||
import {ensurePermissions, hasPermissions} from './permissions'
|
||||
|
||||
|
||||
const ENDPOINT_ID = 'endpoint_id';
|
||||
const HAS_PERMISSION_ID = 'has_permission_id';
|
||||
const NOTIFICATION_ID = 'notification_id';
|
||||
const DEFAULT_TAGS_ID = 'default_tags_id';
|
||||
// TODO specify capture path here?
|
||||
|
||||
const SAVE_ID = 'save_id';
|
||||
|
||||
|
||||
function getEndpoint(): HTMLInputElement {
|
||||
return ((document.getElementById(ENDPOINT_ID): any): HTMLInputElement);
|
||||
}
|
||||
|
@ -31,47 +31,50 @@ function getHasPermission(): HTMLElement {
|
|||
return ((document.getElementById(HAS_PERMISSION_ID): any): HTMLElement);
|
||||
}
|
||||
|
||||
|
||||
// ugh. needs a better name..
|
||||
function refreshPermissionValidation(endpoint: string) {
|
||||
hasPermissions(endpoint).then(has => {
|
||||
const pstyle = getHasPermission().style;
|
||||
if (has) {
|
||||
console.debug('Got permisssions, nothing to worry about.');
|
||||
pstyle.display = 'none';
|
||||
return;
|
||||
}
|
||||
console.debug('Whoops, no permissions to access %s', endpoint);
|
||||
// TODO maybe just show button? but then it would need to be reactive..
|
||||
pstyle.display = 'block';
|
||||
});
|
||||
async function refreshPermissionValidation(endpoint: string) {
|
||||
const has = await hasPermissions(endpoint)
|
||||
const pstyle = getHasPermission().style
|
||||
if (has) {
|
||||
console.debug('Got permisssions, nothing to worry about.')
|
||||
pstyle.display = 'none'
|
||||
return
|
||||
}
|
||||
console.debug('Whoops, no permissions to access %s', endpoint)
|
||||
// TODO maybe just show button? but then it would need to be reactive..
|
||||
pstyle.display = 'block'
|
||||
}
|
||||
|
||||
function restoreOptions() {
|
||||
getSaveButton().addEventListener('click', saveOptions);
|
||||
get_options(opts => {
|
||||
const ep = opts.endpoint;
|
||||
getEndpoint().value = ep;
|
||||
getDefaultTags().value = opts.default_tags;
|
||||
getEnableNotification().checked = opts.notification;
|
||||
refreshPermissionValidation(ep);
|
||||
});
|
||||
|
||||
async function restoreOptions() {
|
||||
getSaveButton().addEventListener('click', saveOptions)
|
||||
|
||||
const opts = await getOptions()
|
||||
getEndpoint().value = opts.endpoint
|
||||
getDefaultTags().value = opts.default_tags
|
||||
getEnableNotification().checked = opts.notification
|
||||
await refreshPermissionValidation(opts.endpoint)
|
||||
}
|
||||
|
||||
function saveOptions() {
|
||||
|
||||
async function saveOptions() {
|
||||
// TODO could also check for permissions and display message?
|
||||
|
||||
const endpoint = getEndpoint().value;
|
||||
ensurePermissions(endpoint).finally(() => {
|
||||
refreshPermissionValidation(endpoint);
|
||||
});
|
||||
const endpoint = getEndpoint().value
|
||||
await ensurePermissions(endpoint)
|
||||
refreshPermissionValidation(endpoint)
|
||||
|
||||
const opts = {
|
||||
endpoint: endpoint,
|
||||
default_tags: getDefaultTags().value,
|
||||
notification: getEnableNotification().checked,
|
||||
};
|
||||
set_options(opts, () => { alert('Saved!'); });
|
||||
}
|
||||
await setOptions(opts)
|
||||
|
||||
// hmm seems that regular alert() doesn't work in chrome anymore
|
||||
chrome.extension.getBackgroundPage().alert('Saved!')
|
||||
}
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', restoreOptions);
|
||||
document.addEventListener('DOMContentLoaded', restoreOptions)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/* @flow */
|
||||
|
||||
import {METHOD_CAPTURE_WITH_EXTRAS} from './common';
|
||||
import {get_options} from './options';
|
||||
|
||||
import {METHOD_CAPTURE_WITH_EXTRAS} from './common'
|
||||
import {getOptions} from './options'
|
||||
|
||||
// TODO template it in html too?
|
||||
const BUTTON_ID = 'button_id';
|
||||
|
@ -73,14 +74,15 @@ function getUiState(): State {
|
|||
}
|
||||
|
||||
|
||||
function restoreState(state: ?State) {
|
||||
async function restoreState(state: ?State) {
|
||||
window.justSubmitted = false
|
||||
if (state == null) {
|
||||
// comment just relies on default
|
||||
get_options(opts => {getTags().value = opts.default_tags;});
|
||||
const opts = await getOptions()
|
||||
getTags().value = opts.default_tags
|
||||
} else {
|
||||
getComment().value = state.comment;
|
||||
getTags().value = state.tag_str;
|
||||
getComment().value = state.comment
|
||||
getTags().value = state.tag_str
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
"name": "<webpack managed>",
|
||||
"version": "<webpack managed>",
|
||||
"background": {
|
||||
"scripts": ["background.js"],
|
||||
"scripts": [
|
||||
"browser-polyfill.js",
|
||||
"background.js"
|
||||
],
|
||||
"persistent": false
|
||||
},
|
||||
"options_ui": {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript" src="browser-polyfill.js"/></script>
|
||||
<script type="text/javascript" src="options_page.js"/></script>
|
||||
<style>
|
||||
input:invalid {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script type="text/javascript" src="browser-polyfill.js"></script>
|
||||
<script type="text/javascript" src="popup.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -166,6 +166,7 @@ const options = {
|
|||
patterns: [
|
||||
{ context: 'src', from: '**/*.html' },
|
||||
{ context: 'src', from: '**/*.png' },
|
||||
{ from: 'node_modules/webextension-polyfill/dist/browser-polyfill.js'},
|
||||
]
|
||||
}),
|
||||
new WebpackExtensionManifestPlugin({
|
||||
|
|
Loading…
Reference in a new issue