Files
flipper/desktop/plugins/public/logs/index.tsx
dependabot[bot] 674f71a426 Bump prettier from 2.2.1 to 2.3.0 in /desktop (#2300)
Summary:
Bumps [prettier](https://github.com/prettier/prettier) from 2.2.1 to 2.3.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/prettier/prettier/releases">prettier's releases</a>.</em></p>
<blockquote>
<h2>2.3.0</h2>
<p><a href="https://github.com/prettier/prettier/compare/2.2.1...2.3.0">diff</a></p>
<p>{emoji:1f517} <a href="https://prettier.io/blog/2021/05/09/2.3.0.html">Release Notes</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md">prettier's changelog</a>.</em></p>
<blockquote>
<h1>2.3.0</h1>
<p><a href="https://github.com/prettier/prettier/compare/2.2.1...2.3.0">diff</a></p>
<p>{emoji:1f517} <a href="https://prettier.io/blog/2021/05/09/2.3.0.html">Release Notes</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="2afc3b9ae6"><code>2afc3b9</code></a> Release 2.3.0</li>
<li><a href="7cfa9aa89b"><code>7cfa9aa</code></a> Fix pre-commit hook setup command (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10710">#10710</a>)</li>
<li><a href="c8c02b4753"><code>c8c02b4</code></a> Build(deps-dev): Bump concurrently from 6.0.2 to 6.1.0 in /website (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10834">#10834</a>)</li>
<li><a href="6506e0f50e"><code>6506e0f</code></a> Build(deps-dev): Bump webpack-cli from 4.6.0 to 4.7.0 in /website (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10836">#10836</a>)</li>
<li><a href="69fae9c291"><code>69fae9c</code></a> Build(deps): Bump flow-parser from 0.150.0 to 0.150.1 (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10839">#10839</a>)</li>
<li><a href="164a6e2351"><code>164a6e2</code></a> Switch CLI to async (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10804">#10804</a>)</li>
<li><a href="d3e7e2f634"><code>d3e7e2f</code></a> Build(deps): Bump codecov/codecov-action from v1.4.1 to v1.5.0 (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10833">#10833</a>)</li>
<li><a href="9e09845da0"><code>9e09845</code></a> Build(deps): Bump <code>@​angular/compiler</code> from 11.2.12 to 11.2.13 (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10838">#10838</a>)</li>
<li><a href="1bfab3d045"><code>1bfab3d</code></a> Build(deps-dev): Bump eslint from 7.25.0 to 7.26.0 (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10840">#10840</a>)</li>
<li><a href="387fce4ed8"><code>387fce4</code></a> Minor formatting tweaks (<a href="https://github-redirect.dependabot.com/prettier/prettier/issues/10807">#10807</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/prettier/prettier/compare/2.2.1...2.3.0">compare view</a></li>
</ul>
</details>
<br />

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=prettier&package-manager=npm_and_yarn&previous-version=2.2.1&new-version=2.3.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

 ---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `dependabot rebase` will rebase this PR
- `dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `dependabot merge` will merge this PR after your CI passes on it
- `dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `dependabot cancel merge` will cancel a previously requested merge and block automerging
- `dependabot reopen` will reopen this PR if it is closed
- `dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

</details>

Pull Request resolved: https://github.com/facebook/flipper/pull/2300

Reviewed By: passy

Differential Revision: D28323849

Pulled By: cekkaewnumchai

fbshipit-source-id: 1842877ccc9a9587af7f0d9ff9432c2075c8ee22
2021-05-11 05:51:56 -07:00

249 lines
5.7 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {
DevicePluginClient,
DeviceLogEntry,
usePlugin,
createDataSource,
DataTable,
DataTableColumn,
theme,
DataTableManager,
createState,
useValue,
DataFormatter,
} from 'flipper-plugin';
import {
PlayCircleOutlined,
PauseCircleOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import React, {createRef, CSSProperties} from 'react';
import {Badge, Button} from 'antd';
import {baseRowStyle, logTypes} from './logTypes';
export type ExtendedLogEntry = DeviceLogEntry & {
count: number;
};
function createColumnConfig(
_os: 'iOS' | 'Android' | 'Metro',
): DataTableColumn<ExtendedLogEntry>[] {
return [
{
key: 'type',
title: '',
width: 30,
filters: Object.entries(logTypes).map(([value, config]) => ({
label: config.label,
value,
enabled: config.enabled,
})),
onRender(entry) {
return entry.count > 1 ? (
<Badge
count={entry.count}
size="small"
style={{
marginTop: 4,
color: theme.white,
background:
(logTypes[entry.type]?.style as any)?.color ??
theme.textColorSecondary,
}}
/>
) : (
logTypes[entry.type]?.icon
);
},
},
{
key: 'date',
title: 'Time',
width: 120,
},
{
key: 'pid',
title: 'PID',
width: 60,
visible: true,
},
{
key: 'tid',
title: 'TID',
width: 60,
visible: false,
},
{
key: 'tag',
title: 'Tag',
width: 160,
},
{
key: 'app',
title: 'App',
width: 160,
visible: false,
},
{
key: 'message',
title: 'Message',
wrap: true,
formatters: [
DataFormatter.truncate(400),
DataFormatter.prettyPrintJson,
DataFormatter.linkify,
],
},
];
}
function getRowStyle(entry: DeviceLogEntry): CSSProperties | undefined {
return (logTypes[entry.type]?.style as any) ?? baseRowStyle;
}
export function devicePlugin(client: DevicePluginClient) {
const rows = createDataSource<ExtendedLogEntry>([], {
limit: 200000,
persist: 'logs',
});
const isPaused = createState(true);
const tableManagerRef =
createRef<undefined | DataTableManager<ExtendedLogEntry>>();
client.onDeepLink((payload: unknown) => {
if (typeof payload === 'string') {
// timeout as we want to await restoring any previous scroll positin first, then scroll to the
setTimeout(() => {
let hasMatch = false;
rows.view.output(0, rows.view.size).forEach((row, index) => {
if (row.message.includes(payload)) {
tableManagerRef.current?.selectItem(index, hasMatch);
hasMatch = true;
}
});
}, 500);
}
});
client.addMenuEntry(
{
action: 'clear',
handler: clearLogs,
},
{
action: 'createPaste',
handler: createPaste,
},
{
action: 'goToBottom',
handler: goToBottom,
},
);
let logDisposer: (() => void) | undefined;
function resumePause() {
if (isPaused.get() && client.device.isConnected) {
// start listening to the logs
isPaused.set(false);
logDisposer = client.device.onLogEntry((entry: DeviceLogEntry) => {
const lastIndex = rows.size - 1;
const previousRow = rows.get(lastIndex);
if (
previousRow &&
previousRow.message === entry.message &&
previousRow.tag === entry.tag &&
previousRow.type === entry.type
) {
rows.update(lastIndex, {
...previousRow,
count: previousRow.count + 1,
});
} else {
rows.append({
...entry,
count: 1,
});
}
});
} else {
logDisposer?.();
isPaused.set(true);
}
}
function clearLogs() {
// Non public Android specific api
(client.device.realDevice as any)?.clearLogs?.();
rows.clear();
tableManagerRef.current?.clearSelection();
}
function createPaste() {
let selection = tableManagerRef.current?.getSelectedItems();
if (!selection?.length) {
selection = rows.view.output(0, rows.view.size);
}
if (selection?.length) {
client.createPaste(JSON.stringify(selection, null, 2));
}
}
function goToBottom() {
tableManagerRef?.current?.selectItem(rows.view.size - 1);
}
// start listening to the logs
resumePause();
const columns = createColumnConfig(client.device.os as any);
return {
columns,
isConnected: client.device.isConnected,
isPaused,
tableManagerRef,
rows,
clearLogs,
resumePause,
};
}
export function Component() {
const plugin = usePlugin(devicePlugin);
const paused = useValue(plugin.isPaused);
return (
<DataTable<ExtendedLogEntry>
dataSource={plugin.rows}
columns={plugin.columns}
enableAutoScroll
onRowStyle={getRowStyle}
extraActions={
plugin.isConnected ? (
<>
<Button
title={`Click to ${paused ? 'resume' : 'pause'} the log stream`}
danger={paused}
onClick={plugin.resumePause}>
{paused ? <PlayCircleOutlined /> : <PauseCircleOutlined />}
</Button>
<Button title="Clear logs" onClick={plugin.clearLogs}>
<DeleteOutlined />
</Button>
</>
) : undefined
}
tableManagerRef={plugin.tableManagerRef}
/>
);
}