More work

This commit is contained in:
Nathan Bierema 2021-06-20 16:34:04 -04:00
parent 696a669bd0
commit 084f9b9429
33 changed files with 302 additions and 185 deletions

View File

@ -1,6 +1,11 @@
import mapValues from 'lodash/mapValues'; import mapValues from 'lodash/mapValues';
export const FilterState = { export type FilterStateValue =
| 'DO_NOT_FILTER'
| 'BLACKLIST_SPECIFIC'
| 'WHITELIST_SPECIFIC';
export const FilterState: { [K in FilterStateValue]: FilterStateValue } = {
DO_NOT_FILTER: 'DO_NOT_FILTER', DO_NOT_FILTER: 'DO_NOT_FILTER',
BLACKLIST_SPECIFIC: 'BLACKLIST_SPECIFIC', BLACKLIST_SPECIFIC: 'BLACKLIST_SPECIFIC',
WHITELIST_SPECIFIC: 'WHITELIST_SPECIFIC', WHITELIST_SPECIFIC: 'WHITELIST_SPECIFIC',

View File

@ -1,14 +1,22 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect, ResolveThunks } from 'react-redux';
import { Container, Notification } from 'devui'; import { Container, Notification } from 'devui';
import { getActiveInstance } from '@redux-devtools/app/lib/reducers/instances'; import { getActiveInstance } from '@redux-devtools/app/lib/reducers/instances';
import Settings from '@redux-devtools/app/lib/components/Settings'; import Settings from '@redux-devtools/app/lib/components/Settings';
import Actions from '@redux-devtools/app/lib/containers/Actions'; import Actions from '@redux-devtools/app/lib/containers/Actions';
import Header from '@redux-devtools/app/lib/components/Header'; import Header from '@redux-devtools/app/lib/components/Header';
import { clearNotification } from '@redux-devtools/app/lib/actions'; import { clearNotification } from '@redux-devtools/app/lib/actions';
import { StoreState } from '@redux-devtools/app/lib/reducers';
class App extends Component { type StateProps = ReturnType<typeof mapStateToProps>;
openWindow = (position) => { type DispatchProps = ResolveThunks<typeof actionCreators>;
interface OwnProps {
readonly position: string;
}
type Props = StateProps & DispatchProps & OwnProps;
class App extends Component<Props> {
openWindow = (position: string) => {
chrome.runtime.sendMessage({ type: 'OPEN', position }); chrome.runtime.sendMessage({ type: 'OPEN', position });
}; };
openOptionsPage = () => { openOptionsPage = () => {
@ -62,7 +70,7 @@ class App extends Component {
} }
} }
function mapStateToProps(state) { function mapStateToProps(state: StoreState) {
const instances = state.instances; const instances = state.instances;
const id = getActiveInstance(instances); const id = getActiveInstance(instances);
return { return {

View File

@ -1,9 +1,16 @@
import { Dispatch, Store } from 'redux';
import { import {
SELECT_INSTANCE, SELECT_INSTANCE,
UPDATE_STATE, UPDATE_STATE,
} from '@redux-devtools/app/lib/constants/actionTypes'; } from '@redux-devtools/app/lib/constants/actionTypes';
import { StoreAction } from '@redux-devtools/app/lib/actions';
import { StoreState } from '@redux-devtools/app/lib/reducers';
function selectInstance(tabId, store, next) { function selectInstance(
tabId: number,
store: Store<StoreState, StoreAction>,
next: Dispatch<StoreAction>
) {
const instances = store.getState().instances; const instances = store.getState().instances;
if (instances.current === 'default') return; if (instances.current === 'default') return;
const connections = instances.connections[tabId]; const connections = instances.connections[tabId];
@ -12,7 +19,7 @@ function selectInstance(tabId, store, next) {
} }
} }
function getCurrentTabId(next) { function getCurrentTabId(next: (tabId: number) => void) {
chrome.tabs.query( chrome.tabs.query(
{ {
active: true, active: true,
@ -21,13 +28,13 @@ function getCurrentTabId(next) {
(tabs) => { (tabs) => {
const tab = tabs[0]; const tab = tabs[0];
if (!tab) return; if (!tab) return;
next(tab.id); next(tab.id!);
} }
); );
} }
export default function popupSelector(store) { export default function popupSelector(store: Store<StoreState, StoreAction>) {
return (next) => (action) => { return (next: Dispatch<StoreAction>) => (action: StoreAction) => {
const result = next(action); const result = next(action);
if (action.type === UPDATE_STATE) { if (action.type === UPDATE_STATE) {
if (chrome.devtools && chrome.devtools.inspectedWindow) { if (chrome.devtools && chrome.devtools.inspectedWindow) {

View File

@ -1,31 +0,0 @@
import {
LIFTED_ACTION,
UPDATE_STATE,
SELECT_INSTANCE,
} from '@redux-devtools/app/lib/constants/actionTypes';
import { getActiveInstance } from '@redux-devtools/app/lib/reducers/instances';
function panelDispatcher(bgConnection) {
let autoselected = false;
const tabId = chrome.devtools.inspectedWindow.tabId;
return (store) => (next) => (action) => {
const result = next(action);
if (!autoselected && action.type === UPDATE_STATE && tabId) {
autoselected = true;
const connections = store.getState().instances.connections[tabId];
if (connections && connections.length === 1) {
next({ type: SELECT_INSTANCE, selected: connections[0] });
}
}
if (action.type === LIFTED_ACTION || action.type === 'TOGGLE_PERSIST') {
const instances = store.getState().instances;
const instanceId = getActiveInstance(instances);
const id = instances.options[instanceId].connectionId;
bgConnection.postMessage({ ...action, instanceId, id });
}
return result;
};
}
export default panelDispatcher;

View File

@ -0,0 +1,36 @@
import {
LIFTED_ACTION,
UPDATE_STATE,
SELECT_INSTANCE,
} from '@redux-devtools/app/lib/constants/actionTypes';
import { getActiveInstance } from '@redux-devtools/app/lib/reducers/instances';
import { Dispatch, MiddlewareAPI, Store } from 'redux';
import { StoreState } from '@redux-devtools/app/lib/reducers';
import { StoreAction } from '@redux-devtools/app/lib/actions';
function panelDispatcher(bgConnection: chrome.runtime.Port) {
let autoselected = false;
const tabId = chrome.devtools.inspectedWindow.tabId;
return (store: MiddlewareAPI<Dispatch<StoreAction>, StoreState>) =>
(next: Dispatch<StoreAction>) =>
(action: StoreAction) => {
const result = next(action);
if (!autoselected && action.type === UPDATE_STATE && tabId) {
autoselected = true;
const connections = store.getState().instances.connections[tabId];
if (connections && connections.length === 1) {
next({ type: SELECT_INSTANCE, selected: connections[0] });
}
}
if (action.type === LIFTED_ACTION || action.type === 'TOGGLE_PERSIST') {
const instances = store.getState().instances;
const instanceId = getActiveInstance(instances);
const id = instances.options[instanceId].connectionId;
bgConnection.postMessage({ ...action, instanceId, id });
}
return result;
};
}
export default panelDispatcher;

View File

@ -1,10 +0,0 @@
import { combineReducers } from 'redux';
import instances from '@redux-devtools/app/lib/reducers/instances';
import persistStates from './persistStates';
const rootReducer = combineReducers({
instances,
persistStates,
});
export default rootReducer;

View File

@ -0,0 +1,17 @@
import { combineReducers } from 'redux';
import instances, {
InstancesState,
} from '@redux-devtools/app/lib/reducers/instances';
import persistStates from './persistStates';
export interface BackgroundState {
readonly instances: InstancesState;
readonly persistStates: boolean;
}
const rootReducer = combineReducers({
instances,
persistStates,
});
export default rootReducer;

View File

@ -5,14 +5,20 @@ import notification from '@redux-devtools/app/lib/reducers/notification';
import reports from '@redux-devtools/app/lib/reducers/reports'; import reports from '@redux-devtools/app/lib/reducers/reports';
import section from '@redux-devtools/app/lib/reducers/section'; import section from '@redux-devtools/app/lib/reducers/section';
import theme from '@redux-devtools/app/lib/reducers/theme'; import theme from '@redux-devtools/app/lib/reducers/theme';
import connection from '@redux-devtools/app/lib/reducers/connection';
import socket from '@redux-devtools/app/lib/reducers/socket';
import { StoreState } from '@redux-devtools/app/lib/reducers';
import { StoreAction } from '@redux-devtools/app/lib/actions';
const rootReducer = combineReducers({ const rootReducer = combineReducers<StoreState, StoreAction>({
instances, instances,
monitor, monitor,
reports, reports,
notification, notification,
section, section,
theme, theme,
connection,
socket,
}); });
export default rootReducer; export default rootReducer;

View File

@ -6,8 +6,11 @@ import socket from '@redux-devtools/app/lib/reducers/socket';
import reports from '@redux-devtools/app/lib/reducers/reports'; import reports from '@redux-devtools/app/lib/reducers/reports';
import section from '@redux-devtools/app/lib/reducers/section'; import section from '@redux-devtools/app/lib/reducers/section';
import theme from '@redux-devtools/app/lib/reducers/theme'; import theme from '@redux-devtools/app/lib/reducers/theme';
import connection from '@redux-devtools/app/lib/reducers/connection';
import { StoreState } from '@redux-devtools/app/lib/reducers';
import { StoreAction } from '@redux-devtools/app/lib/actions';
const rootReducer = combineReducers({ const rootReducer = combineReducers<StoreState, StoreAction>({
instances, instances,
monitor, monitor,
socket, socket,
@ -15,6 +18,7 @@ const rootReducer = combineReducers({
notification, notification,
section, section,
theme, theme,
connection,
}); });
export default rootReducer; export default rootReducer;

View File

@ -7,8 +7,9 @@ import {
SELECT_INSTANCE, SELECT_INSTANCE,
LIFTED_ACTION, LIFTED_ACTION,
} from '@redux-devtools/app/lib/constants/actionTypes'; } from '@redux-devtools/app/lib/constants/actionTypes';
import { StoreAction } from '@redux-devtools/app/lib/actions';
export default function instances(state = initialState, action) { export default function instances(state = initialState, action: StoreAction) {
switch (action.type) { switch (action.type) {
case UPDATE_STATE: case UPDATE_STATE:
return { ...action.instances, selected: state.selected }; return { ...action.instances, selected: state.selected };

View File

@ -1,8 +1,10 @@
import { createStore, applyMiddleware } from 'redux'; import { createStore, applyMiddleware, PreloadedState } from 'redux';
import rootReducer from '../reducers/background'; import rootReducer, { BackgroundState } from '../reducers/background';
import api from '../middlewares/api'; import api from '../middlewares/api';
export default function configureStore(preloadedState) { export default function configureStore(
preloadedState: PreloadedState<BackgroundState>
) {
return createStore(rootReducer, preloadedState, applyMiddleware(api)); return createStore(rootReducer, preloadedState, applyMiddleware(api));
/* /*
let enhancer; let enhancer;

View File

@ -1,12 +1,13 @@
import { createStore, applyMiddleware } from 'redux'; import { createStore, applyMiddleware, PreloadedState } from 'redux';
import exportState from '@redux-devtools/app/lib/middlewares/exportState'; import exportState from '@redux-devtools/app/lib/middlewares/exportState';
import panelDispatcher from '../middlewares/panelSync'; import panelDispatcher from '../middlewares/panelSync';
import rootReducer from '../reducers/panel'; import rootReducer from '../reducers/panel';
import { StoreState } from '@redux-devtools/app/lib/reducers';
export default function configureStore( export default function configureStore(
position: string, position: string,
bgConnection: chrome.runtime.Port, bgConnection: chrome.runtime.Port,
preloadedState preloadedState: PreloadedState<StoreState>
) { ) {
const enhancer = applyMiddleware(exportState, panelDispatcher(bgConnection)); const enhancer = applyMiddleware(exportState, panelDispatcher(bgConnection));
return createStore(rootReducer, preloadedState, enhancer); return createStore(rootReducer, preloadedState, enhancer);

View File

@ -1,12 +1,25 @@
import { createStore, compose, applyMiddleware } from 'redux'; import {
createStore,
compose,
applyMiddleware,
Store,
PreloadedState,
} from 'redux';
import exportState from '@redux-devtools/app/lib/middlewares/exportState'; import exportState from '@redux-devtools/app/lib/middlewares/exportState';
import api from '@redux-devtools/app/lib/middlewares/api'; import api from '@redux-devtools/app/lib/middlewares/api';
import { CONNECT_REQUEST } from '@redux-devtools/app/lib/constants/socketActionTypes'; import { CONNECT_REQUEST } from '@redux-devtools/app/lib/constants/socketActionTypes';
import { StoreState } from '@redux-devtools/app/lib/reducers';
import { StoreAction } from '@redux-devtools/app/lib/actions';
import syncStores from '../middlewares/windowSync'; import syncStores from '../middlewares/windowSync';
import instanceSelector from '../middlewares/instanceSelector'; import instanceSelector from '../middlewares/instanceSelector';
import rootReducer from '../reducers/window'; import rootReducer from '../reducers/window';
import { BackgroundState } from '../reducers/background';
export default function configureStore(baseStore, position, preloadedState) { export default function configureStore(
baseStore: Store<BackgroundState, StoreAction>,
position: string,
preloadedState: PreloadedState<StoreState>
) {
let enhancer; let enhancer;
const middlewares = [exportState, api, syncStores(baseStore)]; const middlewares = [exportState, api, syncStores(baseStore)];
if (!position || position === '#popup') { if (!position || position === '#popup') {

View File

@ -1,3 +1,6 @@
import { PreloadedState } from 'redux';
import { StoreState } from '@redux-devtools/app/lib/reducers';
const getIfExists = (sel, template) => const getIfExists = (sel, template) =>
typeof sel === 'undefined' || typeof sel === 'undefined' ||
typeof template === 'undefined' || typeof template === 'undefined' ||
@ -5,7 +8,10 @@ const getIfExists = (sel, template) =>
? 0 ? 0
: sel; : sel;
export default function getPreloadedState(position, cb) { export default function getPreloadedState(
position: string,
cb: (state: PreloadedState<StoreState>) => void
) {
chrome.storage.local.get( chrome.storage.local.get(
[ [
'monitor' + position, 'monitor' + position,

View File

@ -7,6 +7,9 @@ import configureStore from '../../../app/stores/panelStore';
import getPreloadedState from '../background/getPreloadedState'; import getPreloadedState from '../background/getPreloadedState';
import '../../views/devpanel.pug'; import '../../views/devpanel.pug';
import { PreloadedState, Store } from 'redux';
import { StoreState } from '@redux-devtools/app/lib/reducers';
import { StoreAction } from '@redux-devtools/app/lib/actions';
const position = location.hash; const position = location.hash;
const messageStyle: CSSProperties = { const messageStyle: CSSProperties = {
@ -16,10 +19,10 @@ const messageStyle: CSSProperties = {
}; };
let rendered: boolean; let rendered: boolean;
let store; let store: Store<StoreState, StoreAction> | undefined;
let bgConnection: chrome.runtime.Port; let bgConnection: chrome.runtime.Port;
let naTimeout: NodeJS.Timeout; let naTimeout: NodeJS.Timeout;
let preloadedState; let preloadedState: PreloadedState<StoreState>;
const isChrome = navigator.userAgent.indexOf('Firefox') === -1; const isChrome = navigator.userAgent.indexOf('Firefox') === -1;
@ -96,10 +99,10 @@ function init(id: number) {
bgConnection.onMessage.addListener((message) => { bgConnection.onMessage.addListener((message) => {
if (message.type === 'NA') { if (message.type === 'NA') {
if (message.id === id) renderNA(); if (message.id === id) renderNA();
else store.dispatch({ type: REMOVE_INSTANCE, id: message.id }); else store!.dispatch({ type: REMOVE_INSTANCE, id: message.id });
} else { } else {
if (!rendered) renderDevTools(); if (!rendered) renderDevTools();
store.dispatch(message); store!.dispatch(message);
} }
}); });
} }

View File

@ -1,6 +1,6 @@
import '../../views/devtools.pug'; import '../../views/devtools.pug';
function createPanel(url) { function createPanel(url: string) {
chrome.devtools.panels.create( chrome.devtools.panels.create(
'Redux', 'Redux',
'img/logo/scalable.png', 'img/logo/scalable.png',

View File

@ -5,7 +5,7 @@ if (process.env.NODE_ENV === 'production') {
const { default: script } = require('raw-loader!tmp/page.bundle.js'); const { default: script } = require('raw-loader!tmp/page.bundle.js');
s.appendChild(document.createTextNode(script)); s.appendChild(document.createTextNode(script));
(document.head || document.documentElement).appendChild(s); (document.head || document.documentElement).appendChild(s);
s.parentNode.removeChild(s); s.parentNode!.removeChild(s);
} else { } else {
s.src = chrome.extension.getURL('page.bundle.js'); s.src = chrome.extension.getURL('page.bundle.js');
s.onload = function () { s.onload = function () {

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { OptionsProps } from './Options';
export default ({ options, saveOption }) => { export default ({ options, saveOption }: OptionsProps) => {
const AllowToRunState = { const AllowToRunState = {
EVERYWHERE: true, EVERYWHERE: true,
ON_SPECIFIC_URLS: false, ON_SPECIFIC_URLS: false,

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { OptionsProps } from './Options';
export default ({ options, saveOption }) => { export default ({ options, saveOption }: OptionsProps) => {
return ( return (
<fieldset className="option-group"> <fieldset className="option-group">
<legend className="option-group__title">Context Menu</legend> <legend className="option-group__title">Context Menu</legend>

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { OptionsProps } from './Options';
export default ({ options, saveOption }) => { export default ({ options, saveOption }: OptionsProps) => {
const EditorState = { const EditorState = {
BROWSER: 0, BROWSER: 0,
EXTERNAL: 1, EXTERNAL: 1,
@ -45,7 +46,7 @@ export default ({ options, saveOption }) => {
className="option__element" className="option__element"
id="editor" id="editor"
type="text" type="text"
size="33" size={33}
maxLength={30} maxLength={30}
placeholder="vscode, atom, webstorm, sublime..." placeholder="vscode, atom, webstorm, sublime..."
value={options.editor} value={options.editor}

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import { FilterState } from '../../../app/api/filters'; import { FilterState } from '../../../app/api/filters';
import { OptionsProps } from './Options';
export default ({ options, saveOption }) => { export default ({ options, saveOption }: OptionsProps) => {
return ( return (
<fieldset className="option-group"> <fieldset className="option-group">
<legend className="option-group__title"> <legend className="option-group__title">

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { OptionsProps } from './Options';
export default ({ options, saveOption }) => { export default ({ options, saveOption }: OptionsProps) => {
const browserName = navigator.userAgent.includes('Firefox') const browserName = navigator.userAgent.includes('Firefox')
? 'Firefox' ? 'Firefox'
: 'Chrome'; : 'Chrome';

View File

@ -4,8 +4,17 @@ import FilterGroup from './FilterGroup';
import AllowToRunGroup from './AllowToRunGroup'; import AllowToRunGroup from './AllowToRunGroup';
import MiscellaneousGroup from './MiscellaneousGroup'; import MiscellaneousGroup from './MiscellaneousGroup';
import ContextMenuGroup from './ContextMenuGroup'; import ContextMenuGroup from './ContextMenuGroup';
import { Options } from './syncOptions';
export default (props) => ( export interface OptionsProps {
readonly options: Options;
readonly saveOption: <K extends keyof Options>(
name: K,
value: Options[K]
) => void;
}
export default (props: OptionsProps) => (
<div> <div>
<EditorGroup {...props} /> <EditorGroup {...props} />
<FilterGroup {...props} /> <FilterGroup {...props} />

View File

@ -1,108 +0,0 @@
import { FilterState } from '../../../app/api/filters';
let options;
let subscribers = [];
const save = (toAllTabs) => (key, value) => {
let obj = {};
obj[key] = value;
chrome.storage.sync.set(obj);
options[key] = value;
toAllTabs({ options: options });
subscribers.forEach((s) => s(options));
};
const migrateOldOptions = (oldOptions) => {
let newOptions = Object.assign({}, oldOptions);
// Migrate the old `filter` option from 2.2.1
if (typeof oldOptions.filter === 'boolean') {
if (oldOptions.filter && oldOptions.whitelist.length > 0) {
newOptions.filter = FilterState.WHITELIST_SPECIFIC;
} else if (oldOptions.filter) {
newOptions.filter = FilterState.BLACKLIST_SPECIFIC;
} else {
newOptions.filter = FilterState.DO_NOT_FILTER;
}
}
return newOptions;
};
const get = (callback) => {
if (options) callback(options);
else {
chrome.storage.sync.get(
{
useEditor: 0,
editor: '',
projectPath: '',
maxAge: 50,
filter: FilterState.DO_NOT_FILTER,
whitelist: '',
blacklist: '',
shouldCatchErrors: false,
inject: true,
urls: '^https?://localhost|0\\.0\\.0\\.0:\\d+\n^https?://.+\\.github\\.io',
showContextMenus: true,
},
function (items) {
options = migrateOldOptions(items);
callback(options);
}
);
}
};
const subscribe = (callback) => {
subscribers = subscribers.concat(callback);
};
const toReg = (str) =>
str !== '' ? str.split('\n').filter(Boolean).join('|') : null;
export const injectOptions = (newOptions) => {
if (!newOptions) return;
if (newOptions.filter !== FilterState.DO_NOT_FILTER) {
newOptions.whitelist = toReg(newOptions.whitelist);
newOptions.blacklist = toReg(newOptions.blacklist);
}
options = newOptions;
let s = document.createElement('script');
s.type = 'text/javascript';
s.appendChild(
document.createTextNode(
'window.devToolsOptions = Object.assign(window.devToolsOptions||{},' +
JSON.stringify(options) +
');'
)
);
(document.head || document.documentElement).appendChild(s);
s.parentNode.removeChild(s);
};
export const getOptionsFromBg = () => {
/* chrome.runtime.sendMessage({ type: 'GET_OPTIONS' }, response => {
if (response && response.options) injectOptions(response.options);
});
*/
get((newOptions) => {
injectOptions(newOptions);
}); // Legacy
};
export const isAllowed = (localOptions = options) =>
!localOptions ||
localOptions.inject ||
!localOptions.urls ||
location.href.match(toReg(localOptions.urls));
export default function syncOptions(toAllTabs) {
if (toAllTabs && !options) get(() => {}); // Initialize
return {
save: save(toAllTabs),
get: get,
subscribe: subscribe,
};
}

View File

@ -0,0 +1,142 @@
import { FilterState, FilterStateValue } from '../../../app/api/filters';
export interface Options {
readonly useEditor: number;
readonly editor: string;
readonly projectPath: string;
readonly maxAge: number;
readonly filter: FilterStateValue;
readonly whitelist: string;
readonly blacklist: string;
readonly shouldCatchErrors: boolean;
readonly inject: boolean;
readonly urls: string;
readonly showContextMenus: boolean;
}
interface OldOrNewOptions {
readonly useEditor: number;
readonly editor: string;
readonly projectPath: string;
readonly maxAge: number;
readonly filter: FilterStateValue | boolean;
readonly whitelist: string;
readonly blacklist: string;
readonly shouldCatchErrors: boolean;
readonly inject: boolean;
readonly urls: string;
readonly showContextMenus: boolean;
}
let options: Options | undefined;
let subscribers: ((options: Options) => void)[] = [];
type ToAllTabs = (msg: { readonly options: Options }) => void;
const save =
(toAllTabs: ToAllTabs | undefined) =>
<K extends keyof Options>(key: K, value: Options[K]) => {
let obj: { [K1 in keyof Options]?: Options[K1] } = {};
obj[key] = value;
chrome.storage.sync.set(obj);
options![key] = value;
toAllTabs!({ options: options! });
subscribers.forEach((s) => s(options!));
};
const migrateOldOptions = (oldOptions: OldOrNewOptions): Options => ({
...oldOptions,
filter:
// Migrate the old `filter` option from 2.2.1
typeof oldOptions.filter === 'boolean'
? oldOptions.filter && oldOptions.whitelist.length > 0
? FilterState.WHITELIST_SPECIFIC
: oldOptions.filter
? FilterState.BLACKLIST_SPECIFIC
: FilterState.DO_NOT_FILTER
: oldOptions.filter,
});
const get = (callback: (options: Options) => void) => {
if (options) callback(options);
else {
chrome.storage.sync.get(
{
useEditor: 0,
editor: '',
projectPath: '',
maxAge: 50,
filter: FilterState.DO_NOT_FILTER,
whitelist: '',
blacklist: '',
shouldCatchErrors: false,
inject: true,
urls: '^https?://localhost|0\\.0\\.0\\.0:\\d+\n^https?://.+\\.github\\.io',
showContextMenus: true,
},
function (items) {
options = migrateOldOptions(items as OldOrNewOptions);
callback(options);
}
);
}
};
const subscribe = (callback: (options: Options) => void) => {
subscribers = subscribers.concat(callback);
};
const toReg = (str: string) =>
str !== '' ? str.split('\n').filter(Boolean).join('|') : null;
export const injectOptions = (newOptions: Options) => {
if (!newOptions) return;
options = {
...newOptions,
whitelist:
newOptions.filter !== FilterState.DO_NOT_FILTER
? toReg(newOptions.whitelist)!
: newOptions.whitelist,
blacklist:
newOptions.filter !== FilterState.DO_NOT_FILTER
? toReg(newOptions.blacklist)!
: newOptions.blacklist,
};
let s = document.createElement('script');
s.type = 'text/javascript';
s.appendChild(
document.createTextNode(
'window.devToolsOptions = Object.assign(window.devToolsOptions||{},' +
JSON.stringify(options) +
');'
)
);
(document.head || document.documentElement).appendChild(s);
s.parentNode!.removeChild(s);
};
export const getOptionsFromBg = () => {
/* chrome.runtime.sendMessage({ type: 'GET_OPTIONS' }, response => {
if (response && response.options) injectOptions(response.options);
});
*/
get((newOptions) => {
injectOptions(newOptions);
}); // Legacy
};
export const isAllowed = (localOptions = options) =>
!localOptions ||
localOptions.inject ||
!localOptions.urls ||
location.href.match(toReg(localOptions.urls)!);
export default function syncOptions(toAllTabs?: ToAllTabs) {
if (toAllTabs && !options) get(() => {}); // Initialize
return {
save: save(toAllTabs),
get: get,
subscribe: subscribe,
};
}

View File

@ -1,7 +1,9 @@
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import { render } from 'react-dom';
import { PreloadedState } from 'redux';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { UPDATE_STATE } from '@redux-devtools/app/lib/constants/actionTypes'; import { UPDATE_STATE } from '@redux-devtools/app/lib/constants/actionTypes';
import { StoreState } from '@redux-devtools/app/lib/reducers';
import App from '../../../app/containers/App'; import App from '../../../app/containers/App';
import configureStore from '../../../app/stores/windowStore'; import configureStore from '../../../app/stores/windowStore';
import getPreloadedState from '../background/getPreloadedState'; import getPreloadedState from '../background/getPreloadedState';
@ -9,7 +11,7 @@ import getPreloadedState from '../background/getPreloadedState';
import '../../views/window.pug'; import '../../views/window.pug';
const position = location.hash; const position = location.hash;
let preloadedState; let preloadedState: PreloadedState<StoreState>;
getPreloadedState(position, (state) => { getPreloadedState(position, (state) => {
preloadedState = state; preloadedState = state;
}); });

View File

@ -19,7 +19,6 @@ chrome.storage.local.get(
selectMonitor={options['select-monitor']} selectMonitor={options['select-monitor']}
testTemplates={options['test-templates']} testTemplates={options['test-templates']}
selectedTemplate={options['test-templates-sel']} selectedTemplate={options['test-templates-sel']}
testTemplates={options['test-templates']}
useCodemirror useCodemirror
socketOptions={ socketOptions={
options['s:hostname'] && options['s:port'] options['s:hostname'] && options['s:port']