Convert logs plugin to TypeScript
Summary: _typescript_ Reviewed By: danielbuechele Differential Revision: D17184173 fbshipit-source-id: c7a055544ee4d9e07e5685fa84669d68fd68bf31
This commit is contained in:
committed by
Facebook Github Bot
parent
25de8ee90a
commit
2fcd0cbcac
@@ -70,7 +70,10 @@ export {
|
|||||||
TableColumnOrderVal,
|
TableColumnOrderVal,
|
||||||
TableColumnSizes,
|
TableColumnSizes,
|
||||||
} from './ui/components/table/types';
|
} from './ui/components/table/types';
|
||||||
export {default as ManagedTable} from './ui/components/table/ManagedTable';
|
export {
|
||||||
|
default as ManagedTable,
|
||||||
|
ManagedTable as ManagedTableClass,
|
||||||
|
} from './ui/components/table/ManagedTable';
|
||||||
export {ManagedTableProps} from './ui/components/table/ManagedTable';
|
export {ManagedTableProps} from './ui/components/table/ManagedTable';
|
||||||
export {
|
export {
|
||||||
default as ManagedTable_immutable,
|
default as ManagedTable_immutable,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {addEntriesToState, processEntry} from '../index';
|
import {addEntriesToState, processEntry} from '../index.tsx';
|
||||||
|
|
||||||
const entry = {
|
const entry = {
|
||||||
tag: 'OpenGLRenderer',
|
tag: 'OpenGLRenderer',
|
||||||
|
|||||||
@@ -5,19 +5,20 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {
|
import {
|
||||||
TableBodyRow,
|
TableBodyRow,
|
||||||
TableColumnOrder,
|
TableColumnOrder,
|
||||||
TableColumnSizes,
|
TableColumnSizes,
|
||||||
TableColumns,
|
TableColumns,
|
||||||
} from 'flipper';
|
} from 'flipper';
|
||||||
import type {Counter} from './LogWatcher.tsx';
|
import {Counter} from './LogWatcher';
|
||||||
import type {Props as PluginProps} from '../../plugin.tsx';
|
import {Props as PluginProps, BaseAction} from '../../plugin';
|
||||||
import type {DeviceLogEntry} from '../../devices/BaseDevice.tsx';
|
import {DeviceLogEntry} from '../../devices/BaseDevice';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Text,
|
Text,
|
||||||
ManagedTable,
|
ManagedTable,
|
||||||
|
ManagedTableClass,
|
||||||
Button,
|
Button,
|
||||||
colors,
|
colors,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
@@ -30,27 +31,33 @@ import {
|
|||||||
Device,
|
Device,
|
||||||
createPaste,
|
createPaste,
|
||||||
textContent,
|
textContent,
|
||||||
|
KeyboardActions,
|
||||||
} from 'flipper';
|
} from 'flipper';
|
||||||
import LogWatcher from './LogWatcher.tsx';
|
import LogWatcher from './LogWatcher';
|
||||||
|
import React from 'react';
|
||||||
|
import {MenuTemplate} from 'src/ui/components/ContextMenu';
|
||||||
|
|
||||||
const LOG_WATCHER_LOCAL_STORAGE_KEY = 'LOG_WATCHER_LOCAL_STORAGE_KEY';
|
const LOG_WATCHER_LOCAL_STORAGE_KEY = 'LOG_WATCHER_LOCAL_STORAGE_KEY';
|
||||||
|
|
||||||
type Entries = Array<{
|
type Entries = Array<{
|
||||||
row: TableBodyRow,
|
row: TableBodyRow;
|
||||||
entry: DeviceLogEntry,
|
entry: DeviceLogEntry;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type State = {|
|
type BaseState = {
|
||||||
rows: Array<TableBodyRow>,
|
rows: Array<TableBodyRow>;
|
||||||
entries: Entries,
|
entries: Entries;
|
||||||
key2entry: {[key: string]: DeviceLogEntry},
|
key2entry: {[key: string]: DeviceLogEntry};
|
||||||
highlightedRows: Set<string>,
|
};
|
||||||
counters: Array<Counter>,
|
|
||||||
|};
|
|
||||||
|
|
||||||
type Actions = {||};
|
type AdditionalState = {
|
||||||
|
highlightedRows: Set<string>;
|
||||||
|
counters: Array<Counter>;
|
||||||
|
};
|
||||||
|
|
||||||
type PersistedState = {||};
|
type State = BaseState & AdditionalState;
|
||||||
|
|
||||||
|
type PersistedState = {};
|
||||||
|
|
||||||
const Icon = styled(Glyph)({
|
const Icon = styled(Glyph)({
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
@@ -69,8 +76,8 @@ function getLineCount(str: string): number {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
function keepKeys(obj, keys) {
|
function keepKeys<A>(obj: A, keys: Array<string>): A {
|
||||||
const result = {};
|
const result: A = {} as A;
|
||||||
for (const key in obj) {
|
for (const key in obj) {
|
||||||
if (keys.includes(key)) {
|
if (keys.includes(key)) {
|
||||||
result[key] = obj[key];
|
result[key] = obj[key];
|
||||||
@@ -146,11 +153,11 @@ const INITIAL_COLUMN_ORDER = [
|
|||||||
|
|
||||||
const LOG_TYPES: {
|
const LOG_TYPES: {
|
||||||
[level: string]: {
|
[level: string]: {
|
||||||
label: string,
|
label: string;
|
||||||
color: string,
|
color: string;
|
||||||
icon?: React.Node,
|
icon?: React.ReactNode;
|
||||||
style?: Object,
|
style?: Object;
|
||||||
},
|
};
|
||||||
} = {
|
} = {
|
||||||
verbose: {
|
verbose: {
|
||||||
label: 'Verbose',
|
label: 'Verbose',
|
||||||
@@ -221,24 +228,26 @@ const HiddenScrollText = styled(Text)({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const LogCount = styled('div')(({backgroundColor}) => ({
|
const LogCount = styled('div')(
|
||||||
backgroundColor,
|
({backgroundColor}: {backgroundColor: string}) => ({
|
||||||
borderRadius: '999em',
|
backgroundColor,
|
||||||
fontSize: 11,
|
borderRadius: '999em',
|
||||||
marginTop: 4,
|
fontSize: 11,
|
||||||
minWidth: 16,
|
marginTop: 4,
|
||||||
height: 16,
|
minWidth: 16,
|
||||||
color: colors.white,
|
height: 16,
|
||||||
textAlign: 'center',
|
color: colors.white,
|
||||||
lineHeight: '16px',
|
textAlign: 'center',
|
||||||
paddingLeft: 4,
|
lineHeight: '16px',
|
||||||
paddingRight: 4,
|
paddingLeft: 4,
|
||||||
textOverflow: 'ellipsis',
|
paddingRight: 4,
|
||||||
overflow: 'hidden',
|
textOverflow: 'ellipsis',
|
||||||
whiteSpace: 'nowrap',
|
overflow: 'hidden',
|
||||||
}));
|
whiteSpace: 'nowrap',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
function pad(chunk: mixed, len: number): string {
|
function pad(chunk: any, len: number): string {
|
||||||
let str = String(chunk);
|
let str = String(chunk);
|
||||||
while (str.length < len) {
|
while (str.length < len) {
|
||||||
str = `0${str}`;
|
str = `0${str}`;
|
||||||
@@ -248,12 +257,12 @@ function pad(chunk: mixed, len: number): string {
|
|||||||
|
|
||||||
export function addEntriesToState(
|
export function addEntriesToState(
|
||||||
items: Entries,
|
items: Entries,
|
||||||
state: $Shape<State> = {
|
state: BaseState = {
|
||||||
rows: [],
|
rows: [],
|
||||||
entries: [],
|
entries: [],
|
||||||
key2entry: {},
|
key2entry: {},
|
||||||
},
|
},
|
||||||
): $Shape<State> {
|
): BaseState {
|
||||||
const rows = [...state.rows];
|
const rows = [...state.rows];
|
||||||
const entries = [...state.entries];
|
const entries = [...state.entries];
|
||||||
const key2entry = {...state.key2entry};
|
const key2entry = {...state.key2entry};
|
||||||
@@ -263,7 +272,7 @@ export function addEntriesToState(
|
|||||||
entries.push({row, entry});
|
entries.push({row, entry});
|
||||||
key2entry[row.key] = entry;
|
key2entry[row.key] = entry;
|
||||||
|
|
||||||
let previousEntry: ?DeviceLogEntry = null;
|
let previousEntry: DeviceLogEntry | null = null;
|
||||||
|
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
previousEntry = items[i - 1].entry;
|
previousEntry = items[i - 1].entry;
|
||||||
@@ -285,7 +294,7 @@ export function addRowIfNeeded(
|
|||||||
rows: Array<TableBodyRow>,
|
rows: Array<TableBodyRow>,
|
||||||
row: TableBodyRow,
|
row: TableBodyRow,
|
||||||
entry: DeviceLogEntry,
|
entry: DeviceLogEntry,
|
||||||
previousEntry: ?DeviceLogEntry,
|
previousEntry: DeviceLogEntry | null,
|
||||||
) {
|
) {
|
||||||
const previousRow = rows.length > 0 ? rows[rows.length - 1] : null;
|
const previousRow = rows.length > 0 ? rows[rows.length - 1] : null;
|
||||||
if (
|
if (
|
||||||
@@ -315,10 +324,10 @@ export function processEntry(
|
|||||||
entry: DeviceLogEntry,
|
entry: DeviceLogEntry,
|
||||||
key: string,
|
key: string,
|
||||||
): {
|
): {
|
||||||
row: TableBodyRow,
|
row: TableBodyRow;
|
||||||
entry: DeviceLogEntry,
|
entry: DeviceLogEntry;
|
||||||
} {
|
} {
|
||||||
const {icon, style} = LOG_TYPES[(entry.type: string)] || LOG_TYPES.debug;
|
const {icon, style} = LOG_TYPES[entry.type] || LOG_TYPES.debug;
|
||||||
// build the item, it will either be batched or added straight away
|
// build the item, it will either be batched or added straight away
|
||||||
return {
|
return {
|
||||||
entry,
|
entry,
|
||||||
@@ -374,13 +383,16 @@ export function processEntry(
|
|||||||
|
|
||||||
export default class LogTable extends FlipperDevicePlugin<
|
export default class LogTable extends FlipperDevicePlugin<
|
||||||
State,
|
State,
|
||||||
Actions,
|
BaseAction,
|
||||||
PersistedState,
|
PersistedState
|
||||||
> {
|
> {
|
||||||
static keyboardActions = ['clear', 'goToBottom', 'createPaste'];
|
static keyboardActions: KeyboardActions = [
|
||||||
|
'clear',
|
||||||
|
'goToBottom',
|
||||||
|
'createPaste',
|
||||||
|
];
|
||||||
|
|
||||||
initTimer: ?TimeoutID;
|
batchTimer: NodeJS.Timeout | undefined;
|
||||||
batchTimer: ?TimeoutID;
|
|
||||||
|
|
||||||
static supportsDevice(device: Device) {
|
static supportsDevice(device: Device) {
|
||||||
return device.os === 'iOS' || device.os === 'Android';
|
return device.os === 'iOS' || device.os === 'Android';
|
||||||
@@ -407,10 +419,10 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
};
|
};
|
||||||
|
|
||||||
calculateHighlightedRows = (
|
calculateHighlightedRows = (
|
||||||
deepLinkPayload: ?string,
|
deepLinkPayload: string | null,
|
||||||
rows: Array<TableBodyRow>,
|
rows: Array<TableBodyRow>,
|
||||||
): Set<string> => {
|
): Set<string> => {
|
||||||
const highlightedRows = new Set();
|
const highlightedRows = new Set<string>();
|
||||||
if (!deepLinkPayload) {
|
if (!deepLinkPayload) {
|
||||||
return highlightedRows;
|
return highlightedRows;
|
||||||
}
|
}
|
||||||
@@ -418,10 +430,8 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
// Run through array from last to first, because we want to show the last
|
// Run through array from last to first, because we want to show the last
|
||||||
// time it the log we are looking for appeared.
|
// time it the log we are looking for appeared.
|
||||||
for (let i = rows.length - 1; i >= 0; i--) {
|
for (let i = rows.length - 1; i >= 0; i--) {
|
||||||
if (
|
const filterValue = rows[i].filterValue;
|
||||||
rows[i].filterValue &&
|
if (filterValue != null && filterValue.includes(deepLinkPayload)) {
|
||||||
rows[i].filterValue.includes(deepLinkPayload)
|
|
||||||
) {
|
|
||||||
highlightedRows.add(rows[i].key);
|
highlightedRows.add(rows[i].key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -431,7 +441,8 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
const arr = deepLinkPayload.split('\n');
|
const arr = deepLinkPayload.split('\n');
|
||||||
for (const msg of arr) {
|
for (const msg of arr) {
|
||||||
for (let i = rows.length - 1; i >= 0; i--) {
|
for (let i = rows.length - 1; i >= 0; i--) {
|
||||||
if (rows[i].filterValue && rows[i].filterValue.includes(msg)) {
|
const filterValue = rows[i].filterValue;
|
||||||
|
if (filterValue != null && filterValue.includes(msg)) {
|
||||||
highlightedRows.add(rows[i].key);
|
highlightedRows.add(rows[i].key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -441,11 +452,11 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
return highlightedRows;
|
return highlightedRows;
|
||||||
};
|
};
|
||||||
|
|
||||||
tableRef: ?ManagedTable;
|
tableRef: ManagedTableClass | undefined;
|
||||||
columns: TableColumns;
|
columns: TableColumns;
|
||||||
columnSizes: TableColumnSizes;
|
columnSizes: TableColumnSizes;
|
||||||
columnOrder: TableColumnOrder;
|
columnOrder: TableColumnOrder;
|
||||||
logListener: ?Symbol;
|
logListener: Symbol | undefined;
|
||||||
|
|
||||||
batch: Entries = [];
|
batch: Entries = [];
|
||||||
queued: boolean = false;
|
queued: boolean = false;
|
||||||
@@ -464,6 +475,7 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
this.device
|
this.device
|
||||||
.getLogs()
|
.getLogs()
|
||||||
.map(log => processEntry(log, String(this.counter++))),
|
.map(log => processEntry(log, String(this.counter++))),
|
||||||
|
this.state,
|
||||||
);
|
);
|
||||||
this.state = {
|
this.state = {
|
||||||
...initialState,
|
...initialState,
|
||||||
@@ -487,7 +499,7 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
if (entry.message.match(counter.expression)) {
|
if (entry.message.match(counter.expression)) {
|
||||||
counterUpdated = true;
|
counterUpdated = true;
|
||||||
if (counter.notify) {
|
if (counter.notify) {
|
||||||
new window.Notification(`${counter.label}`, {
|
new Notification(`${counter.label}`, {
|
||||||
body: 'The watched log message appeared',
|
body: 'The watched log message appeared',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -505,8 +517,8 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
};
|
};
|
||||||
|
|
||||||
scheudleEntryForBatch = (item: {
|
scheudleEntryForBatch = (item: {
|
||||||
row: TableBodyRow,
|
row: TableBodyRow;
|
||||||
entry: DeviceLogEntry,
|
entry: DeviceLogEntry;
|
||||||
}) => {
|
}) => {
|
||||||
// batch up logs to be processed every 250ms, if we have lots of log
|
// batch up logs to be processed every 250ms, if we have lots of log
|
||||||
// messages coming in, then calling an setState 200+ times is actually
|
// messages coming in, then calling an setState 200+ times is actually
|
||||||
@@ -553,7 +565,7 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
|
|
||||||
createPaste = () => {
|
createPaste = () => {
|
||||||
let paste = '';
|
let paste = '';
|
||||||
const mapFn = row =>
|
const mapFn = (row: TableBodyRow) =>
|
||||||
Object.keys(COLUMNS)
|
Object.keys(COLUMNS)
|
||||||
.map(key => textContent(row.columns[key].value))
|
.map(key => textContent(row.columns[key].value))
|
||||||
.join('\t');
|
.join('\t');
|
||||||
@@ -571,7 +583,7 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
createPaste(paste);
|
createPaste(paste);
|
||||||
};
|
};
|
||||||
|
|
||||||
setTableRef = (ref: React.ElementRef<typeof ManagedTable>) => {
|
setTableRef = (ref: ManagedTableClass) => {
|
||||||
this.tableRef = ref;
|
this.tableRef = ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -608,7 +620,7 @@ export default class LogTable extends FlipperDevicePlugin<
|
|||||||
flex: 1,
|
flex: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
buildContextMenuItems = () => [
|
buildContextMenuItems: () => MenuTemplate = () => [
|
||||||
{
|
{
|
||||||
type: 'separator',
|
type: 'separator',
|
||||||
},
|
},
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "DeviceLogs",
|
"name": "DeviceLogs",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "index.js",
|
"main": "index.tsx",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {},
|
"dependencies": {},
|
||||||
"title": "Logs",
|
"title": "Logs",
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ const Container = styled(FlexColumn)((props: {canOverflow?: boolean}) => ({
|
|||||||
|
|
||||||
const globalTableState: {[key: string]: TableColumnSizes} = {};
|
const globalTableState: {[key: string]: TableColumnSizes} = {};
|
||||||
|
|
||||||
class ManagedTable extends React.Component<
|
export class ManagedTable extends React.Component<
|
||||||
ManagedTableProps,
|
ManagedTableProps,
|
||||||
ManagedTableState
|
ManagedTableState
|
||||||
> {
|
> {
|
||||||
@@ -607,7 +607,7 @@ class ManagedTable extends React.Component<
|
|||||||
getRow = ({index, style}: {index: number; style: React.CSSProperties}) => {
|
getRow = ({index, style}: {index: number; style: React.CSSProperties}) => {
|
||||||
const {onAddFilter, multiline, zebra, rows} = this.props;
|
const {onAddFilter, multiline, zebra, rows} = this.props;
|
||||||
const {columnOrder, columnSizes, highlightedRows} = this.state;
|
const {columnOrder, columnSizes, highlightedRows} = this.state;
|
||||||
const columnKeys = columnOrder
|
const columnKeys: Array<string> = columnOrder
|
||||||
.map(k => (k.visible ? k.key : null))
|
.map(k => (k.visible ? k.key : null))
|
||||||
.filter(notNull);
|
.filter(notNull);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user