Allow only images in modal image uploader. #7672
4 changed files with 63 additions and 8 deletions
|
@ -299,6 +299,32 @@ app.on('before-quit', () => {
|
||||||
appState.isQuitting = true;
|
appState.isQuitting = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Get the content of a file as a raw buffer of bytes.
|
||||||
|
// Useful to convert a file path to a File instance.
|
||||||
|
// Example:
|
||||||
|
// const result = await ipcMain.invoke('get-file-from-path', 'path/to/file');
|
||||||
|
// const file = new File([result.buffer], result.name);
|
||||||
|
ipcMain.handle('get-file-from-path', (event, path) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Encoding null ensures data results in a Buffer.
|
||||||
|
fs.readFile(path, { encoding: null }, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Separate folders considering "\" and "/"
|
||||||
|
// as separators (cross platform)
|
||||||
|
const folders = path.split(/[\\/]/);
|
||||||
|
const fileName = folders[folders.length - 1];
|
||||||
|
resolve({
|
||||||
|
name: fileName,
|
||||||
|
path: path,
|
||||||
|
buffer: data,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on('get-disk-space', async (event) => {
|
ipcMain.on('get-disk-space', async (event) => {
|
||||||
try {
|
try {
|
||||||
const { data_dir } = await Lbry.settings_get();
|
const { data_dir } = await Lbry.settings_get();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as remote from '@electron/remote';
|
import * as remote from '@electron/remote';
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
import Button from 'component/button';
|
import Button from 'component/button';
|
||||||
import { FormField } from 'component/common/form';
|
import { FormField } from 'component/common/form';
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ type Props = {
|
||||||
error?: string,
|
error?: string,
|
||||||
disabled?: boolean,
|
disabled?: boolean,
|
||||||
autoFocus?: boolean,
|
autoFocus?: boolean,
|
||||||
|
filters?: Array<{ name: string, extension: string[] }>,
|
||||||
};
|
};
|
||||||
|
|
||||||
class FileSelector extends React.PureComponent<Props> {
|
class FileSelector extends React.PureComponent<Props> {
|
||||||
|
@ -64,13 +66,26 @@ class FileSelector extends React.PureComponent<Props> {
|
||||||
properties = ['openDirectory'];
|
properties = ['openDirectory'];
|
||||||
}
|
}
|
||||||
|
|
||||||
remote.dialog.showOpenDialog({ properties, defaultPath }).then((result) => {
|
remote.dialog
|
||||||
const path = result && result.filePaths[0];
|
.showOpenDialog({
|
||||||
if (path) {
|
properties,
|
||||||
// $FlowFixMe
|
defaultPath,
|
||||||
this.props.onFileChosen({ path });
|
filters: this.props.filters,
|
||||||
}
|
})
|
||||||
});
|
.then((result) => {
|
||||||
|
const path = result && result.filePaths[0];
|
||||||
|
if (path) {
|
||||||
|
return ipcRenderer.invoke('get-file-from-path', path);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const file = new File([result.buffer], result.name);
|
||||||
|
this.props.onFileChosen(file);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
fileInputButton = () => {
|
fileInputButton = () => {
|
||||||
|
|
|
@ -27,6 +27,14 @@ type Props = {
|
||||||
// passed to the onUpdate function after the
|
// passed to the onUpdate function after the
|
||||||
// upload service returns success.
|
// upload service returns success.
|
||||||
buildImagePreview?: boolean,
|
buildImagePreview?: boolean,
|
||||||
|
// File extension filtering. Files can be filtered
|
||||||
|
// but the "All Files" options always shows up. To
|
||||||
|
// avoid that, you can use the filters property.
|
||||||
|
// For example, to only accept images pass the
|
||||||
|
// following filter:
|
||||||
|
// { name: 'Images', extensions: ['jpg', 'png', 'gif'] },
|
||||||
|
filters?: Array<{ name: string, extension: string[] }>,
|
||||||
|
type?: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
function filePreview(file) {
|
function filePreview(file) {
|
||||||
|
@ -43,7 +51,8 @@ function filePreview(file) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function SelectAsset(props: Props) {
|
function SelectAsset(props: Props) {
|
||||||
const { onUpdate, onDone, assetName, currentValue, recommended, title, inline, buildImagePreview } = props;
|
const { onUpdate, onDone, assetName, currentValue, recommended, title, inline, buildImagePreview, filters, type } =
|
||||||
|
props;
|
||||||
const [pathSelected, setPathSelected] = React.useState('');
|
const [pathSelected, setPathSelected] = React.useState('');
|
||||||
const [fileSelected, setFileSelected] = React.useState<any>(null);
|
const [fileSelected, setFileSelected] = React.useState<any>(null);
|
||||||
const [uploadStatus, setUploadStatus] = React.useState(SPEECH_READY);
|
const [uploadStatus, setUploadStatus] = React.useState(SPEECH_READY);
|
||||||
|
@ -121,6 +130,8 @@ function SelectAsset(props: Props) {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<FileSelector
|
<FileSelector
|
||||||
|
filters={filters}
|
||||||
|
type={type}
|
||||||
autoFocus
|
autoFocus
|
||||||
disabled={uploadStatus === SPEECH_UPLOADING}
|
disabled={uploadStatus === SPEECH_UPLOADING}
|
||||||
label={fileSelectorLabel}
|
label={fileSelectorLabel}
|
||||||
|
|
|
@ -14,10 +14,13 @@ type Props = {
|
||||||
|
|
||||||
function ModalImageUpload(props: Props) {
|
function ModalImageUpload(props: Props) {
|
||||||
const { closeModal, currentValue, title, assetName, helpText, onUpdate } = props;
|
const { closeModal, currentValue, title, assetName, helpText, onUpdate } = props;
|
||||||
|
const filters = React.useMemo(() => [{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen type="card" onAborted={closeModal} contentLabel={title}>
|
<Modal isOpen type="card" onAborted={closeModal} contentLabel={title}>
|
||||||
<SelectAsset
|
<SelectAsset
|
||||||
|
filters={filters}
|
||||||
|
type="openFile"
|
||||||
onUpdate={onUpdate}
|
onUpdate={onUpdate}
|
||||||
currentValue={currentValue}
|
currentValue={currentValue}
|
||||||
assetName={assetName}
|
assetName={assetName}
|
||||||
|
|
Loading…
Add table
Reference in a new issue