main folder

Summary: _typescript_

Reviewed By: passy

Differential Revision: D16762117

fbshipit-source-id: b6ee32e0bb3fc686fc69cfccab703e2ef4989571
This commit is contained in:
Daniel Büchele
2019-08-15 03:28:28 -07:00
committed by Facebook Github Bot
parent d68dac2ce0
commit d0da0d66a5
20 changed files with 326 additions and 530 deletions

View File

@@ -51,10 +51,10 @@
}, },
"devDependencies": { "devDependencies": {
"@jest-runner/electron": "^2.0.1", "@jest-runner/electron": "^2.0.1",
"@types/react-dom": "^16.8.5",
"@types/invariant": "^2.2.30", "@types/invariant": "^2.2.30",
"@types/jest": "^24.0.16", "@types/jest": "^24.0.16",
"@types/react": "^16.8.24", "@types/react": "^16.8.24",
"@types/react-dom": "^16.8.5",
"@types/react-redux": "^7.1.1", "@types/react-redux": "^7.1.1",
"@types/redux-persist": "^4.3.1", "@types/redux-persist": "^4.3.1",
"@types/rsocket-core": "^0.0.2", "@types/rsocket-core": "^0.0.2",
@@ -84,6 +84,7 @@
"typescript": "^3.5.2" "typescript": "^3.5.2"
}, },
"dependencies": { "dependencies": {
"@types/redux-devtools-extension": "^2.13.2",
"@types/rsocket-tcp-server": "^0.0.2", "@types/rsocket-tcp-server": "^0.0.2",
"JSONStream": "^1.3.1", "JSONStream": "^1.3.1",
"adbkit-fb": "2.10.1", "adbkit-fb": "2.10.1",

View File

@@ -160,7 +160,7 @@ function downloadIcons(buildFolder) {
copyStaticFolder(dir); copyStaticFolder(dir);
await downloadIcons(dir); await downloadIcons(dir);
await compileDefaultPlugins(path.join(dir, 'defaultPlugins')); await compileDefaultPlugins(path.join(dir, 'defaultPlugins'));
await compile(dir, path.join(__dirname, '..', 'src', 'init.js')); await compile(dir, path.join(__dirname, '..', 'src', 'init.tsx'));
const versionNumber = getVersionNumber(); const versionNumber = getVersionNumber();
const hgRevision = await genMercurialRevision(); const hgRevision = await genMercurialRevision();
modifyPackageManifest(dir, versionNumber, hgRevision); modifyPackageManifest(dir, versionNumber, hgRevision);

View File

@@ -8,22 +8,22 @@
import React from 'react'; import React from 'react';
import {FlexColumn, FlexRow} from 'flipper'; import {FlexColumn, FlexRow} from 'flipper';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import WelcomeScreen from './chrome/WelcomeScreen.tsx'; import WelcomeScreen from './chrome/WelcomeScreen';
import TitleBar from './chrome/TitleBar.tsx'; import TitleBar from './chrome/TitleBar';
import MainSidebar from './chrome/MainSidebar.tsx'; import MainSidebar from './chrome/MainSidebar';
import BugReporterDialog from './chrome/BugReporterDialog.tsx'; import BugReporterDialog from './chrome/BugReporterDialog';
import ErrorBar from './chrome/ErrorBar.tsx'; import ErrorBar from './chrome/ErrorBar';
import ShareSheet from './chrome/ShareSheet.tsx'; import ShareSheet from './chrome/ShareSheet';
import SignInSheet from './chrome/SignInSheet.tsx'; import SignInSheet from './chrome/SignInSheet';
import ExportDataPluginSheet from './chrome/ExportDataPluginSheet.tsx'; import ExportDataPluginSheet from './chrome/ExportDataPluginSheet';
import ShareSheetExportFile from './chrome/ShareSheetExportFile.tsx'; import ShareSheetExportFile from './chrome/ShareSheetExportFile';
import PluginContainer from './PluginContainer.js'; import PluginContainer from './PluginContainer';
import Sheet from './chrome/Sheet.tsx'; import Sheet from './chrome/Sheet';
import {ipcRenderer, remote} from 'electron'; import {ipcRenderer, remote} from 'electron';
import PluginDebugger from './chrome/PluginDebugger.tsx'; import PluginDebugger from './chrome/PluginDebugger';
import { import {
ShareType,
ActiveSheet, ActiveSheet,
ShareType,
ACTIVE_SHEET_BUG_REPORTER, ACTIVE_SHEET_BUG_REPORTER,
ACTIVE_SHEET_PLUGIN_DEBUGGER, ACTIVE_SHEET_PLUGIN_DEBUGGER,
ACTIVE_SHEET_SHARE_DATA, ACTIVE_SHEET_SHARE_DATA,
@@ -31,25 +31,27 @@ import {
ACTIVE_SHEET_SHARE_DATA_IN_FILE, ACTIVE_SHEET_SHARE_DATA_IN_FILE,
ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT, ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT,
ACTIVE_SHEET_PLUGIN_SHEET, ACTIVE_SHEET_PLUGIN_SHEET,
} from './reducers/application.tsx'; } from './reducers/application';
import type {Logger} from './fb-interfaces/Logger.js'; import {Logger} from './fb-interfaces/Logger.js';
import type BugReporter from './fb-stubs/BugReporter.tsx'; import BugReporter from './fb-stubs/BugReporter';
import type BaseDevice from './devices/BaseDevice.tsx'; import BaseDevice from './devices/BaseDevice';
import {State as Store} from './reducers/index';
const version = remote.app.getVersion(); const version = remote.app.getVersion();
type OwnProps = {| type OwnProps = {
logger: Logger, logger: Logger;
bugReporter: BugReporter, bugReporter: BugReporter;
|}; };
type Props = {| type StateFromProps = {
...OwnProps, leftSidebarVisible: boolean;
leftSidebarVisible: boolean, selectedDevice: BaseDevice | undefined;
selectedDevice: ?BaseDevice, error: string | null | undefined;
error: ?string, activeSheet: ActiveSheet;
activeSheet: ActiveSheet, share: ShareType | undefined;
share: ?ShareType, };
|};
type Props = StateFromProps & OwnProps;
export class App extends React.Component<Props> { export class App extends React.Component<Props> {
componentDidMount() { componentDidMount() {
@@ -67,7 +69,7 @@ export class App extends React.Component<Props> {
ipcRenderer.send('componentDidMount'); ipcRenderer.send('componentDidMount');
} }
getSheet = (onHide: () => mixed) => { getSheet = (onHide: () => any) => {
const {activeSheet} = this.props; const {activeSheet} = this.props;
switch (activeSheet) { switch (activeSheet) {
case ACTIVE_SHEET_BUG_REPORTER: case ACTIVE_SHEET_BUG_REPORTER:
@@ -124,7 +126,7 @@ export class App extends React.Component<Props> {
} }
} }
export default connect<Props, OwnProps, _, _, _, _>( export default connect<StateFromProps, {}, OwnProps, Store>(
({ ({
application: {leftSidebarVisible, activeSheet, share}, application: {leftSidebarVisible, activeSheet, share},
connections: {selectedDevice, error}, connections: {selectedDevice, error},

View File

@@ -5,39 +5,25 @@
* @format * @format
*/ */
import type {FlipperPlugin, FlipperDevicePlugin} from './plugin.tsx'; import {FlipperPlugin, FlipperDevicePlugin} from './plugin';
import {showOpenDialog} from './utils/exportData.tsx'; import {showOpenDialog} from './utils/exportData';
import { import {setSelectPluginsToExportActiveSheet} from './reducers/application';
setExportDataToFileActiveSheet, import {Store} from './reducers/';
setActiveSheet, import electron, {MenuItemConstructorOptions} from 'electron';
setSelectPluginsToExportActiveSheet, import constants from './fb-stubs/constants';
ACTIVE_SHEET_SHARE_DATA,
} from './reducers/application.tsx';
import type {Store} from './reducers/index.tsx';
import electron from 'electron';
import {constants} from 'flipper';
export type DefaultKeyboardAction = 'clear' | 'goToBottom' | 'createPaste';
export type TopLevelMenu = 'Edit' | 'View' | 'Window' | 'Help';
const {dialog} = electron.remote;
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
type MenuItem = {| export type DefaultKeyboardAction = 'clear' | 'goToBottom' | 'createPaste';
label?: string, export type TopLevelMenu = 'Edit' | 'View' | 'Window' | 'Help';
accelerator?: string, const {dialog} = electron.remote;
role?: string,
click?: Function,
submenu?: Array<MenuItem>,
type?: string,
enabled?: boolean,
|};
export type KeyboardAction = {| export type KeyboardAction = {
action: string, action: string;
label: string, label: string;
accelerator?: string, accelerator?: string;
topLevelMenu: TopLevelMenu, topLevelMenu: TopLevelMenu;
|}; };
const defaultKeyboardActions: Array<KeyboardAction> = [ const defaultKeyboardActions: Array<KeyboardAction> = [
{ {
@@ -61,7 +47,7 @@ const defaultKeyboardActions: Array<KeyboardAction> = [
export type KeyboardActions = Array<DefaultKeyboardAction | KeyboardAction>; export type KeyboardActions = Array<DefaultKeyboardAction | KeyboardAction>;
const menuItems: Map<string, Object> = new Map(); const menuItems: Map<string, electron.MenuItem> = new Map();
let pluginActionHandler; let pluginActionHandler;
function actionHandler(action: string) { function actionHandler(action: string) {
@@ -73,7 +59,7 @@ function actionHandler(action: string) {
} }
export function setupMenuBar( export function setupMenuBar(
plugins: Array<Class<FlipperPlugin<> | FlipperDevicePlugin<>>>, plugins: Array<typeof FlipperPlugin | typeof FlipperDevicePlugin>,
store: Store, store: Store,
) { ) {
const template = getTemplate( const template = getTemplate(
@@ -82,12 +68,9 @@ export function setupMenuBar(
store, store,
); );
// collect all keyboard actions from all plugins // collect all keyboard actions from all plugins
const registeredActions: Set<?KeyboardAction> = new Set( const registeredActions: Set<KeyboardAction> = new Set(
plugins plugins
.map( .map(plugin => plugin.keyboardActions || [])
(plugin: Class<FlipperPlugin<> | FlipperDevicePlugin<>>) =>
plugin.keyboardActions || [],
)
.reduce((acc: KeyboardActions, cv) => acc.concat(cv), []) .reduce((acc: KeyboardActions, cv) => acc.concat(cv), [])
.map((action: DefaultKeyboardAction | KeyboardAction) => .map((action: DefaultKeyboardAction | KeyboardAction) =>
typeof action === 'string' typeof action === 'string'
@@ -130,7 +113,7 @@ export function setupMenuBar(
function appendMenuItem( function appendMenuItem(
template: Array<MenuItemConstructorOptions>, template: Array<MenuItemConstructorOptions>,
actionHandler: (action: string) => void, actionHandler: (action: string) => void,
item: ?KeyboardAction, item: KeyboardAction,
) { ) {
const keyboardAction = item; const keyboardAction = item;
if (keyboardAction == null) { if (keyboardAction == null) {
@@ -140,7 +123,7 @@ function appendMenuItem(
menu => menu.label === keyboardAction.topLevelMenu, menu => menu.label === keyboardAction.topLevelMenu,
); );
if (itemIndex > -1 && template[itemIndex].submenu != null) { if (itemIndex > -1 && template[itemIndex].submenu != null) {
template[itemIndex].submenu.push({ (template[itemIndex].submenu as MenuItemConstructorOptions[]).push({
click: () => actionHandler(keyboardAction.action), click: () => actionHandler(keyboardAction.action),
label: keyboardAction.label, label: keyboardAction.label,
accelerator: keyboardAction.accelerator, accelerator: keyboardAction.accelerator,
@@ -150,7 +133,9 @@ function appendMenuItem(
} }
export function activateMenuItems( export function activateMenuItems(
activePlugin: FlipperPlugin<> | FlipperDevicePlugin<>, activePlugin:
| FlipperPlugin<any, any, any>
| FlipperDevicePlugin<any, any, any>,
) { ) {
// disable all keyboard actions // disable all keyboard actions
for (const item of menuItems) { for (const item of menuItems) {
@@ -183,15 +168,15 @@ export function activateMenuItems(
} }
function getTemplate( function getTemplate(
app: Object, app: electron.App,
shell: Object, shell: electron.Shell,
store: Store, store: Store,
): Array<MenuItemConstructorOptions> { ): Array<MenuItemConstructorOptions> {
const exportSubmenu = [ const exportSubmenu = [
{ {
label: 'File...', label: 'File...',
accelerator: 'CommandOrControl+E', accelerator: 'CommandOrControl+E',
click: function(item: Object, focusedWindow: Object) { click: function() {
dialog.showSaveDialog( dialog.showSaveDialog(
null, null,
{ {
@@ -214,20 +199,20 @@ function getTemplate(
exportSubmenu.push({ exportSubmenu.push({
label: 'Sharable Link', label: 'Sharable Link',
accelerator: 'CommandOrControl+Shift+E', accelerator: 'CommandOrControl+Shift+E',
click: async function(item: Object, focusedWindow: Object) { click: function() {
store.dispatch(setSelectPluginsToExportActiveSheet({type: 'link'})); store.dispatch(setSelectPluginsToExportActiveSheet({type: 'link'}));
}, },
}); });
} }
const template = [ const template: MenuItemConstructorOptions[] = [
{ {
label: 'File', label: 'File',
submenu: [ submenu: [
{ {
label: 'Open File...', label: 'Open File...',
accelerator: 'CommandOrControl+O', accelerator: 'CommandOrControl+O',
click: function(item: Object, focusedWindow: Object) { click: function() {
showOpenDialog(store); showOpenDialog(store);
}, },
}, },
@@ -281,7 +266,10 @@ function getTemplate(
{ {
label: 'Reload', label: 'Reload',
accelerator: 'CmdOrCtrl+R', accelerator: 'CmdOrCtrl+R',
click: function(item: Object, focusedWindow: Object) { click: function(
_,
focusedWindow: electron.BrowserWindow | undefined,
) {
if (focusedWindow) { if (focusedWindow) {
focusedWindow.reload(); focusedWindow.reload();
} }
@@ -296,7 +284,10 @@ function getTemplate(
return 'F11'; return 'F11';
} }
})(), })(),
click: function(item: Object, focusedWindow: Object) { click: function(
_,
focusedWindow: electron.BrowserWindow | undefined,
) {
if (focusedWindow) { if (focusedWindow) {
focusedWindow.setFullScreen(!focusedWindow.isFullScreen()); focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
} }
@@ -311,8 +302,12 @@ function getTemplate(
return 'Ctrl+Shift+I'; return 'Ctrl+Shift+I';
} }
})(), })(),
click: function(item: Object, focusedWindow: Object) { click: function(
_,
focusedWindow: electron.BrowserWindow | undefined,
) {
if (focusedWindow) { if (focusedWindow) {
// @ts-ignore: https://github.com/electron/electron/issues/7832
focusedWindow.toggleDevTools(); focusedWindow.toggleDevTools();
} }
}, },
@@ -414,11 +409,11 @@ function getTemplate(
}, },
], ],
}); });
const windowMenu = template.find(function(m: Object) { const windowMenu = template.find(function(m) {
return m.role === 'window'; return m.role === 'window';
}); });
if (windowMenu) { if (windowMenu) {
windowMenu.submenu.push( (windowMenu.submenu as MenuItemConstructorOptions[]).push(
{ {
type: 'separator', type: 'separator',
}, },

View File

@@ -5,17 +5,9 @@
* @format * @format
*/ */
import type { import {SearchableProps, FlipperBasePlugin, FlipperPlugin} from 'flipper';
SearchableProps, import {Logger} from './fb-interfaces/Logger';
FlipperBasePlugin,
FlipperPlugin,
Device,
} from 'flipper';
import type {PluginNotification} from './reducers/notifications.tsx';
import type {Logger} from './fb-interfaces/Logger';
import { import {
FlipperDevicePlugin,
Searchable, Searchable,
Button, Button,
ButtonGroup, ButtonGroup,
@@ -27,30 +19,38 @@ import {
styled, styled,
colors, colors,
} from 'flipper'; } from 'flipper';
import {FlipperDevicePlugin, BaseAction} from './plugin';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import React, {Component, Fragment} from 'react'; import React, {Component, Fragment} from 'react';
import {clipboard} from 'electron'; import {clipboard} from 'electron';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { import {
PluginNotification,
clearAllNotifications, clearAllNotifications,
updatePluginBlacklist, updatePluginBlacklist,
updateCategoryBlacklist, updateCategoryBlacklist,
} from './reducers/notifications.tsx'; } from './reducers/notifications';
import {selectPlugin} from './reducers/connections.tsx'; import {selectPlugin} from './reducers/connections';
import {textContent} from './utils/index.tsx'; import {State as Store} from './reducers/index';
import createPaste from './fb-stubs/createPaste.tsx'; import textContent from './utils/textContent';
import createPaste from './fb-stubs/createPaste';
import {KeyboardActions} from './MenuBar';
export default class Notifications extends FlipperDevicePlugin<{}> { export default class Notifications<
S,
A extends BaseAction,
P
> extends FlipperDevicePlugin<S, A, P> {
static id = 'notifications'; static id = 'notifications';
static title = 'Notifications'; static title = 'Notifications';
static icon = 'bell'; static icon = 'bell';
static keyboardActions = ['clear']; static keyboardActions: KeyboardActions = ['clear'];
static contextTypes = { static contextTypes = {
store: PropTypes.object.isRequired, store: PropTypes.object.isRequired,
}; };
static supportsDevice(device: Device) { static supportsDevice() {
return false; return false;
} }
@@ -99,33 +99,36 @@ export default class Notifications extends FlipperDevicePlugin<{}> {
} }
} }
type OwnProps = {| type OwnProps = {
...SearchableProps, onClear: () => void;
onClear: () => void, selectedID: string | null | undefined;
selectedID: ?string, logger: Logger;
logger: Logger, } & SearchableProps;
|};
type Props = {| type StateFromProps = {
...OwnProps, activeNotifications: Array<PluginNotification>;
activeNotifications: Array<PluginNotification>, invalidatedNotifications: Array<PluginNotification>;
invalidatedNotifications: Array<PluginNotification>, blacklistedPlugins: Array<string>;
blacklistedPlugins: Array<string>, blacklistedCategories: Array<string>;
blacklistedCategories: Array<string>, devicePlugins: Map<string, typeof FlipperDevicePlugin>;
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>, clientPlugins: Map<string, typeof FlipperPlugin>;
clientPlugins: Map<string, Class<FlipperPlugin<>>>, };
updatePluginBlacklist: (blacklist: Array<string>) => mixed,
updateCategoryBlacklist: (blacklist: Array<string>) => mixed,
selectPlugin: (payload: {|
selectedPlugin: ?string,
selectedApp: ?string,
deepLinkPayload: ?string,
|}) => mixed,
|};
type State = {| type DispatchFromProps = {
selectedNotification: ?string, selectPlugin: (payload: {
|}; selectedPlugin: string | null | undefined;
selectedApp: string | null | undefined;
deepLinkPayload: string | null | undefined;
}) => any;
updatePluginBlacklist: (blacklist: Array<string>) => any;
updateCategoryBlacklist: (blacklist: Array<string>) => any;
};
type Props = OwnProps & StateFromProps & DispatchFromProps;
type State = {
selectedNotification: string | null | undefined;
};
const Content = styled(FlexColumn)({ const Content = styled(FlexColumn)({
padding: '0 10px', padding: '0 10px',
@@ -327,7 +330,12 @@ class NotificationsTable extends Component<Props, State> {
} }
} }
const ConnectedNotificationsTable = connect<Props, OwnProps, _, _, _, _>( const ConnectedNotificationsTable = connect<
StateFromProps,
DispatchFromProps,
OwnProps,
Store
>(
({ ({
notifications: { notifications: {
activeNotifications, activeNotifications,
@@ -351,7 +359,10 @@ const ConnectedNotificationsTable = connect<Props, OwnProps, _, _, _, _>(
}, },
)(Searchable(NotificationsTable)); )(Searchable(NotificationsTable));
const shadow = (props, hover) => { const shadow = (
props: {isSelected?: boolean; inactive?: boolean},
_hover?: boolean,
) => {
if (props.inactive) { if (props.inactive) {
return `inset 0 0 0 1px ${colors.light10}`; return `inset 0 0 0 1px ${colors.light10}`;
} }
@@ -448,27 +459,30 @@ const NotificationButton = styled('div')({
}); });
type ItemProps = { type ItemProps = {
...PluginNotification, onHighlight?: () => any;
onHighlight?: () => mixed, onHidePlugin?: () => any;
onHidePlugin?: () => mixed, onHideCategory?: () => any;
onHideCategory?: () => mixed, onClear?: () => any;
isSelected?: boolean, isSelected?: boolean;
inactive?: boolean, inactive?: boolean;
selectPlugin?: (payload: {| selectPlugin?: (payload: {
selectedPlugin: ?string, selectedPlugin: string | null | undefined;
selectedApp: ?string, selectedApp: string | null | undefined;
deepLinkPayload: ?string, deepLinkPayload: string | null | undefined;
|}) => mixed, }) => any;
logger?: Logger, logger?: Logger;
plugin: ?Class<FlipperBasePlugin<>>, plugin: typeof FlipperBasePlugin | null | undefined;
}; };
type ItemState = {| type ItemState = {
reportedNotHelpful: boolean, reportedNotHelpful: boolean;
|}; };
class NotificationItem extends Component<ItemProps, ItemState> { class NotificationItem extends Component<
constructor(props: ItemProps) { ItemProps & PluginNotification,
ItemState
> {
constructor(props: ItemProps & PluginNotification) {
super(props); super(props);
const items = []; const items = [];
if (props.onHidePlugin && props.plugin) { if (props.onHidePlugin && props.plugin) {
@@ -566,7 +580,7 @@ class NotificationItem extends Component<ItemProps, ItemState> {
isSelected={isSelected} isSelected={isSelected}
inactive={inactive} inactive={inactive}
items={this.contextMenuItems}> items={this.contextMenuItems}>
<Glyph name={plugin?.icon || 'bell'} size={12} /> <Glyph name={(plugin ? plugin.icon : 'bell') || 'bell'} size={12} />
<NotificationContent isSelected={isSelected}> <NotificationContent isSelected={isSelected}>
<Title>{notification.title}</Title> <Title>{notification.title}</Title>
{notification.message} {notification.message}

View File

@@ -4,27 +4,30 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
* @format * @format
*/ */
import type {FlipperPlugin, FlipperDevicePlugin} from './plugin.tsx'; import {
import type {Logger} from './fb-interfaces/Logger'; FlipperPlugin,
import type {Props as PluginProps} from './plugin.tsx'; FlipperDevicePlugin,
import {pluginKey as getPluginKey} from './reducers/pluginStates.tsx'; Props as PluginProps,
import Client from './Client.tsx'; } from './plugin';
import BaseDevice from './devices/BaseDevice.tsx'; import {Logger} from './fb-interfaces/Logger';
import BaseDevice from './devices/BaseDevice';
import {pluginKey as getPluginKey} from './reducers/pluginStates';
import Client from './Client';
import { import {
ErrorBoundary, ErrorBoundary,
PureComponent,
FlexColumn, FlexColumn,
FlexRow, FlexRow,
colors, colors,
styled, styled,
ArchivedDevice, ArchivedDevice,
} from 'flipper'; } from 'flipper';
import React from 'react'; import React, {PureComponent} from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {setPluginState} from './reducers/pluginStates.tsx'; import {setPluginState} from './reducers/pluginStates';
import {selectPlugin} from './reducers/connections.tsx'; import {selectPlugin} from './reducers/connections';
import {State as Store} from './reducers/index';
import NotificationsHub from './NotificationsHub'; import NotificationsHub from './NotificationsHub';
import {activateMenuItems} from './MenuBar.js'; import {activateMenuItems} from './MenuBar';
const Container = styled(FlexColumn)({ const Container = styled(FlexColumn)({
width: 0, width: 0,
@@ -39,34 +42,48 @@ const SidebarContainer = styled(FlexRow)({
overflow: 'scroll', overflow: 'scroll',
}); });
type OwnProps = {| type OwnProps = {
logger: Logger, logger: Logger;
|}; };
type Props = {| type StateFromProps = {
...OwnProps, pluginState: Object;
pluginState: Object, activePlugin: typeof FlipperPlugin | typeof FlipperDevicePlugin;
activePlugin: ?Class<FlipperPlugin<> | FlipperDevicePlugin<>>, target: Client | BaseDevice | null;
target: Client | BaseDevice | null, pluginKey: string | null | undefined;
pluginKey: ?string, deepLinkPayload: string | null | undefined;
deepLinkPayload: ?string, selectedApp: string | null | undefined;
selectedApp: ?string, isArchivedDevice: boolean;
selectPlugin: (payload: {| };
selectedPlugin: ?string,
selectedApp?: ?string, type DispatchFromProps = {
deepLinkPayload: ?string, selectPlugin: (payload: {
|}) => mixed, selectedPlugin: string | null | undefined;
selectedApp?: string | null | undefined;
deepLinkPayload: string | null | undefined;
}) => any;
setPluginState: (payload: { setPluginState: (payload: {
pluginKey: string, pluginKey: string;
state: Object, state: Partial<Object>;
}) => void, }) => void;
isArchivedDevice: boolean, };
|};
type Props = StateFromProps & DispatchFromProps & OwnProps;
class PluginContainer extends PureComponent<Props> { class PluginContainer extends PureComponent<Props> {
plugin: ?FlipperPlugin<> | FlipperDevicePlugin<>; plugin:
| FlipperPlugin<any, any, any>
| FlipperDevicePlugin<any, any, any>
| null
| undefined;
refChanged = (ref: ?FlipperPlugin<> | FlipperDevicePlugin<>) => { refChanged = (
ref:
| FlipperPlugin<any, any, any>
| FlipperDevicePlugin<any, any, any>
| null
| undefined,
) => {
if (this.plugin) { if (this.plugin) {
this.plugin._teardown(); this.plugin._teardown();
this.plugin = null; this.plugin = null;
@@ -100,7 +117,16 @@ class PluginContainer extends PureComponent<Props> {
console.warn(`No selected plugin. Rendering empty!`); console.warn(`No selected plugin. Rendering empty!`);
return null; return null;
} }
const props: PluginProps<Object> = { const props: PluginProps<Object> & {
key: string;
ref: (
ref:
| FlipperPlugin<any, any, any>
| FlipperDevicePlugin<any, any, any>
| null
| undefined,
) => void;
} = {
key: pluginKey, key: pluginKey,
logger: this.props.logger, logger: this.props.logger,
selectedApp, selectedApp,
@@ -113,7 +139,10 @@ class PluginContainer extends PureComponent<Props> {
setPersistedState: state => setPluginState({pluginKey, state}), setPersistedState: state => setPluginState({pluginKey, state}),
target, target,
deepLinkPayload: this.props.deepLinkPayload, deepLinkPayload: this.props.deepLinkPayload,
selectPlugin: (pluginID: string, deepLinkPayload: ?string) => { selectPlugin: (
pluginID: string,
deepLinkPayload: string | null | undefined,
) => {
const {target} = this.props; const {target} = this.props;
// check if plugin will be available // check if plugin will be available
if ( if (
@@ -148,9 +177,8 @@ class PluginContainer extends PureComponent<Props> {
} }
} }
export default connect<Props, OwnProps, _, _, _, _>( export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
({ ({
application: {rightSidebarVisible, rightSidebarAvailable},
connections: { connections: {
selectedPlugin, selectedPlugin,
selectedDevice, selectedDevice,
@@ -163,7 +191,10 @@ export default connect<Props, OwnProps, _, _, _, _>(
}) => { }) => {
let pluginKey = null; let pluginKey = null;
let target = null; let target = null;
let activePlugin: ?Class<FlipperPlugin<> | FlipperDevicePlugin<>> = null; let activePlugin:
| typeof FlipperDevicePlugin
| typeof FlipperPlugin
| null = null;
if (selectedPlugin) { if (selectedPlugin) {
if (selectedPlugin === NotificationsHub.id) { if (selectedPlugin === NotificationsHub.id) {
@@ -185,6 +216,7 @@ export default connect<Props, OwnProps, _, _, _, _>(
const isArchivedDevice = !selectedDevice const isArchivedDevice = !selectedDevice
? false ? false
: selectedDevice instanceof ArchivedDevice; : selectedDevice instanceof ArchivedDevice;
return { return {
pluginState: pluginStates[pluginKey], pluginState: pluginStates[pluginKey],
activePlugin, activePlugin,

View File

@@ -5,13 +5,13 @@
* @format * @format
*/ */
import React from 'react'; import React from 'react';
import {App} from '../App.js'; import {App} from '../App';
import {Provider} from 'react-redux'; import {Provider} from 'react-redux';
import renderer from 'react-test-renderer'; import renderer from 'react-test-renderer';
import reducers from '../reducers/index.tsx'; import reducers from '../reducers/index';
import configureStore from 'redux-mock-store'; import configureStore from 'redux-mock-store';
import {init as initLogger} from '../fb-stubs/Logger.tsx'; import {init as initLogger} from '../fb-stubs/Logger';
import BugReporter from '../fb-stubs/BugReporter.tsx'; import BugReporter from '../fb-stubs/BugReporter';
// create redux store with initial state // create redux store with initial state
const mockStore = configureStore([])(reducers(undefined, {type: 'INIT'})); const mockStore = configureStore([])(reducers(undefined, {type: 'INIT'}));

View File

@@ -1,254 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Empty app state matches snapshot 1`] = `
<div
className="css-1si6n3e"
>
<div
className="toolbar css-78eqwq"
>
<div
className="css-q7gju5"
onClick={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
>
<div
className="css-1h9aj9a"
color="#acacac"
size={12}
src="https://external.xx.fbcdn.net/assets/?name=minus-circle&variant=filled&size=12&set=facebook_icons&density=1x"
/>
No device selected
</div>
<div
className="css-1ayt83l"
>
<div
className="css-z34oxs"
disabled={true}
onClick={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
title="Take Screenshot"
>
<div
className="css-1dg3xuk"
color="#acacac"
size={12}
src="https://external.xx.fbcdn.net/assets/?name=camera&variant=filled&size=12&set=facebook_icons&density=1x"
/>
</div>
<div
className="css-z34oxs"
disabled={true}
onClick={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
title="Make Screen Recording"
>
<div
className="css-wvm62d"
color="#acacac"
size={12}
src="https://external.xx.fbcdn.net/assets/?name=camcorder&variant=filled&size=12&set=facebook_icons&density=1x"
/>
</div>
</div>
<div
className="css-12zzrdt"
/>
<span
className="css-1swhxtd"
onClick={[Function]}
>
5.0.8-dev
</span>
<div
className="css-1cecbfb"
onClick={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
title="Report Bug"
>
<div
className="css-1idwz0j"
color="#acacac"
size={12}
src="https://external.xx.fbcdn.net/assets/?name=bug&variant=filled&size=12&set=facebook_icons&density=1x"
/>
</div>
<div
className="css-1ayt83l"
>
<div
className="css-u1e6jr"
onClick={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
title="Toggle Plugins"
>
<div
className="css-2bfl92"
color="#80a6f5"
size={20}
src="icons/sidebar_left.svg"
/>
</div>
<div
className="css-z34oxs"
disabled={true}
onClick={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
title="Toggle Details"
>
<div
className="css-j5i4pm"
color="#acacac"
size={20}
src="icons/sidebar_right.svg"
/>
</div>
</div>
</div>
<div
className="css-v6xy5u"
>
<div
id="pluginSheetContents"
style={
Object {
"display": "none",
}
}
/>
</div>
<div
className="css-9qtipk"
>
<div
className="css-1atbcdi"
>
<div
className="css-1hs1k35"
>
<img
className="css-1yl4k4p"
src="./icon.png"
/>
<span
className="css-p2pwny"
>
Welcome to Flipper
</span>
<span
className="css-1xkgddx"
>
Development Mode
</span>
<div
className="css-ls6p57"
onClick={[Function]}
>
<div
className="css-1hjpcq0"
color="#8155cb"
size={20}
src="https://external.xx.fbcdn.net/assets/?name=rocket&variant=filled&size=20&set=facebook_icons&density=1x"
/>
<div
className="css-1k4677w"
>
<span
className="css-1jw94dh"
>
Using Flipper
</span>
<span
className="css-bcc6f5"
>
Learn how Flipper can help you debug your App
</span>
</div>
</div>
<div
className="css-ls6p57"
onClick={[Function]}
>
<div
className="css-yfo7mj"
color="#8155cb"
size={20}
src="https://external.xx.fbcdn.net/assets/?name=magic-wand&variant=filled&size=20&set=facebook_icons&density=1x"
/>
<div
className="css-1k4677w"
>
<span
className="css-1jw94dh"
>
Create your own plugin
</span>
<span
className="css-bcc6f5"
>
Get started with these pointers
</span>
</div>
</div>
<div
className="css-ls6p57"
onClick={[Function]}
>
<div
className="css-4qdej8"
color="#8155cb"
size={20}
src="https://external.xx.fbcdn.net/assets/?name=tools&variant=filled&size=20&set=facebook_icons&density=1x"
/>
<div
className="css-1k4677w"
>
<span
className="css-1jw94dh"
>
Add Flipper support to your app
</span>
<span
className="css-bcc6f5"
>
Get started with these pointers
</span>
</div>
</div>
<div
className="css-ls6p57"
onClick={[Function]}
>
<div
className="css-l82yfp"
color="#8155cb"
size={20}
src="https://external.xx.fbcdn.net/assets/?name=posts&variant=filled&size=20&set=facebook_icons&density=1x"
/>
<div
className="css-1k4677w"
>
<span
className="css-1jw94dh"
>
Contributing and Feedback
</span>
<span
className="css-bcc6f5"
>
Report issues and help us improve Flipper
</span>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@@ -5,31 +5,27 @@
* @format * @format
*/ */
import {createTablePlugin} from '../createTablePlugin.js'; import {createTablePlugin} from '../createTablePlugin';
import {FlipperPlugin} from '../plugin';
import type {TableRows_immutable} from 'flipper';
//import type {PersistedState, RowData} from '../createTablePlugin.js';
import {FlipperPlugin} from '../plugin.tsx';
import {List, Map as ImmutableMap} from 'immutable'; import {List, Map as ImmutableMap} from 'immutable';
import {TableRows_immutable} from '../ui/components/table/types.js';
const PROPS = { const PROPS = {
method: 'method', method: 'method',
resetMethod: 'resetMethod', resetMethod: 'resetMethod',
columns: {}, columns: {},
columnSizes: {}, columnSizes: {},
renderSidebar: (r: {id: string}) => {}, renderSidebar: () => {},
buildRow: (r: {id: string}) => {}, buildRow: () => {},
}; };
type PersistedState<T> = {| type PersistedState<T> = {
rows: TableRows_immutable, rows: TableRows_immutable;
datas: ImmutableMap<string, T>, datas: ImmutableMap<string, T>;
|}; };
type RowData = { type RowData = {
id: string, id: string;
}; };
test('createTablePlugin returns FlipperPlugin', () => { test('createTablePlugin returns FlipperPlugin', () => {
@@ -55,8 +51,9 @@ test('persistedStateReducer is resetting data', () => {
]), ]),
}; };
// $FlowFixMe persistedStateReducer exists for createTablePlugin const {rows, datas} = tablePlugin.persistedStateReducer(ps, resetMethod, {
const {rows, datas} = tablePlugin.persistedStateReducer(ps, resetMethod, {}); id: '0',
});
expect(datas.toJSON()).toEqual({}); expect(datas.toJSON()).toEqual({});
expect(rows.size).toBe(0); expect(rows.size).toBe(0);

View File

@@ -29,7 +29,7 @@ import {
LoadingIndicator, LoadingIndicator,
} from 'flipper'; } from 'flipper';
import React, {Component, PureComponent} from 'react'; import React, {Component, PureComponent} from 'react';
import NotificationsHub from '../NotificationsHub.js'; import NotificationsHub from '../NotificationsHub';
import {selectPlugin} from '../reducers/connections'; import {selectPlugin} from '../reducers/connections';
import {setActiveSheet} from '../reducers/application'; import {setActiveSheet} from '../reducers/application';
import UserAccount from './UserAccount'; import UserAccount from './UserAccount';

View File

@@ -5,46 +5,46 @@
* @format * @format
*/ */
import type { import {
TableHighlightedRows, TableHighlightedRows,
TableRows_immutable, TableRows_immutable,
TableColumnSizes, TableColumnSizes,
TableColumns, TableColumns,
} from 'flipper'; } from 'flipper';
import FlexColumn from './ui/components/FlexColumn'; import FlexColumn from './ui/components/FlexColumn';
import Button from './ui/components/Button'; import Button from './ui/components/Button';
import DetailSidebar from './chrome/DetailSidebar.tsx'; import DetailSidebar from './chrome/DetailSidebar';
import {FlipperPlugin} from './plugin.tsx'; import {FlipperPlugin} from './plugin';
import SearchableTable_immutable from './ui/components/searchable/SearchableTable_immutable'; import SearchableTable_immutable from './ui/components/searchable/SearchableTable_immutable';
import textContent from './utils/textContent.tsx'; import textContent from './utils/textContent';
import createPaste from './fb-stubs/createPaste.tsx'; import createPaste from './fb-stubs/createPaste';
import {List, Map as ImmutableMap} from 'immutable'; import {List, Map as ImmutableMap} from 'immutable';
import React from 'react';
import {KeyboardActions} from './MenuBar';
type ID = string; type ID = string;
export type RowData = { export interface RowData {
id: ID, id: ID;
}
type Props<T> = {
method: string;
resetMethod?: string;
columns: TableColumns;
columnSizes: TableColumnSizes;
renderSidebar: (row: T) => any;
buildRow: (row: T) => any;
}; };
type Props<T> = {| export type PersistedState<T> = {
method: string, rows: TableRows_immutable;
resetMethod?: string, datas: ImmutableMap<ID, T>;
columns: TableColumns, };
columnSizes: TableColumnSizes,
renderSidebar: (row: T) => any,
buildRow: (row: T) => any,
|};
export type PersistedState<T> = {| type State = {
rows: TableRows_immutable, selectedIds: Array<ID>;
datas: ImmutableMap<ID, T>, };
|};
type State = {|
selectedIds: Array<ID>,
|};
/** /**
* createTablePlugin creates a Plugin class which handles fetching data from the client and * createTablePlugin creates a Plugin class which handles fetching data from the client and
@@ -59,9 +59,10 @@ type State = {|
* data provided. This is useful when connecting to Flipper for this first time, or reconnecting to * data provided. This is useful when connecting to Flipper for this first time, or reconnecting to
* the client in an unknown state. * the client in an unknown state.
*/ */
export function createTablePlugin<T: RowData>(props: Props<T>) { export function createTablePlugin<T extends RowData>(props: Props<T>) {
return class extends FlipperPlugin<State, *, PersistedState<*>> { // @ts-ignore
static keyboardActions = ['clear', 'createPaste']; return class extends FlipperPlugin<State, any, PersistedState<T>> {
static keyboardActions: KeyboardActions = ['clear', 'createPaste'];
static defaultPersistedState = { static defaultPersistedState = {
rows: List(), rows: List(),
@@ -69,13 +70,13 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
}; };
static persistedStateReducer = ( static persistedStateReducer = (
persistedState: PersistedState<*>, persistedState: PersistedState<T>,
method: string, method: string,
payload: T | Array<T>, payload: T | Array<T>,
): $Shape<PersistedState<T>> => { ): Partial<PersistedState<T>> => {
if (method === props.method) { if (method === props.method) {
return List(Array.isArray(payload) ? payload : [payload]).reduce( return List(Array.isArray(payload) ? payload : [payload]).reduce(
(ps: PersistedState<*>, data: T) => { (ps: PersistedState<any>, data: T) => {
if (data.id == null) { if (data.id == null) {
console.warn('The data sent did not contain an ID.', data); console.warn('The data sent did not contain an ID.', data);
} }

View File

@@ -20,7 +20,6 @@ test('test parsing of deeplink URL when arguments are less', () => {
}); });
test('test parsing of deeplink URL when url is null', () => { test('test parsing of deeplink URL when url is null', () => {
// $FlowFixMe
const components = uriComponents(null); const components = uriComponents(null);
expect(components).toEqual([]); expect(components).toEqual([]);
}); });

View File

@@ -122,10 +122,7 @@ test('requirePlugin loads plugin', () => {
homepage, homepage,
out: path.join(__dirname, 'TestPlugin.js'), out: path.join(__dirname, 'TestPlugin.js'),
}); });
// $FlowFixMe
expect(plugin.prototype).toBeInstanceOf(FlipperPlugin); expect(plugin.prototype).toBeInstanceOf(FlipperPlugin);
// $FlowFixMe
expect(plugin.homepage).toBe(homepage); expect(plugin.homepage).toBe(homepage);
// $FlowFixMe
expect(plugin.id).toBe(TestPlugin.id); expect(plugin.id).toBe(TestPlugin.id);
}); });

View File

@@ -9,7 +9,6 @@ import {Store} from '../reducers/index';
import {Logger} from '../fb-interfaces/Logger.js'; import {Logger} from '../fb-interfaces/Logger.js';
import {FlipperPlugin, FlipperDevicePlugin} from '../plugin'; import {FlipperPlugin, FlipperDevicePlugin} from '../plugin';
import {State} from '../reducers/plugins'; import {State} from '../reducers/plugins';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import * as Flipper from '../index.js'; import * as Flipper from '../index.js';
@@ -22,7 +21,7 @@ import {
import {remote} from 'electron'; import {remote} from 'electron';
import GK from '../fb-stubs/GK'; import GK from '../fb-stubs/GK';
import {FlipperBasePlugin} from '../plugin'; import {FlipperBasePlugin} from '../plugin';
import {setupMenuBar} from '../MenuBar.js'; import {setupMenuBar} from '../MenuBar';
import path from 'path'; import path from 'path';
import {default as config} from '../utils/processConfig'; import {default as config} from '../utils/processConfig';
import isProduction from '../utils/isProduction'; import isProduction from '../utils/isProduction';

View File

@@ -38,7 +38,7 @@ export {
} from './devices/BaseDevice.tsx'; } from './devices/BaseDevice.tsx';
export {shouldParseAndroidLog} from './utils/crashReporterUtility.tsx'; export {shouldParseAndroidLog} from './utils/crashReporterUtility.tsx';
export {default as isProduction} from './utils/isProduction.tsx'; export {default as isProduction} from './utils/isProduction.tsx';
export {createTablePlugin} from './createTablePlugin.js'; export {createTablePlugin} from './createTablePlugin.tsx';
export {default as DetailSidebar} from './chrome/DetailSidebar.tsx'; export {default as DetailSidebar} from './chrome/DetailSidebar.tsx';
export {default as Device} from './devices/BaseDevice.tsx'; export {default as Device} from './devices/BaseDevice.tsx';

View File

@@ -8,30 +8,34 @@
import {Provider} from 'react-redux'; import {Provider} from 'react-redux';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import {useState, useEffect} from 'react'; import {useState, useEffect} from 'react';
import {ContextMenuProvider} from 'flipper'; import ContextMenuProvider from './ui/components/ContextMenuProvider.js';
import GK from './fb-stubs/GK.tsx'; import GK from './fb-stubs/GK';
import {init as initLogger} from './fb-stubs/Logger.tsx'; import {init as initLogger} from './fb-stubs/Logger';
import App from './App.js'; import App from './App';
import BugReporter from './fb-stubs/BugReporter.tsx'; import BugReporter from './fb-stubs/BugReporter';
import setupPrefetcher from './fb-stubs/Prefetcher.tsx'; import setupPrefetcher from './fb-stubs/Prefetcher';
import {createStore} from 'redux'; import {createStore} from 'redux';
import {persistStore} from 'redux-persist'; import {persistStore} from 'redux-persist';
import reducers from './reducers/index.tsx'; import reducers, {Actions, State as StoreState} from './reducers/index';
import dispatcher from './dispatcher/index.tsx'; import dispatcher from './dispatcher/index';
import TooltipProvider from './ui/components/TooltipProvider.js'; import TooltipProvider from './ui/components/TooltipProvider.js';
import config from './utils/processConfig.tsx'; import config from './utils/processConfig';
import {stateSanitizer} from './utils/reduxDevToolsConfig.tsx'; import {stateSanitizer} from './utils/reduxDevToolsConfig';
import {initLauncherHooks} from './utils/launcher.tsx'; import {initLauncherHooks} from './utils/launcher';
import initCrashReporter from './utils/electronCrashReporter.tsx'; import initCrashReporter from './utils/electronCrashReporter';
import fbConfig from './fb-stubs/config.tsx'; import fbConfig from './fb-stubs/config';
import {isFBEmployee} from './utils/fbEmployee.js'; import {isFBEmployee} from './utils/fbEmployee.js';
import path from 'path'; import WarningEmployee from './chrome/WarningEmployee';
import WarningEmployee from './chrome/WarningEmployee.tsx'; import React from 'react';
const store = createStore( const store = createStore<StoreState, Actions, any, any>(
reducers, reducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__
window.__REDUX_DEVTOOLS_EXTENSION__({stateSanitizer}), ? window.__REDUX_DEVTOOLS_EXTENSION__({
// @ts-ignore
stateSanitizer,
})
: undefined,
); );
const logger = initLogger(store); const logger = initLogger(store);
@@ -55,7 +59,7 @@ const AppFrame = () => {
<Provider store={store}> <Provider store={store}>
{warnEmployee ? ( {warnEmployee ? (
<WarningEmployee <WarningEmployee
onClick={e => { onClick={() => {
setWarnEmployee(false); setWarnEmployee(false);
}} }}
/> />
@@ -69,13 +73,12 @@ const AppFrame = () => {
}; };
function init() { function init() {
// $FlowFixMe: this element exists!
ReactDOM.render(<AppFrame />, document.getElementById('root')); ReactDOM.render(<AppFrame />, document.getElementById('root'));
initLauncherHooks(config(), store); initLauncherHooks(config(), store);
const sessionId = store.getState().application.sessionId; const sessionId = store.getState().application.sessionId;
initCrashReporter(sessionId || ''); initCrashReporter(sessionId || '');
requestIdleCallback(() => { window.requestIdleCallback(() => {
setupPrefetcher(); setupPrefetcher();
}); });
} }

View File

@@ -33,7 +33,7 @@ import storage from 'redux-persist/lib/storage/index.js';
import {Store as ReduxStore, MiddlewareAPI as ReduxMiddlewareAPI} from 'redux'; import {Store as ReduxStore, MiddlewareAPI as ReduxMiddlewareAPI} from 'redux';
type Actions = export type Actions =
| ApplicationAction | ApplicationAction
| DevicesAction | DevicesAction
| PluginStatesAction | PluginStatesAction

View File

@@ -173,7 +173,6 @@ test('test processStore function for an iOS device connected', async () => {
selectedPlugins: [], selectedPlugins: [],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
// $FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {device, clients} = json; const {device, clients} = json;
expect(device).toBeDefined(); expect(device).toBeDefined();
expect(clients).toEqual([]); expect(clients).toEqual([]);
@@ -206,7 +205,6 @@ test('test processStore function for an iOS device connected with client plugin
selectedPlugins: [], selectedPlugins: [],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const expectedPluginState = { const expectedPluginState = {
[generateClientIdentifierWithSalt(clientIdentifier, 'salt')]: { [generateClientIdentifierWithSalt(clientIdentifier, 'salt')]: {
@@ -265,7 +263,6 @@ test('test processStore function to have only the client for the selected device
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already added
const {clients} = json; const {clients} = json;
const {pluginStates} = json.store; const {pluginStates} = json.store;
const expectedPluginState = { const expectedPluginState = {
@@ -321,7 +318,6 @@ test('test processStore function to have multiple clients for the selected devic
selectedPlugins: [], selectedPlugins: [],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already added
const {clients} = json; const {clients} = json;
const {pluginStates} = json.store; const {pluginStates} = json.store;
const expectedPluginState = { const expectedPluginState = {
@@ -364,7 +360,6 @@ test('test processStore function for device plugin state and no clients', async
selectedPlugins: [], selectedPlugins: [],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const {clients} = json; const {clients} = json;
const expectedPluginState = { const expectedPluginState = {
@@ -397,7 +392,6 @@ test('test processStore function for unselected device plugin state and no clien
selectedPlugins: [], selectedPlugins: [],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const {clients} = json; const {clients} = json;
expect(pluginStates).toEqual({}); expect(pluginStates).toEqual({});
@@ -436,7 +430,6 @@ test('test processStore function for notifications for selected device', async (
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const {clients} = json; const {clients} = json;
expect(pluginStates).toEqual({}); expect(pluginStates).toEqual({});
@@ -493,7 +486,6 @@ test('test processStore function for notifications for unselected device', async
selectedPlugins: [], selectedPlugins: [],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const {clients} = json; const {clients} = json;
expect(pluginStates).toEqual({}); expect(pluginStates).toEqual({});
@@ -530,7 +522,6 @@ test('test processStore function for selected plugins', async () => {
selectedPlugins: ['plugin2'], selectedPlugins: ['plugin2'],
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const {clients} = json; const {clients} = json;
expect(pluginStates).toEqual({ expect(pluginStates).toEqual({
@@ -574,7 +565,6 @@ test('test processStore function for no selected plugins', async () => {
}); });
expect(json).toBeDefined(); expect(json).toBeDefined();
//$FlowFixMe Flow doesn't that its a test and the assertion for null is already done
const {pluginStates} = json.store; const {pluginStates} = json.store;
const {clients} = json; const {clients} = json;
expect(pluginStates).toEqual({ expect(pluginStates).toEqual({

View File

@@ -5,11 +5,19 @@
* @format * @format
*/ */
import {StoreEnhancerStoreCreator} from 'redux';
export {}; export {};
type RequestIdleHandle = number; type RequestIdleHandle = number;
declare global { declare global {
interface Window { interface Window {
__REDUX_DEVTOOLS_EXTENSION__: undefined | StoreEnhancerStoreCreator;
Flipper: {
init: () => void;
};
// rIC not supportedin TS: https://github.com/Microsoft/TypeScript/issues/21309 // rIC not supportedin TS: https://github.com/Microsoft/TypeScript/issues/21309
requestIdleCallback: ( requestIdleCallback: (
callback: (deadline: { callback: (deadline: {

View File

@@ -1176,6 +1176,13 @@
"@types/prop-types" "*" "@types/prop-types" "*"
csstype "^2.2.0" csstype "^2.2.0"
"@types/redux-devtools-extension@^2.13.2":
version "2.13.2"
resolved "https://registry.yarnpkg.com/@types/redux-devtools-extension/-/redux-devtools-extension-2.13.2.tgz#b2e09a8c163b2b0f5072e6a5ac41474000df2111"
integrity sha1-suCajBY7Kw9QcualrEFHQADfIRE=
dependencies:
redux-devtools-extension "*"
"@types/redux-persist@^4.3.1": "@types/redux-persist@^4.3.1":
version "4.3.1" version "4.3.1"
resolved "https://registry.yarnpkg.com/@types/redux-persist/-/redux-persist-4.3.1.tgz#aa4c876859e0bea5155e5f7980e5b8c4699dc2e6" resolved "https://registry.yarnpkg.com/@types/redux-persist/-/redux-persist-4.3.1.tgz#aa4c876859e0bea5155e5f7980e5b8c4699dc2e6"
@@ -7269,6 +7276,11 @@ redux-devtools-core@^0.2.1:
nanoid "^2.0.0" nanoid "^2.0.0"
remotedev-serialize "^0.1.8" remotedev-serialize "^0.1.8"
redux-devtools-extension@*:
version "2.13.8"
resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1"
integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg==
redux-devtools-instrument@^1.9.4: redux-devtools-instrument@^1.9.4:
version "1.9.6" version "1.9.6"
resolved "https://registry.yarnpkg.com/redux-devtools-instrument/-/redux-devtools-instrument-1.9.6.tgz#6b412595f74b9d48cfd4ecc13e585b1588ed6e7e" resolved "https://registry.yarnpkg.com/redux-devtools-instrument/-/redux-devtools-instrument-1.9.6.tgz#6b412595f74b9d48cfd4ecc13e585b1588ed6e7e"