mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-27 00:19:55 +03:00
More work
This commit is contained in:
parent
c80473329e
commit
ca68117921
|
@ -28,7 +28,8 @@
|
|||
"test:app": "cross-env BABEL_ENV=test jest test/app",
|
||||
"test:chrome": "jest test/chrome",
|
||||
"test:electron": "jest test/electron",
|
||||
"test": "npm run test:app && npm run build:extension && npm run test:chrome && npm run test:electron"
|
||||
"test": "npm run test:app && npm run build:extension && npm run test:chrome && npm run test:electron",
|
||||
"type-check": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@redux-devtools/app": "^1.0.0-8",
|
||||
|
|
|
@ -357,6 +357,7 @@ export interface ErrorMessage {
|
|||
readonly payload: string;
|
||||
readonly source: typeof source;
|
||||
readonly instanceId: number;
|
||||
readonly message?: string | undefined;
|
||||
}
|
||||
|
||||
interface InitInstanceMessage {
|
||||
|
@ -449,16 +450,34 @@ export function sendMessage<S, A extends Action<unknown>>(
|
|||
config = {}; // eslint-disable-line no-param-reassign
|
||||
if (action) amendedAction = amendActionType(action, config, sendMessage);
|
||||
}
|
||||
const message = {
|
||||
type: action ? 'ACTION' : 'STATE',
|
||||
if (action) {
|
||||
toContentScript(
|
||||
{
|
||||
type: 'ACTION',
|
||||
action: amendedAction,
|
||||
payload: state,
|
||||
maxAge: config.maxAge,
|
||||
source,
|
||||
name: config.name || name,
|
||||
instanceId: config.instanceId || instanceId || 1,
|
||||
};
|
||||
toContentScript(message, config.serialize, config.serialize);
|
||||
},
|
||||
config.serialize,
|
||||
config.serialize
|
||||
);
|
||||
}
|
||||
toContentScript(
|
||||
{
|
||||
type: 'STATE',
|
||||
action: amendedAction,
|
||||
payload: state,
|
||||
maxAge: config.maxAge,
|
||||
source,
|
||||
name: config.name || name,
|
||||
instanceId: config.instanceId || instanceId || 1,
|
||||
},
|
||||
config.serialize,
|
||||
config.serialize
|
||||
);
|
||||
}
|
||||
|
||||
function handleMessages(event: MessageEvent<ContentScriptToPageScriptMessage>) {
|
||||
|
@ -609,7 +628,11 @@ export function connect(preConfig: Config) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
sendMessage(amendedAction, amendedState, config);
|
||||
sendMessage(
|
||||
amendedAction as StructuralPerformAction<A>,
|
||||
amendedState,
|
||||
config
|
||||
);
|
||||
};
|
||||
|
||||
const init = <S, A extends Action<unknown>>(
|
||||
|
|
|
@ -7,6 +7,8 @@ import Actions from '@redux-devtools/app/lib/containers/Actions';
|
|||
import Header from '@redux-devtools/app/lib/components/Header';
|
||||
import { clearNotification } from '@redux-devtools/app/lib/actions';
|
||||
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||
import { SingleMessage } from '../middlewares/api';
|
||||
import { Position } from '../api/openWindow';
|
||||
|
||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||
|
@ -15,13 +17,17 @@ interface OwnProps {
|
|||
}
|
||||
type Props = StateProps & DispatchProps & OwnProps;
|
||||
|
||||
function sendMessage(message: SingleMessage) {
|
||||
chrome.runtime.sendMessage(message);
|
||||
}
|
||||
|
||||
class App extends Component<Props> {
|
||||
openWindow = (position: string) => {
|
||||
chrome.runtime.sendMessage({ type: 'OPEN', position });
|
||||
openWindow = (position: Position) => {
|
||||
sendMessage({ type: 'OPEN', position });
|
||||
};
|
||||
openOptionsPage = () => {
|
||||
if (navigator.userAgent.indexOf('Firefox') !== -1) {
|
||||
chrome.runtime.sendMessage({ type: 'OPEN_OPTIONS' });
|
||||
sendMessage({ type: 'OPEN_OPTIONS' });
|
||||
} else {
|
||||
chrome.runtime.openOptionsPage();
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@ import syncOptions, {
|
|||
OptionsMessage,
|
||||
SyncOptions,
|
||||
} from '../../browser/extension/options/syncOptions';
|
||||
import openDevToolsWindow from '../../browser/extension/background/openWindow';
|
||||
import openDevToolsWindow, {
|
||||
DevToolsPosition,
|
||||
} from '../../browser/extension/background/openWindow';
|
||||
import { getReport } from '../../browser/extension/background/logging';
|
||||
import {
|
||||
CustomAction,
|
||||
|
@ -32,6 +34,7 @@ import {
|
|||
BackgroundAction,
|
||||
LiftedActionAction,
|
||||
} from '../stores/backgroundStore';
|
||||
import { Position } from '../api/openWindow';
|
||||
|
||||
interface TabMessageBase {
|
||||
readonly type: string;
|
||||
|
@ -87,7 +90,7 @@ interface NAAction {
|
|||
interface InitMessage<S, A extends Action<unknown>> {
|
||||
readonly type: 'INIT';
|
||||
readonly payload: string;
|
||||
readonly instanceId: string;
|
||||
instanceId: string;
|
||||
readonly source: '@devtools-page';
|
||||
action?: string;
|
||||
name?: string | undefined;
|
||||
|
@ -98,7 +101,7 @@ interface InitMessage<S, A extends Action<unknown>> {
|
|||
interface LiftedMessage {
|
||||
readonly type: 'LIFTED';
|
||||
readonly liftedState: { readonly isPaused: boolean | undefined };
|
||||
readonly instanceId: string;
|
||||
instanceId: number;
|
||||
readonly source: '@devtools-page';
|
||||
}
|
||||
|
||||
|
@ -112,7 +115,7 @@ interface SerializedPartialStateMessage {
|
|||
readonly type: 'PARTIAL_STATE';
|
||||
readonly payload: SerializedPartialLiftedState;
|
||||
readonly source: '@devtools-page';
|
||||
readonly instanceId: string;
|
||||
instanceId: number;
|
||||
readonly maxAge: number;
|
||||
readonly actionsById: string;
|
||||
readonly computedStates: string;
|
||||
|
@ -124,14 +127,14 @@ interface SerializedExportMessage {
|
|||
readonly payload: string;
|
||||
readonly committedState: string | undefined;
|
||||
readonly source: '@devtools-page';
|
||||
readonly instanceId: string;
|
||||
instanceId: number;
|
||||
}
|
||||
|
||||
interface SerializedActionMessage {
|
||||
readonly type: 'ACTION';
|
||||
readonly payload: string;
|
||||
readonly source: '@devtools-page';
|
||||
readonly instanceId: string;
|
||||
instanceId: number;
|
||||
readonly action: string;
|
||||
readonly maxAge: number;
|
||||
readonly nextActionId: number;
|
||||
|
@ -144,7 +147,7 @@ interface SerializedStateMessage<S, A extends Action<unknown>> {
|
|||
'actionsById' | 'computedStates' | 'committedState'
|
||||
>;
|
||||
readonly source: '@devtools-page';
|
||||
readonly instanceId: string;
|
||||
instanceId: string;
|
||||
readonly libConfig?: LibConfig;
|
||||
readonly actionsById: string;
|
||||
readonly computedStates: string;
|
||||
|
@ -165,7 +168,7 @@ interface EmptyUpdateStateAction {
|
|||
|
||||
interface UpdateStateAction<S, A extends Action<unknown>> {
|
||||
readonly type: typeof UPDATE_STATE;
|
||||
readonly request: UpdateStateRequest<S, A>;
|
||||
request: UpdateStateRequest<S, A>;
|
||||
readonly id: string | number;
|
||||
}
|
||||
|
||||
|
@ -195,8 +198,8 @@ type MonitorPort = Omit<chrome.runtime.Port, 'postMessage'> & {
|
|||
postMessage: (message: MonitorMessage) => void;
|
||||
};
|
||||
|
||||
const CONNECTED = 'socket/CONNECTED';
|
||||
const DISCONNECTED = 'socket/DISCONNECTED';
|
||||
export const CONNECTED = 'socket/CONNECTED';
|
||||
export const DISCONNECTED = 'socket/DISCONNECTED';
|
||||
const connections: {
|
||||
readonly tab: { [K in number | string]: TabPort };
|
||||
readonly panel: { [K in number | string]: PanelPort };
|
||||
|
@ -248,19 +251,78 @@ interface ImportMessage {
|
|||
|
||||
type ToContentScriptMessage = ImportMessage | LiftedActionAction;
|
||||
|
||||
function toContentScript({
|
||||
message,
|
||||
action,
|
||||
id,
|
||||
instanceId,
|
||||
state,
|
||||
}: ToContentScriptMessage) {
|
||||
function toContentScript(messageBody: ToContentScriptMessage) {
|
||||
if (messageBody.message === 'DISPATCH') {
|
||||
const { message, action, id, instanceId, state } = messageBody;
|
||||
connections.tab[id!].postMessage({
|
||||
type: message,
|
||||
action,
|
||||
state: nonReduxDispatch(window.store, message, instanceId, action, state),
|
||||
state: nonReduxDispatch(
|
||||
window.store,
|
||||
message,
|
||||
instanceId,
|
||||
action as AppDispatchAction,
|
||||
state
|
||||
),
|
||||
id: instanceId.toString().replace(/^[^\/]+\//, ''),
|
||||
});
|
||||
} else if (messageBody.message === 'IMPORT') {
|
||||
const { message, action, id, instanceId, state } = messageBody;
|
||||
connections.tab[id!].postMessage({
|
||||
type: message,
|
||||
action,
|
||||
state: nonReduxDispatch(
|
||||
window.store,
|
||||
message,
|
||||
instanceId,
|
||||
action as unknown as AppDispatchAction,
|
||||
state
|
||||
),
|
||||
id: instanceId.toString().replace(/^[^\/]+\//, ''),
|
||||
});
|
||||
} else if (messageBody.message === 'ACTION') {
|
||||
const { message, action, id, instanceId, state } = messageBody;
|
||||
connections.tab[id!].postMessage({
|
||||
type: message,
|
||||
action,
|
||||
state: nonReduxDispatch(
|
||||
window.store,
|
||||
message,
|
||||
instanceId,
|
||||
action as unknown as AppDispatchAction,
|
||||
state
|
||||
),
|
||||
id: instanceId.toString().replace(/^[^\/]+\//, ''),
|
||||
});
|
||||
} else if (messageBody.message === 'EXPORT') {
|
||||
const { message, action, id, instanceId, state } = messageBody;
|
||||
connections.tab[id!].postMessage({
|
||||
type: message,
|
||||
action,
|
||||
state: nonReduxDispatch(
|
||||
window.store,
|
||||
message,
|
||||
instanceId,
|
||||
action as unknown as AppDispatchAction,
|
||||
state
|
||||
),
|
||||
id: instanceId.toString().replace(/^[^\/]+\//, ''),
|
||||
});
|
||||
} else {
|
||||
const { message, action, id, instanceId, state } = messageBody;
|
||||
connections.tab[id!].postMessage({
|
||||
type: message,
|
||||
action,
|
||||
state: nonReduxDispatch(
|
||||
window.store,
|
||||
message,
|
||||
instanceId,
|
||||
action as AppDispatchAction,
|
||||
state
|
||||
),
|
||||
id: (instanceId as number).toString().replace(/^[^\/]+\//, ''),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toAllTabs(msg: TabMessage) {
|
||||
|
@ -302,9 +364,28 @@ function togglePersist() {
|
|||
}
|
||||
}
|
||||
|
||||
interface OpenMessage {
|
||||
readonly type: 'OPEN';
|
||||
readonly position: Position;
|
||||
}
|
||||
|
||||
interface OpenOptionsMessage {
|
||||
readonly type: 'OPEN_OPTIONS';
|
||||
}
|
||||
|
||||
interface GetOptionsMessage {
|
||||
readonly type: 'GET_OPTIONS';
|
||||
}
|
||||
|
||||
export type SingleMessage =
|
||||
| OpenMessage
|
||||
| OpenOptionsMessage
|
||||
| GetOptionsMessage;
|
||||
|
||||
type BackgroundStoreMessage<S, A extends Action<unknown>> =
|
||||
| PageScriptToContentScriptMessageWithoutDisconnectOrInitInstance<S, A>
|
||||
| SplitMessage;
|
||||
| SplitMessage
|
||||
| SingleMessage;
|
||||
type BackgroundStoreResponse = { readonly options: Options };
|
||||
|
||||
// Receive messages from content scripts
|
||||
|
@ -338,13 +419,13 @@ function messaging<S, A extends Action<unknown>>(
|
|||
return;
|
||||
}
|
||||
if (request.type === 'OPEN') {
|
||||
let position = 'devtools-left';
|
||||
let position: DevToolsPosition = 'devtools-left';
|
||||
if (
|
||||
['remote', 'panel', 'left', 'right', 'bottom'].indexOf(
|
||||
request.position
|
||||
) !== -1
|
||||
) {
|
||||
position = 'devtools-' + request.position;
|
||||
position = ('devtools-' + request.position) as DevToolsPosition;
|
||||
}
|
||||
openDevToolsWindow(position);
|
||||
return;
|
||||
|
@ -372,19 +453,20 @@ function messaging<S, A extends Action<unknown>>(
|
|||
type: UPDATE_STATE,
|
||||
request,
|
||||
id: tabId,
|
||||
};
|
||||
} as UpdateStateAction<S, A>;
|
||||
const instanceId = `${tabId}/${request.instanceId}`;
|
||||
if ('split' in request) {
|
||||
if (request.split === 'start') {
|
||||
chunks[instanceId] = request;
|
||||
chunks[instanceId] = request as any;
|
||||
return;
|
||||
}
|
||||
if (request.split === 'chunk') {
|
||||
chunks[instanceId][request.chunk[0]] =
|
||||
(chunks[instanceId][request.chunk[0]] || '') + request.chunk[1];
|
||||
(chunks[instanceId] as any)[request.chunk[0]] =
|
||||
((chunks[instanceId] as any)[request.chunk[0]] || '') +
|
||||
request.chunk[1];
|
||||
return;
|
||||
}
|
||||
action.request = chunks[instanceId];
|
||||
action.request = chunks[instanceId] as any;
|
||||
delete chunks[instanceId];
|
||||
}
|
||||
if (request.instanceId) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { createStore, applyMiddleware, PreloadedState } from 'redux';
|
||||
import rootReducer, { BackgroundState } from '../reducers/background';
|
||||
import api from '../middlewares/api';
|
||||
import api, { CONNECTED, DISCONNECTED } from '../middlewares/api';
|
||||
import { LIFTED_ACTION } from '@redux-devtools/app/lib/constants/actionTypes';
|
||||
import {
|
||||
CustomAction,
|
||||
|
@ -26,6 +26,7 @@ interface LiftedActionImportAction extends LiftedActionActionBase {
|
|||
message: 'IMPORT';
|
||||
state: string;
|
||||
preloadedState?: unknown | undefined;
|
||||
action?: never;
|
||||
}
|
||||
interface LiftedActionActionAction extends LiftedActionActionBase {
|
||||
type: typeof LIFTED_ACTION;
|
||||
|
@ -36,6 +37,7 @@ interface LiftedActionExportAction extends LiftedActionActionBase {
|
|||
type: typeof LIFTED_ACTION;
|
||||
message: 'EXPORT';
|
||||
toExport: boolean;
|
||||
action?: never;
|
||||
}
|
||||
export type LiftedActionAction =
|
||||
| LiftedActionDispatchAction
|
||||
|
@ -49,10 +51,20 @@ interface TogglePersistAction {
|
|||
readonly id: string | number | undefined;
|
||||
}
|
||||
|
||||
interface ConnectedAction {
|
||||
readonly type: typeof CONNECTED;
|
||||
}
|
||||
|
||||
interface DisconnectedAction {
|
||||
readonly type: typeof DISCONNECTED;
|
||||
}
|
||||
|
||||
export type BackgroundAction =
|
||||
| StoreActionWithoutLiftedAction
|
||||
| LiftedActionAction
|
||||
| TogglePersistAction;
|
||||
| TogglePersistAction
|
||||
| ConnectedAction
|
||||
| DisconnectedAction;
|
||||
|
||||
export default function configureStore(
|
||||
preloadedState?: PreloadedState<BackgroundState>
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
// Mock not supported chrome.* API for Firefox and Electron
|
||||
|
||||
window.isElectron =
|
||||
(window as any).isElectron =
|
||||
window.navigator && window.navigator.userAgent.indexOf('Electron') !== -1;
|
||||
|
||||
const isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;
|
||||
|
||||
// Background page only
|
||||
if (
|
||||
(window.isElectron &&
|
||||
((window as any).isElectron &&
|
||||
location.pathname === '/_generated_background_page.html') ||
|
||||
isFirefox
|
||||
) {
|
||||
chrome.runtime.onConnectExternal = {
|
||||
(chrome.runtime as any).onConnectExternal = {
|
||||
addListener() {},
|
||||
};
|
||||
chrome.runtime.onMessageExternal = {
|
||||
(chrome.runtime as any).onMessageExternal = {
|
||||
addListener() {},
|
||||
};
|
||||
|
||||
if (window.isElectron) {
|
||||
chrome.notifications = {
|
||||
if ((window as any).isElectron) {
|
||||
(chrome.notifications as any) = {
|
||||
onClicked: {
|
||||
addListener() {},
|
||||
},
|
||||
create() {},
|
||||
clear() {},
|
||||
};
|
||||
chrome.contextMenus = {
|
||||
(chrome.contextMenus as any) = {
|
||||
onClicked: {
|
||||
addListener() {},
|
||||
},
|
||||
};
|
||||
} else {
|
||||
chrome.storage.sync = chrome.storage.local;
|
||||
chrome.runtime.onInstalled = {
|
||||
addListener: (cb) => cb(),
|
||||
(chrome.storage as any).sync = chrome.storage.local;
|
||||
(chrome.runtime as any).onInstalled = {
|
||||
addListener: (cb: any) => cb(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (window.isElectron) {
|
||||
if ((window as any).isElectron) {
|
||||
if (!chrome.storage.local || !chrome.storage.local.remove) {
|
||||
chrome.storage.local = {
|
||||
set(obj, callback) {
|
||||
(chrome.storage as any).local = {
|
||||
set(obj: any, callback: any) {
|
||||
Object.keys(obj).forEach((key) => {
|
||||
localStorage.setItem(key, obj[key]);
|
||||
});
|
||||
|
@ -50,8 +50,8 @@ if (window.isElectron) {
|
|||
callback();
|
||||
}
|
||||
},
|
||||
get(obj, callback) {
|
||||
const result = {};
|
||||
get(obj: any, callback: any) {
|
||||
const result: any = {};
|
||||
Object.keys(obj).forEach((key) => {
|
||||
result[key] = localStorage.getItem(key) || obj[key];
|
||||
});
|
||||
|
@ -60,7 +60,7 @@ if (window.isElectron) {
|
|||
}
|
||||
},
|
||||
// Electron ~ 1.4.6
|
||||
remove(items, callback) {
|
||||
remove(items: any, callback: any) {
|
||||
if (Array.isArray(items)) {
|
||||
items.forEach((name) => {
|
||||
localStorage.removeItem(name);
|
||||
|
@ -75,7 +75,7 @@ if (window.isElectron) {
|
|||
};
|
||||
}
|
||||
// Avoid error: chrome.runtime.sendMessage is not supported responseCallback
|
||||
const originSendMessage = chrome.runtime.sendMessage;
|
||||
const originSendMessage = (chrome.runtime as any).sendMessage;
|
||||
chrome.runtime.sendMessage = function () {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return originSendMessage(...arguments);
|
||||
|
@ -87,6 +87,6 @@ if (window.isElectron) {
|
|||
};
|
||||
}
|
||||
|
||||
if (isFirefox || window.isElectron) {
|
||||
chrome.storage.sync = chrome.storage.local;
|
||||
if (isFirefox || (window as any).isElectron) {
|
||||
(chrome.storage as any).sync = chrome.storage.local;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Include this script in Chrome apps and extensions for remote debugging
|
||||
// <script src="chrome-extension://lmhkpmbekcpmknklioeibfkpmmfibljd/js/redux-devtools-extension.bundle.js"></script>
|
||||
|
||||
import { Options } from '../options/syncOptions';
|
||||
|
||||
window.devToolsExtensionID = 'lmhkpmbekcpmknklioeibfkpmmfibljd';
|
||||
require('./contentScript');
|
||||
require('./pageScript');
|
||||
|
@ -8,7 +10,7 @@ require('./pageScript');
|
|||
chrome.runtime.sendMessage(
|
||||
window.devToolsExtensionID,
|
||||
{ type: 'GET_OPTIONS' },
|
||||
function (response) {
|
||||
function (response: { readonly options: Options }) {
|
||||
if (!response.options.inject) {
|
||||
const urls = response.options.urls.split('\n').filter(Boolean).join('|');
|
||||
if (!location.href.match(new RegExp(urls))) return;
|
||||
|
|
|
@ -5,7 +5,6 @@ import { SET_STATE } from '../constants/actionTypes';
|
|||
import { InstancesState, State } from '../reducers/instances';
|
||||
import { Dispatch, MiddlewareAPI } from 'redux';
|
||||
import { DispatchAction, StoreAction } from '../actions';
|
||||
import { StoreState } from '../reducers';
|
||||
|
||||
export function sweep(state: State): State {
|
||||
return {
|
||||
|
|
Loading…
Reference in New Issue
Block a user