DeviceLogs plugin to Sandy
Summary: Converted the DeviceLogs plugin to sandy. Kept logic and UI the same (so same batching, localstorage mechanisms etc). But used sandy api's for log subscribing, state, and separating the logical part of the component from the UI. Note that some mechanisms work slightly different, like deeplinking and scrollToBottom handling, to reflect the fact that plugins are now long lived Reviewed By: jknoxville Differential Revision: D22845466 fbshipit-source-id: 7c98b2ddd9121dc730768ee1bece7e71bb5bec16
This commit is contained in:
committed by
Facebook GitHub Bot
parent
dd15cffa64
commit
685cc09b3b
@@ -343,12 +343,11 @@ class PluginContainer extends PureComponent<Props, State> {
|
||||
let pluginElement: null | React.ReactElement<any>;
|
||||
if (isSandyPlugin(activePlugin)) {
|
||||
// Make sure we throw away the container for different pluginKey!
|
||||
pluginElement = (
|
||||
<SandyPluginRenderer
|
||||
key={pluginKey}
|
||||
plugin={target.sandyPluginStates.get(activePlugin.id)!}
|
||||
/>
|
||||
);
|
||||
const instance = target.sandyPluginStates.get(activePlugin.id);
|
||||
if (!instance) {
|
||||
return null;
|
||||
}
|
||||
pluginElement = <SandyPluginRenderer key={pluginKey} plugin={instance} />;
|
||||
} else {
|
||||
const props: PluginProps<Object> & {
|
||||
key: string;
|
||||
|
||||
@@ -120,6 +120,7 @@ export default class BaseDevice {
|
||||
this._notifyLogListeners(entry);
|
||||
}
|
||||
|
||||
// TODO: remove getLogs T70688226
|
||||
getLogs(startDate: Date | null = null) {
|
||||
return startDate != null
|
||||
? this.logEntries.filter((log) => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import {Logger} from '../fb-interfaces/Logger';
|
||||
import {PluginNotification} from '../reducers/notifications';
|
||||
import {PluginDefinition, isSandyPlugin} from '../plugin';
|
||||
import isHeadless from '../utils/isHeadless';
|
||||
import {setStaticView, setDeeplinkPayload} from '../reducers/connections';
|
||||
import {setStaticView} from '../reducers/connections';
|
||||
import {ipcRenderer, IpcRendererEvent} from 'electron';
|
||||
import {
|
||||
setActiveNotifications,
|
||||
@@ -48,9 +48,11 @@ export default (store: Store, logger: Logger) => {
|
||||
) => {
|
||||
if (eventName === 'click' || (eventName === 'action' && arg === 0)) {
|
||||
store.dispatch(
|
||||
setDeeplinkPayload(pluginNotification.notification.action ?? null),
|
||||
setStaticView(
|
||||
NotificationScreen,
|
||||
pluginNotification.notification.action ?? null,
|
||||
),
|
||||
);
|
||||
store.dispatch(setStaticView(NotificationScreen));
|
||||
} else if (eventName === 'action') {
|
||||
if (arg === 1 && pluginNotification.notification.category) {
|
||||
// Hide similar (category)
|
||||
|
||||
@@ -128,6 +128,7 @@ export type Action =
|
||||
| {
|
||||
type: 'SET_STATIC_VIEW';
|
||||
payload: StaticView;
|
||||
deepLinkPayload: unknown;
|
||||
}
|
||||
| {
|
||||
type: 'DISMISS_ERROR';
|
||||
@@ -145,10 +146,6 @@ export type Action =
|
||||
type: 'SELECT_CLIENT';
|
||||
payload: string;
|
||||
}
|
||||
| {
|
||||
type: 'SET_DEEPLINK_PAYLOAD';
|
||||
payload: null | string;
|
||||
}
|
||||
| RegisterPluginAction;
|
||||
|
||||
const DEFAULT_PLUGIN = 'DeviceLogs';
|
||||
@@ -173,12 +170,13 @@ const INITAL_STATE: State = {
|
||||
export default (state: State = INITAL_STATE, action: Actions): State => {
|
||||
switch (action.type) {
|
||||
case 'SET_STATIC_VIEW': {
|
||||
const {payload} = action;
|
||||
const {payload, deepLinkPayload} = action;
|
||||
const {selectedPlugin} = state;
|
||||
return {
|
||||
...state,
|
||||
staticView: payload,
|
||||
selectedPlugin: payload != null ? null : selectedPlugin,
|
||||
deepLinkPayload: deepLinkPayload ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -252,13 +250,17 @@ export default (state: State = INITAL_STATE, action: Actions): State => {
|
||||
if (typeof deepLinkPayload === 'string') {
|
||||
const deepLinkParams = new URLSearchParams(deepLinkPayload);
|
||||
const deviceParam = deepLinkParams.get('device');
|
||||
const deviceMatch = state.devices.find((v) => v.title === deviceParam);
|
||||
if (deviceMatch) {
|
||||
selectedDevice = deviceMatch;
|
||||
} else {
|
||||
console.warn(
|
||||
`Could not find matching device "${deviceParam}" requested through deep-link.`,
|
||||
if (deviceParam) {
|
||||
const deviceMatch = state.devices.find(
|
||||
(v) => v.title === deviceParam,
|
||||
);
|
||||
if (deviceMatch) {
|
||||
selectedDevice = deviceMatch;
|
||||
} else {
|
||||
console.warn(
|
||||
`Could not find matching device "${deviceParam}" requested through deep-link.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!selectDevice) {
|
||||
@@ -388,9 +390,6 @@ export default (state: State = INITAL_STATE, action: Actions): State => {
|
||||
errors,
|
||||
};
|
||||
}
|
||||
case 'SET_DEEPLINK_PAYLOAD': {
|
||||
return {...state, deepLinkPayload: action.payload};
|
||||
}
|
||||
case 'REGISTER_PLUGINS': {
|
||||
// plugins are registered after creating the base devices, so update them
|
||||
const plugins = action.payload;
|
||||
@@ -435,13 +434,17 @@ export const selectDevice = (payload: BaseDevice): Action => ({
|
||||
payload,
|
||||
});
|
||||
|
||||
export const setStaticView = (payload: StaticView): Action => {
|
||||
export const setStaticView = (
|
||||
payload: StaticView,
|
||||
deepLinkPayload?: unknown,
|
||||
): Action => {
|
||||
if (!payload) {
|
||||
throw new Error('Cannot set empty static view');
|
||||
}
|
||||
return {
|
||||
type: 'SET_STATIC_VIEW',
|
||||
payload,
|
||||
deepLinkPayload,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -479,11 +482,6 @@ export const selectClient = (clientId: string): Action => ({
|
||||
payload: clientId,
|
||||
});
|
||||
|
||||
export const setDeeplinkPayload = (payload: string | null): Action => ({
|
||||
type: 'SET_DEEPLINK_PAYLOAD',
|
||||
payload,
|
||||
});
|
||||
|
||||
export function getAvailableClients(
|
||||
device: null | undefined | BaseDevice,
|
||||
clients: Client[],
|
||||
|
||||
@@ -276,6 +276,7 @@ export class ManagedTable extends React.Component<
|
||||
prevState: ManagedTableState,
|
||||
) {
|
||||
if (
|
||||
this.props.stickyBottom !== false &&
|
||||
this.props.rows.length !== prevProps.rows.length &&
|
||||
this.state.shouldScrollToBottom &&
|
||||
this.state.highlightedRows.size < 2
|
||||
|
||||
Reference in New Issue
Block a user