Install plugin from package file

Summary:
Adding a way to install plugins directly from package files. This is required for testing after packaging format changes.

Stage 2: Added new component for file selection and implemented UI required for plugin installation from package file

Reviewed By: priteshrnandgaonkar

Differential Revision: D19743998

fbshipit-source-id: 1112d5afca9a649df11e33eb6ac15c0e06747d47
This commit is contained in:
Anton Nikolaev
2020-02-06 08:00:01 -08:00
committed by Facebook Github Bot
parent 15ed856388
commit 984cdbfb67
3 changed files with 199 additions and 28 deletions

View File

@@ -0,0 +1,127 @@
/**
* 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 FlexColumn from './FlexColumn';
import Glyph from './Glyph';
import Input from './Input';
import electron from 'electron';
import styled from '@emotion/styled';
import {colors} from './colors';
import Electron from 'electron';
import fs from 'fs';
const CenteredGlyph = styled(Glyph)({
flexGrow: 0,
margin: 'auto',
marginLeft: 10,
});
const Container = styled(FlexRow)({
width: '100%',
});
const FileInputBox = styled(Input)<{isValid: boolean}>(({isValid}) => ({
flexGrow: 1,
color: isValid ? undefined : colors.red,
'&::-webkit-input-placeholder': {
color: colors.placeholder,
fontWeight: 300,
},
}));
function strToArr<T extends string>(item: T): T[] {
return [item];
}
export interface Props {
onPathChanged: (evtArgs: {path: string; isValid: boolean}) => void;
placeholderText: string;
defaultPath: string;
showHiddenFiles: boolean;
}
const defaultProps: Props = {
onPathChanged: () => {},
placeholderText: '',
defaultPath: '/',
showHiddenFiles: false,
};
export default function FileSelector({
onPathChanged,
placeholderText,
defaultPath,
showHiddenFiles,
}: Props) {
const [value, setValue] = useState('');
const [isValid, setIsValid] = useState(false);
const options: Electron.OpenDialogOptions = {
properties: [
'openFile',
...(showHiddenFiles ? strToArr('showHiddenFiles') : []),
],
defaultPath,
};
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={true}
onDrop={e => {
if (e.dataTransfer.files.length) {
onChange(e.dataTransfer.files[0].path);
}
}}
onChange={e => {
onChange(e.target.value);
}}
/>
<FlexColumn
onClick={() =>
electron.remote.dialog
.showOpenDialog(options)
.then((result: electron.OpenDialogReturnValue) => {
if (result && !result.canceled && result.filePaths.length) {
onChange(result.filePaths[0]);
}
})
}>
<CenteredGlyph
name="dots-3-circle"
variant="outline"
title="Open file selection dialog"
/>
</FlexColumn>
{isValid ? null : (
<CenteredGlyph
name="caution-triangle"
color={colors.yellow}
title="Path is invalid"
/>
)}
</Container>
);
}
FileSelector.defaultProps = defaultProps;

View File

@@ -48,12 +48,20 @@ function ColoredIcon(
className?: string;
color?: string;
style?: React.CSSProperties;
title?: string;
},
context: {
glyphColor?: string;
},
) {
const {color = context.glyphColor, name, size = 16, src, style} = props;
const {
color = context.glyphColor,
name,
size = 16,
src,
style,
title,
} = props;
const isBlack =
color == null ||
@@ -69,6 +77,7 @@ function ColoredIcon(
size={size}
className={props.className}
style={style}
title={title}
/>
);
} else {
@@ -79,6 +88,7 @@ function ColoredIcon(
src={src}
className={props.className}
style={style}
title={title}
/>
);
}
@@ -98,7 +108,15 @@ export default class Glyph extends React.PureComponent<{
title?: string;
}> {
render() {
const {name, size = 16, variant, color, className, style} = this.props;
const {
name,
size = 16,
variant,
color,
className,
style,
title,
} = this.props;
return (
<ColoredIcon
@@ -106,6 +124,7 @@ export default class Glyph extends React.PureComponent<{
className={className}
color={color}
size={size}
title={title}
src={getIconURL(
variant === 'outline' ? `${name}-outline` : name,
size,