mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2024-11-29 04:53:54 +03:00
feat(extension): add back buttons for opening new windows (#784)
This commit is contained in:
parent
f122f5227a
commit
fdf3f2d94f
168
extension/src/app/containers/Actions.tsx
Normal file
168
extension/src/app/containers/Actions.tsx
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect, ResolveThunks } from 'react-redux';
|
||||||
|
import { Button, Container, Divider, Toolbar } from 'devui';
|
||||||
|
import SliderMonitor from '@redux-devtools/app/lib/containers/monitors/Slider';
|
||||||
|
import {
|
||||||
|
liftedDispatch as liftedDispatchAction,
|
||||||
|
getReport,
|
||||||
|
} from '@redux-devtools/app/lib/actions';
|
||||||
|
import { getActiveInstance } from '@redux-devtools/app/lib/reducers/instances';
|
||||||
|
import DevTools from '@redux-devtools/app/lib/containers/DevTools';
|
||||||
|
import Dispatcher from '@redux-devtools/app/lib/containers/monitors/Dispatcher';
|
||||||
|
import TopButtons from '@redux-devtools/app/lib/components/TopButtons';
|
||||||
|
import ExportButton from '@redux-devtools/app/lib/components/buttons/ExportButton';
|
||||||
|
import ImportButton from '@redux-devtools/app/lib/components/buttons/ImportButton';
|
||||||
|
import PrintButton from '@redux-devtools/app/lib/components/buttons/PrintButton';
|
||||||
|
import MonitorSelector from '@redux-devtools/app/lib/components/MonitorSelector';
|
||||||
|
import SliderButton from '@redux-devtools/app/lib/components/buttons/SliderButton';
|
||||||
|
import DispatcherButton from '@redux-devtools/app/lib/components/buttons/DispatcherButton';
|
||||||
|
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||||
|
import { GoRadioTower } from 'react-icons/go';
|
||||||
|
import {
|
||||||
|
MdBorderBottom,
|
||||||
|
MdBorderLeft,
|
||||||
|
MdBorderRight,
|
||||||
|
MdSave,
|
||||||
|
} from 'react-icons/md';
|
||||||
|
import { Position } from '../api/openWindow';
|
||||||
|
import { SingleMessage } from '../middlewares/api';
|
||||||
|
|
||||||
|
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||||
|
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||||
|
interface OwnProps {
|
||||||
|
readonly position: string;
|
||||||
|
}
|
||||||
|
type Props = StateProps & DispatchProps & OwnProps;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
isElectron?: boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendMessage(message: SingleMessage) {
|
||||||
|
chrome.runtime.sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Actions extends Component<Props> {
|
||||||
|
openWindow = (position: Position) => {
|
||||||
|
sendMessage({ type: 'OPEN', position });
|
||||||
|
};
|
||||||
|
openOptionsPage = () => {
|
||||||
|
if (navigator.userAgent.indexOf('Firefox') !== -1) {
|
||||||
|
sendMessage({ type: 'OPEN_OPTIONS' });
|
||||||
|
} else {
|
||||||
|
chrome.runtime.openOptionsPage();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
monitor,
|
||||||
|
dispatcherIsOpen,
|
||||||
|
sliderIsOpen,
|
||||||
|
options,
|
||||||
|
liftedState,
|
||||||
|
liftedDispatch,
|
||||||
|
position,
|
||||||
|
} = this.props;
|
||||||
|
const { features } = options;
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
<TopButtons
|
||||||
|
dispatch={liftedDispatch}
|
||||||
|
liftedState={liftedState}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
<DevTools
|
||||||
|
monitor={monitor}
|
||||||
|
liftedState={liftedState}
|
||||||
|
monitorState={this.props.monitorState}
|
||||||
|
dispatch={liftedDispatch}
|
||||||
|
features={options.features}
|
||||||
|
/>
|
||||||
|
{sliderIsOpen && options.connectionId && options.features.jump && (
|
||||||
|
<SliderMonitor liftedState={liftedState} dispatch={liftedDispatch} />
|
||||||
|
)}
|
||||||
|
{dispatcherIsOpen &&
|
||||||
|
options.connectionId &&
|
||||||
|
options.features.dispatch && <Dispatcher options={options} />}
|
||||||
|
<Toolbar borderPosition="top">
|
||||||
|
{features.export && (
|
||||||
|
<Button title="Save a report" tooltipPosition="top-right">
|
||||||
|
<MdSave />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{features.export && <ExportButton />}
|
||||||
|
{features.import && <ImportButton />}
|
||||||
|
<PrintButton />
|
||||||
|
<Divider />
|
||||||
|
<MonitorSelector />
|
||||||
|
<Divider />
|
||||||
|
{features.jump && <SliderButton isOpen={this.props.sliderIsOpen} />}
|
||||||
|
{features.dispatch && (
|
||||||
|
<DispatcherButton dispatcherIsOpen={this.props.dispatcherIsOpen} />
|
||||||
|
)}
|
||||||
|
<Divider />
|
||||||
|
{!window.isElectron && position !== '#left' && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
this.openWindow('left');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdBorderLeft />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{!window.isElectron && position !== '#right' && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
this.openWindow('right');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdBorderRight />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{!window.isElectron && position !== '#bottom' && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
this.openWindow('bottom');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdBorderBottom />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{!window.isElectron && (
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
this.openWindow('remote');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<GoRadioTower />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Toolbar>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state: StoreState) => {
|
||||||
|
const instances = state.instances;
|
||||||
|
const id = getActiveInstance(instances);
|
||||||
|
return {
|
||||||
|
liftedState: instances.states[id],
|
||||||
|
monitorState: state.monitor.monitorState,
|
||||||
|
options: instances.options[id],
|
||||||
|
monitor: state.monitor.selected,
|
||||||
|
dispatcherIsOpen: state.monitor.dispatcherIsOpen,
|
||||||
|
sliderIsOpen: state.monitor.sliderIsOpen,
|
||||||
|
reports: state.reports.data,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const actionCreators = {
|
||||||
|
liftedDispatch: liftedDispatchAction,
|
||||||
|
getReport,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, actionCreators)(Actions);
|
|
@ -3,12 +3,10 @@ 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 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';
|
import { StoreState } from '@redux-devtools/app/lib/reducers';
|
||||||
import { SingleMessage } from '../middlewares/api';
|
import Actions from './Actions';
|
||||||
import { Position } from '../api/openWindow';
|
|
||||||
|
|
||||||
type StateProps = ReturnType<typeof mapStateToProps>;
|
type StateProps = ReturnType<typeof mapStateToProps>;
|
||||||
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
type DispatchProps = ResolveThunks<typeof actionCreators>;
|
||||||
|
@ -17,22 +15,7 @@ interface OwnProps {
|
||||||
}
|
}
|
||||||
type Props = StateProps & DispatchProps & OwnProps;
|
type Props = StateProps & DispatchProps & OwnProps;
|
||||||
|
|
||||||
function sendMessage(message: SingleMessage) {
|
|
||||||
chrome.runtime.sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
class App extends Component<Props> {
|
class App extends Component<Props> {
|
||||||
openWindow = (position: Position) => {
|
|
||||||
sendMessage({ type: 'OPEN', position });
|
|
||||||
};
|
|
||||||
openOptionsPage = () => {
|
|
||||||
if (navigator.userAgent.indexOf('Firefox') !== -1) {
|
|
||||||
sendMessage({ type: 'OPEN_OPTIONS' });
|
|
||||||
} else {
|
|
||||||
chrome.runtime.openOptionsPage();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { position, options, section, theme, notification } = this.props;
|
const { position, options, section, theme, notification } = this.props;
|
||||||
if (!position && (!options || !options.features)) {
|
if (!position && (!options || !options.features)) {
|
||||||
|
@ -56,7 +39,7 @@ class App extends Component<Props> {
|
||||||
body = <Settings />;
|
body = <Settings />;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
body = <Actions />;
|
body = <Actions position={position} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
// Mock not supported chrome.* API for Firefox and Electron
|
// Mock not supported chrome.* API for Firefox and Electron
|
||||||
|
|
||||||
(window as any).isElectron =
|
window.isElectron =
|
||||||
window.navigator && window.navigator.userAgent.indexOf('Electron') !== -1;
|
window.navigator && window.navigator.userAgent.indexOf('Electron') !== -1;
|
||||||
|
|
||||||
const isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;
|
const isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;
|
||||||
|
|
||||||
// Background page only
|
// Background page only
|
||||||
if (
|
if (
|
||||||
((window as any).isElectron &&
|
(window.isElectron &&
|
||||||
location.pathname === '/_generated_background_page.html') ||
|
location.pathname === '/_generated_background_page.html') ||
|
||||||
isFirefox
|
isFirefox
|
||||||
) {
|
) {
|
||||||
|
@ -18,7 +18,7 @@ if (
|
||||||
addListener() {},
|
addListener() {},
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((window as any).isElectron) {
|
if (window.isElectron) {
|
||||||
(chrome.notifications as any) = {
|
(chrome.notifications as any) = {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
addListener() {},
|
addListener() {},
|
||||||
|
@ -39,7 +39,7 @@ if (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((window as any).isElectron) {
|
if (window.isElectron) {
|
||||||
if (!chrome.storage.local || !chrome.storage.local.remove) {
|
if (!chrome.storage.local || !chrome.storage.local.remove) {
|
||||||
(chrome.storage as any).local = {
|
(chrome.storage as any).local = {
|
||||||
set(obj: any, callback: any) {
|
set(obj: any, callback: any) {
|
||||||
|
@ -87,6 +87,6 @@ if ((window as any).isElectron) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFirefox || (window as any).isElectron) {
|
if (isFirefox || window.isElectron) {
|
||||||
(chrome.storage as any).sync = chrome.storage.local;
|
(chrome.storage as any).sync = chrome.storage.local;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user