Refactor Stella plugin

Summary:
1. Replace old FileSelector with the new FileSelector
2. Remove showOpenDialog from FlipperLib

Reviewed By: mweststrate

Differential Revision: D32667103

fbshipit-source-id: be8da034c2695f83b397b6c7d35bc6aee78d66e5
This commit is contained in:
Andrey Goncharov
2021-11-26 08:28:50 -08:00
committed by Facebook GitHub Bot
parent b82c41eedd
commit 225a2a7e34
8 changed files with 159 additions and 188 deletions

View File

@@ -144,6 +144,7 @@ export function initializeElectron() {
return {
data,
name: fileName,
path: filePath,
};
}),
);

View File

@@ -43,17 +43,6 @@ export interface FlipperLib {
DetailsSidebarImplementation?(
props: DetailSidebarProps,
): React.ReactElement | null;
/**
* @deprecated
* Will be removed in subsequent commits
*/
showOpenDialog?(options: {
defaultPath?: string;
filter?: {
extensions: string[];
name: string;
};
}): Promise<string | undefined>;
/**
* @returns
* Imported file data.

View File

@@ -16,10 +16,9 @@ import {
LoadingIndicator,
} from '../../ui';
import styled from '@emotion/styled';
import {default as FileSelector} from '../../ui/components/FileSelector';
import React, {useState} from 'react';
import {installPluginFromFile} from 'flipper-plugin-lib';
import {Toolbar} from 'flipper-plugin';
import {Toolbar, FileSelector} from 'flipper-plugin';
const CenteredGlyph = styled(Glyph)({
margin: 'auto',
@@ -80,10 +79,16 @@ export default function PluginPackageInstaller({
return (
<Toolbar>
<FileSelector
placeholderText="Specify path to a Flipper package or just drag and drop it here..."
onPathChanged={(e) => {
setPath(e.path);
setIsPathValid(e.isValid);
label="Select a Flipper package or just drag and drop it here..."
onChange={(newFile) => {
if (newFile) {
// TODO: Fix me before implementing Browser Flipper. "path" is only availbale in Electron!
setPath(newFile.path!);
setIsPathValid(true);
} else {
setPath('');
setIsPathValid(false);
}
setError(undefined);
}}
/>

View File

@@ -275,38 +275,80 @@ exports[`load PluginInstaller list 1`] = `
class="css-1lxv8hi-Container-Horizontal-SandyToolbarContainer e1ecpah20"
>
<div
class="css-1spj5hr-View-FlexBox-FlexRow-Container ev83mp62"
class="ant-row ant-row-no-wrap ant-row-middle"
style="margin-left: -4px; margin-right: -4px;"
>
<div
class="ant-col"
style="padding-left: 4px; padding-right: 4px; flex-basis: auto; min-width: 0;"
>
<input
class="css-sli06x-Input-FileInputBox ev83mp60"
placeholder="Specify path to a Flipper package or just drag and drop it here..."
class="ant-input"
placeholder="Select a Flipper package or just drag and drop it here..."
type="text"
value=""
/>
<div
class="css-ccdckn-View-FlexBox-FlexRow-GlyphContainer ev83mp61"
>
<img
alt="dots-3-circle"
class="ev83mp63 css-6iptsk-ColoredIconBlack-CenteredGlyph ekc8qeh1"
size="16"
src="https://facebook.com/assets/?name=dots-3-circle&variant=outline&size=16&set=facebook_icons&density=1x"
title="Open file selection dialog"
/>
</div>
<div
class="css-ccdckn-View-FlexBox-FlexRow-GlyphContainer ev83mp61"
class="ant-col"
style="padding-left: 4px; padding-right: 4px; flex: 0 0 auto;"
>
<div
class="css-auhar3-TooltipContainer e1m67rki0"
<button
class="ant-btn ant-btn-icon-only"
disabled=""
title="Reset"
type="button"
>
<div
class="ev83mp63 css-1qsl9s4-ColoredIconCustom-CenteredGlyph ekc8qeh0"
color="#D79651"
size="16"
src="https://facebook.com/assets/?name=caution-triangle&variant=filled&size=16&set=facebook_icons&density=1x"
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</button>
</div>
<div
class="ant-col"
style="padding-left: 4px; padding-right: 4px; flex: 0 0 auto;"
>
<button
class="ant-btn ant-btn-icon-only"
title="Select a Flipper package or just drag and drop it here..."
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
</button>
</div>
</div>
<div
@@ -609,38 +651,80 @@ exports[`load PluginInstaller list with one plugin installed 1`] = `
class="css-1lxv8hi-Container-Horizontal-SandyToolbarContainer e1ecpah20"
>
<div
class="css-1spj5hr-View-FlexBox-FlexRow-Container ev83mp62"
class="ant-row ant-row-no-wrap ant-row-middle"
style="margin-left: -4px; margin-right: -4px;"
>
<div
class="ant-col"
style="padding-left: 4px; padding-right: 4px; flex-basis: auto; min-width: 0;"
>
<input
class="css-sli06x-Input-FileInputBox ev83mp60"
placeholder="Specify path to a Flipper package or just drag and drop it here..."
class="ant-input"
placeholder="Select a Flipper package or just drag and drop it here..."
type="text"
value=""
/>
<div
class="css-ccdckn-View-FlexBox-FlexRow-GlyphContainer ev83mp61"
>
<img
alt="dots-3-circle"
class="ev83mp63 css-6iptsk-ColoredIconBlack-CenteredGlyph ekc8qeh1"
size="16"
src="https://facebook.com/assets/?name=dots-3-circle&variant=outline&size=16&set=facebook_icons&density=1x"
title="Open file selection dialog"
/>
</div>
<div
class="css-ccdckn-View-FlexBox-FlexRow-GlyphContainer ev83mp61"
class="ant-col"
style="padding-left: 4px; padding-right: 4px; flex: 0 0 auto;"
>
<div
class="css-auhar3-TooltipContainer e1m67rki0"
<button
class="ant-btn ant-btn-icon-only"
disabled=""
title="Reset"
type="button"
>
<div
class="ev83mp63 css-1qsl9s4-ColoredIconCustom-CenteredGlyph ekc8qeh0"
color="#D79651"
size="16"
src="https://facebook.com/assets/?name=caution-triangle&variant=filled&size=16&set=facebook_icons&density=1x"
<span
aria-label="close"
class="anticon anticon-close"
role="img"
>
<svg
aria-hidden="true"
data-icon="close"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"
/>
</svg>
</span>
</button>
</div>
<div
class="ant-col"
style="padding-left: 4px; padding-right: 4px; flex: 0 0 auto;"
>
<button
class="ant-btn ant-btn-icon-only"
title="Select a Flipper package or just drag and drop it here..."
type="button"
>
<span
aria-label="upload"
class="anticon anticon-upload"
role="img"
>
<svg
aria-hidden="true"
data-icon="upload"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M400 317.7h73.9V656c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V317.7H624c6.7 0 10.4-7.7 6.3-12.9L518.3 163a8 8 0 00-12.6 0l-112 141.7c-4.1 5.3-.4 13 6.3 13zM878 626h-60c-4.4 0-8 3.6-8 8v154H214V634c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v198c0 17.7 14.3 32 32 32h684c17.7 0 32-14.3 32-32V634c0-4.4-3.6-8-8-8z"
/>
</svg>
</span>
</button>
</div>
</div>
<div

View File

@@ -118,7 +118,6 @@ export {
} from 'flipper-plugin';
export {ElementFramework} from './ui/components/elements-inspector/ElementFramework';
export {InspectorSidebar} from './ui/components/elements-inspector/sidebar';
export {default as FileSelector} from './ui/components/FileSelector';
export {getFlipperMediaCDN, appendAccessTokenToUrl} from './fb-stubs/user';
export {Rect} from './utils/geometry';
export {Logger} from 'flipper-common';

View File

@@ -1,121 +0,0 @@
/**
* 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 React, {useState} from 'react';
import FlexRow from './FlexRow';
import Glyph from './Glyph';
import Input from './Input';
import styled from '@emotion/styled';
import {colors} from './colors';
import fs from 'fs';
import {Tooltip} from '..';
import {getFlipperLib} from 'flipper-plugin';
const CenteredGlyph = styled(Glyph)({
margin: 'auto',
marginLeft: 4,
});
const Container = styled(FlexRow)({
width: '100%',
marginRight: 4,
});
const GlyphContainer = styled(FlexRow)({
width: 20,
});
const FileInputBox = styled(Input)<{isValid: boolean}>(({isValid}) => ({
flexGrow: 1,
color: isValid ? undefined : colors.red,
'&::-webkit-input-placeholder': {
color: colors.placeholder,
fontWeight: 300,
},
}));
export interface Props {
onPathChanged: (evtArgs: {path: string; isValid: boolean}) => void;
placeholderText: string;
defaultPath: string;
}
const defaultProps: Props = {
onPathChanged: (_) => {},
placeholderText: '',
defaultPath: '/',
};
// TODO: Should we render null in browsers for FileSelector?
// Do we even need it after decapitation? Every plugin should be using FlipperLib.exportFile which shows a save dialog every time.
export default function FileSelector({
onPathChanged,
placeholderText,
defaultPath,
}: Props) {
const [value, setValue] = useState('');
const [isValid, setIsValid] = useState(false);
const onChange = (path: string) => {
setValue(path);
let isNewPathValid = false;
try {
isNewPathValid = fs.statSync(path).isFile();
} catch {
isNewPathValid = false;
}
setIsValid(isNewPathValid);
onPathChanged({path, isValid: isNewPathValid});
};
return (
<Container>
<FileInputBox
placeholder={placeholderText}
value={value}
isValid
onDrop={(e) => {
if (e.dataTransfer.files.length) {
onChange(e.dataTransfer.files[0].path);
}
}}
onChange={(e) => {
onChange(e.target.value);
}}
/>
<GlyphContainer
onClick={() =>
getFlipperLib()
.showOpenDialog?.({defaultPath})
.then((path) => {
if (path) {
onChange(path);
}
})
}>
<CenteredGlyph
name="dots-3-circle"
variant="outline"
title="Open file selection dialog"
/>
</GlyphContainer>
<GlyphContainer>
{isValid ? null : (
<Tooltip title="The specified path is invalid or such file does not exist">
<CenteredGlyph
name="caution-triangle"
color={colors.yellow}
size={16}
/>
</Tooltip>
)}
</GlyphContainer>
</Container>
);
}
FileSelector.defaultProps = defaultProps;

View File

@@ -62,7 +62,6 @@ export function initializeFlipperLibImplementation(
DetailsSidebarImplementation: DetailSidebarImpl,
importFile: renderHost.importFile,
exportFile: renderHost.exportFile,
showOpenDialog: renderHost.showOpenDialog,
paths: {
appPath: renderHost.paths.appPath,
homePath: renderHost.paths.homePath,

View File

@@ -38,3 +38,18 @@ afterEach(cleanup);
console.debug = function () {
// Intentional noop, we don't want debug statements in Jest runs
};
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});