mirror of
https://github.com/hensm/fx_cast.git
synced 2026-06-08 16:49:58 +00:00
Add lib/options module for typed/easier options storage access
This commit is contained in:
@@ -10,10 +10,13 @@ export interface Options {
|
||||
mirroringAppId: string;
|
||||
userAgentWhitelistEnabled: boolean;
|
||||
userAgentWhitelist: string[];
|
||||
|
||||
[key: string]: Options[keyof Options];
|
||||
}
|
||||
|
||||
const options: Options = {
|
||||
mediaEnabled: true
|
||||
bridgeApplicationName: APPLICATION_NAME
|
||||
, mediaEnabled: true
|
||||
, mediaSyncElement: false
|
||||
, mediaStopOnUnload: false
|
||||
, localMediaEnabled: true
|
||||
|
||||
54
ext/src/lib/options.ts
Normal file
54
ext/src/lib/options.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
"use strict";
|
||||
|
||||
import { Options } from "../defaultOptions";
|
||||
|
||||
|
||||
/**
|
||||
* Fetches `options` key from storage and returns it as
|
||||
* Options interface type.
|
||||
*/
|
||||
async function getAll (): Promise<Options> {
|
||||
const { options }: { options: Options } =
|
||||
await browser.storage.sync.get("options");
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes Options object and sets to `options` storage key.
|
||||
* Returns storage promise.
|
||||
*/
|
||||
async function setAll (options: Options): Promise<void> {
|
||||
return browser.storage.sync.set({ options });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets specific option from storage and returns it as its
|
||||
* type from Options interface type.
|
||||
*/
|
||||
async function get<T extends keyof Options> (name: T): Promise<Options[T]> {
|
||||
const options = await getAll();
|
||||
|
||||
if (options.hasOwnProperty(name)) {
|
||||
return options[name];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets specific option to storage. Returns storage
|
||||
* promise.
|
||||
*/
|
||||
async function set<T extends keyof Options> (
|
||||
name: T
|
||||
, value: Options[T]): Promise<void> {
|
||||
|
||||
const options = await getAll();
|
||||
options[name] = value;
|
||||
return setAll(options);
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
get, getAll
|
||||
, set, setAll
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import semver from "semver";
|
||||
import defaultOptions, { Options } from "./defaultOptions";
|
||||
import getBridgeInfo from "./lib/getBridgeInfo";
|
||||
import messageRouter from "./lib/messageRouter";
|
||||
import options from "./lib/options";
|
||||
import nativeMessaging from "./lib/nativeMessaging";
|
||||
|
||||
import { getChromeUserAgent } from "./lib/userAgents";
|
||||
@@ -29,17 +30,13 @@ browser.runtime.onInstalled.addListener(async details => {
|
||||
switch (details.reason) {
|
||||
// Set default options
|
||||
case "install": {
|
||||
await browser.storage.sync.set({
|
||||
options: defaultOptions
|
||||
});
|
||||
await options.setAll(defaultOptions);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set newly added options
|
||||
case "update": {
|
||||
const { options: existingOptions }
|
||||
= await browser.storage.sync.get("options");
|
||||
|
||||
const existingOptions = await options.getAll();
|
||||
const newOptions: Partial<Options> = {};
|
||||
|
||||
// Find options not already in storage
|
||||
@@ -50,11 +47,9 @@ browser.runtime.onInstalled.addListener(async details => {
|
||||
}
|
||||
|
||||
// Update storage with default values of new options
|
||||
await browser.storage.sync.set({
|
||||
options: {
|
||||
...existingOptions
|
||||
, ...newOptions
|
||||
}
|
||||
options.setAll({
|
||||
...existingOptions
|
||||
, ...newOptions
|
||||
});
|
||||
|
||||
break;
|
||||
@@ -87,17 +82,17 @@ const mediaCastTargetUrlPatterns = new Set([
|
||||
const LOCAL_MEDIA_URL_PATTERN = "file://*/*";
|
||||
|
||||
async function createMenus () {
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
const opts = await options.getAll();
|
||||
|
||||
/**
|
||||
* If options aren't set or menus have already been
|
||||
* created, return.
|
||||
*/
|
||||
if (!options || mirrorCastMenuId || mediaCastMenuId) {
|
||||
if (!opts || mirrorCastMenuId || mediaCastMenuId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.localMediaEnabled) {
|
||||
if (opts.localMediaEnabled) {
|
||||
mediaCastTargetUrlPatterns.add(LOCAL_MEDIA_URL_PATTERN);
|
||||
}
|
||||
|
||||
@@ -107,7 +102,7 @@ async function createMenus () {
|
||||
, id: "contextCastMedia"
|
||||
, targetUrlPatterns: Array.from(mediaCastTargetUrlPatterns)
|
||||
, title: _("contextCast")
|
||||
, visible: options.mediaEnabled
|
||||
, visible: opts.mediaEnabled
|
||||
});
|
||||
|
||||
// Screen/Tab mirroring "Cast..." context menu item
|
||||
@@ -115,7 +110,7 @@ async function createMenus () {
|
||||
contexts: [ "browser_action", "page", "tools_menu" ]
|
||||
, id: "contextCast"
|
||||
, title: _("contextCast")
|
||||
, visible: options.mirroringEnabled
|
||||
, visible: opts.mirroringEnabled
|
||||
|
||||
// Mirroring doesn't work from local files
|
||||
, documentUrlPatterns: [
|
||||
@@ -317,7 +312,6 @@ let currentUAString: string;
|
||||
async function onBeforeSendHeaders (
|
||||
details: { requestHeaders?: browser.webRequest.HttpHeaders }) {
|
||||
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
const { os } = await browser.runtime.getPlatformInfo();
|
||||
|
||||
// Create Chrome UA from platform info on first run
|
||||
@@ -353,10 +347,10 @@ async function onBeforeSendHeaders (
|
||||
* Updates any extension state based on options changes.
|
||||
*/
|
||||
async function onOptionsUpdated (alteredOptions?: Array<(keyof Options)>) {
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
const opts = await options.getAll();
|
||||
|
||||
// If options aren't set yet, return
|
||||
if (!options) {
|
||||
if (!opts) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -367,8 +361,8 @@ async function onOptionsUpdated (alteredOptions?: Array<(keyof Options)>) {
|
||||
function register_userAgentWhitelist () {
|
||||
browser.webRequest.onBeforeSendHeaders.addListener(
|
||||
onBeforeSendHeaders
|
||||
, { urls: options.userAgentWhitelistEnabled
|
||||
? options.userAgentWhitelist
|
||||
, { urls: opts.userAgentWhitelistEnabled
|
||||
? opts.userAgentWhitelist
|
||||
: [] }
|
||||
, [ "blocking", "requestHeaders" ]);
|
||||
}
|
||||
@@ -394,18 +388,18 @@ async function onOptionsUpdated (alteredOptions?: Array<(keyof Options)>) {
|
||||
|
||||
if (alteredOptions.includes("mirroringEnabled")) {
|
||||
browser.menus.update(mirrorCastMenuId, {
|
||||
visible: options.mirroringEnabled
|
||||
visible: opts.mirroringEnabled
|
||||
});
|
||||
}
|
||||
|
||||
if (alteredOptions.includes("mediaEnabled")) {
|
||||
browser.menus.update(mediaCastMenuId, {
|
||||
visible: options.mediaEnabled
|
||||
visible: opts.mediaEnabled
|
||||
});
|
||||
}
|
||||
|
||||
if (alteredOptions.includes("localMediaEnabled")) {
|
||||
if (options.localMediaEnabled) {
|
||||
if (opts.localMediaEnabled) {
|
||||
mediaCastTargetUrlPatterns.add(LOCAL_MEDIA_URL_PATTERN);
|
||||
} else {
|
||||
mediaCastTargetUrlPatterns.delete(LOCAL_MEDIA_URL_PATTERN);
|
||||
@@ -448,7 +442,7 @@ browser.menus.onClicked.addListener(async (info, tab) => {
|
||||
|| info.menuItemId === mediaCastMenuId) {
|
||||
|
||||
const { frameId } = info;
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
const mirroringAppId = await options.get("mirroringAppId");
|
||||
|
||||
// Load cast setup script
|
||||
await browser.tabs.executeScript(tab.id, {
|
||||
@@ -466,7 +460,7 @@ browser.menus.onClicked.addListener(async (info, tab) => {
|
||||
var selectedMedia = ${info.pageUrl
|
||||
? ReceiverSelectorMediaType.Tab
|
||||
: ReceiverSelectorMediaType.Screen};
|
||||
var FX_CAST_RECEIVER_APP_ID = "${options.mirroringAppId}";
|
||||
var FX_CAST_RECEIVER_APP_ID = "${mirroringAppId}";
|
||||
`
|
||||
, frameId
|
||||
});
|
||||
@@ -513,16 +507,13 @@ browser.menus.onClicked.addListener(async (info, tab) => {
|
||||
|
||||
if (info.parentMenuItemId === whitelistMenuId) {
|
||||
const matchPattern = whitelistMenuMap.get(info.menuItemId);
|
||||
const options: Options =
|
||||
(await browser.storage.sync.get("options")).options;
|
||||
const userAgentWhitelist = await options.get("userAgentWhitelist");
|
||||
|
||||
// Add to whitelist
|
||||
options.userAgentWhitelist.push(matchPattern);
|
||||
userAgentWhitelist.push(matchPattern);
|
||||
|
||||
// Update options
|
||||
await browser.storage.sync.set({
|
||||
options
|
||||
});
|
||||
await options.set("userAgentWhitelist", userAgentWhitelist)
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import Bridge from "./Bridge";
|
||||
import EditableList from "./EditableList";
|
||||
|
||||
import getBridgeInfo, { BridgeInfo } from "../../lib/getBridgeInfo";
|
||||
import options from "../../lib/options";
|
||||
import { REMOTE_MATCH_PATTERN_REGEX } from "../../lib/utils";
|
||||
|
||||
|
||||
@@ -77,11 +78,9 @@ class OptionsApp extends Component<{}, OptionsAppState> {
|
||||
}
|
||||
|
||||
public async componentDidMount () {
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
|
||||
this.setState({
|
||||
hasLoaded: true
|
||||
, options
|
||||
, options: await options.getAll()
|
||||
});
|
||||
|
||||
const bridgeInfo = await getBridgeInfo();
|
||||
@@ -259,14 +258,6 @@ class OptionsApp extends Component<{}, OptionsAppState> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stored option values to current state
|
||||
*/
|
||||
private setStorage () {
|
||||
return browser.storage.sync.set({
|
||||
options: this.state.options
|
||||
});
|
||||
}
|
||||
|
||||
private handleReset () {
|
||||
this.setState({
|
||||
@@ -280,15 +271,12 @@ class OptionsApp extends Component<{}, OptionsAppState> {
|
||||
this.form.reportValidity();
|
||||
|
||||
try {
|
||||
const { options: oldOptions }
|
||||
= await browser.storage.sync.get("options");
|
||||
await this.setStorage();
|
||||
const { options } = await browser.storage.sync.get("options");
|
||||
const oldOpts = await options.getAll();
|
||||
await options.setAll(this.state.options);
|
||||
|
||||
const alteredOptions = [];
|
||||
|
||||
for (const [ key, val ] of Object.entries(options)) {
|
||||
const oldVal = oldOptions[key];
|
||||
for (const [ key, val ] of Object.entries(this.state.options)) {
|
||||
const oldVal = oldOpts[key];
|
||||
if (oldVal !== val) {
|
||||
alteredOptions.push(key);
|
||||
}
|
||||
@@ -325,16 +313,16 @@ class OptionsApp extends Component<{}, OptionsAppState> {
|
||||
private handleInputChange (ev: React.ChangeEvent<HTMLInputElement>) {
|
||||
const { target } = ev;
|
||||
|
||||
this.setState(({ options }) => {
|
||||
options[target.name as keyof Options] = getInputValue(target);
|
||||
return { options };
|
||||
this.setState(currentState => {
|
||||
currentState.options[target.name] = getInputValue(target);
|
||||
return currentState;
|
||||
});
|
||||
}
|
||||
|
||||
private handleWhitelistChange (whitelist: string[]) {
|
||||
this.setState(({ options }) => {
|
||||
options.userAgentWhitelist = whitelist;
|
||||
return { options };
|
||||
this.setState(currentState => {
|
||||
currentState.options.userAgentWhitelist = whitelist;
|
||||
return currentState;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user