diff --git a/CHANGELOG.md b/CHANGELOG.md index fd4f4efb6..bf84a1a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,8 +23,8 @@ Web UI version numbers should always match the corresponding version of LBRY App * Enable windows code signing of binary ### Changed - * - * + * Use directory selector instead of ugly text box on Settings page + * Use Electron's native file selector everywhere instead of WebKit file selector ### Fixed * Error modals now display full screen properly diff --git a/ui/js/component/file-selector.js b/ui/js/component/file-selector.js new file mode 100644 index 000000000..4670f4830 --- /dev/null +++ b/ui/js/component/file-selector.js @@ -0,0 +1,58 @@ +import React from 'react'; + +const {remote} = require('electron'); +class FileSelector extends React.Component { + static propTypes = { + type: React.PropTypes.oneOf(['file', 'directory']), + initPath: React.PropTypes.string, + onFileChosen: React.PropTypes.func, + } + + static defaultProps = { + type: 'file', + } + + componentWillMount() { + this.setState({ + path: this.props.initPath || null, + }); + } + + handleButtonClick() { + remote.dialog.showOpenDialog({ + properties: [this.props.type == 'file' ? 'openFile' : 'openDirectory'], + }, (paths) => { + if (!paths) { // User hit cancel, so do nothing + return; + } + + const path = paths[0]; + this.setState({ + path: path, + }); + if (this.props.onFileChosen) { + this.props.onFileChosen(path); + } + }); + } + + render() { + return ( +
+ + {' '} + + {this.state.path ? + this.state.path : + 'No File Chosen'} + +
+ ); + } +}; + +export default FileSelector; diff --git a/ui/js/component/form.js b/ui/js/component/form.js index f75310c92..d5deaf23c 100644 --- a/ui/js/component/form.js +++ b/ui/js/component/form.js @@ -1,7 +1,9 @@ import React from 'react'; +import FileSelector from './file-selector.js'; import {Icon} from './common.js'; var formFieldCounter = 0, + formFieldFileSelectorTypes = ['file', 'directory'], formFieldNestedLabelTypes = ['radio', 'checkbox']; function formFieldId() { @@ -19,6 +21,14 @@ export let FormField = React.createClass({ postfix: React.PropTypes.string, hasError: React.PropTypes.bool }, + handleFileChosen: function(path) { + this.refs.field.value = path; + if (this.props.onChange) { // Updating inputs programmatically doesn't generate an event, so we have to make our own + const event = new Event('change', {bubbles: true}) + this.refs.field.dispatchEvent(event); // This alone won't generate a React event, but we use it to attach the field as a target + this.props.onChange(event); + } + }, getInitialState: function() { return { isError: null, @@ -26,17 +36,29 @@ export let FormField = React.createClass({ } }, componentWillMount: function() { - if (['text', 'number', 'radio', 'checkbox', 'file'].includes(this.props.type)) { + if (['text', 'number', 'radio', 'checkbox'].includes(this.props.type)) { this._element = 'input'; this._type = this.props.type; } else if (this.props.type == 'text-number') { this._element = 'input'; this._type = 'text'; + } else if (formFieldFileSelectorTypes.includes(this.props.type)) { + this._element = 'input'; + this._type = 'hidden'; } else { // Non field, e.g.