Add Connect to server form

This commit is contained in:
futpib 2018-11-19 23:11:01 +03:00
parent ab8f7d698c
commit 4ab936986f
7 changed files with 176 additions and 53 deletions

View File

@ -14,6 +14,7 @@ const ref = memoizeWith(autoFocus => String(Boolean(autoFocus)), autoFocus => in
const Button = props => r.button({
ref,
className: 'button',
type: 'button',
...props,
}, props.children);

View File

@ -11,15 +11,23 @@ const {
Provider,
} = require('@futpib/react-electron-menu');
const MenuProvider = ({ children }) => r(Provider, { electron }, r(React.Fragment, {}, [
r(WindowMenu),
const MenuProvider = ({ children, ...props }) => r(Provider, { electron }, r(React.Fragment, {}, [
r(WindowMenu, props),
...[].concat(children),
]));
const WindowMenu = () => r(WindowMenuBase, [
const WindowMenu = ({ openConnectToServerModal }) => r(WindowMenuBase, [
r(MenuItem, {
label: 'App',
label: 'File',
}, [
r(MenuItem, {
label: 'Connect to server...',
accelerator: 'CommandOrControl+N',
onClick: openConnectToServerModal,
}),
r(MenuItem.Separator),
r(MenuItem, {
label: 'Quit',
role: 'quit',

View File

@ -0,0 +1,51 @@
const r = require('r-dom');
const React = require('react');
const Modal = require('react-modal');
const Checkbox = require('../checkbox');
const Button = require('../button');
class ConfirmationModal extends React.PureComponent {
render() {
const { target, confirmation, onConfirm, onCancel } = this.props;
return r(Modal, {
isOpen: Boolean(confirmation),
onRequestClose: onCancel,
}, [
confirmation === 'unloadModuleByIndex' && r(React.Fragment, [
r.h3('Module unload confirmation'),
target && r.p([
'You are about to unload ',
r.code(target.name),
'.',
'This may not be easily undoable and may impair sound playback on your system.',
]),
]),
r(Checkbox, {
checked: this.props.preferences.doNotAskForConfirmations,
onChange: () => this.props.toggle('doNotAskForConfirmations'),
}, 'Do not ask for confirmations'),
r.div({
className: 'button-group',
}, [
r(Button, {
onClick: onCancel,
}, 'Cancel'),
r(Button, {
onClick: onConfirm,
autoFocus: true,
}, 'Confirm'),
]),
]);
}
}
module.exports = ConfirmationModal;

View File

@ -0,0 +1,87 @@
const { spawn } = require('child_process');
const {
merge,
} = require('ramda');
const r = require('r-dom');
const React = require('react');
const Modal = require('react-modal');
const Button = require('../button');
const Label = require('../label');
const Input = require('../input');
class ConnectToServerModal extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
value: 'tcp:remote-computer.lan',
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
const subprocess = spawn('pagraphcontrol', [], {
detached: true,
stdio: 'ignore',
env: merge(process.env, {
PULSE_SERVER: this.state.value,
}),
});
subprocess.unref();
this.props.onRequestClose();
}
render() {
const { isOpen, onRequestClose } = this.props;
return r(Modal, {
isOpen,
onRequestClose,
}, [
r.h3('Connect to PulseAudio server'),
r.form({
onSubmit: this.handleSubmit,
}, [
r(Label, [
r.div({
title: 'Same format as PULSE_SERVER',
}, 'Specify the server to connect to:'),
r.p([
r(Input, {
style: { width: '100%' },
autoFocus: true,
value: this.state.value,
onChange: e => this.setState({ value: e.target.value }),
}),
]),
]),
r.div({
className: 'button-group',
}, [
r(Button, {
onClick: onRequestClose,
}, 'Cancel'),
r(Button, {
type: 'submit',
}, 'Connect'),
]),
]),
]);
}
}
module.exports = ConnectToServerModal;

View File

@ -26,8 +26,8 @@ const {
const { modules } = require('../../constants/pulse');
const Checkbox = require('../checkbox');
const Button = require('../button');
const ConnectToServerModal = require('./connect-to-server');
const ConfirmationModal = require('./confirmation');
Modal.setAppElement('#root');
@ -36,46 +36,6 @@ Modal.defaultStyles = {
content: {},
};
class ConfirmationModal extends React.PureComponent {
render() {
const { target, confirmation, onConfirm, onCancel } = this.props;
return r(Modal, {
isOpen: Boolean(confirmation),
onRequestClose: onCancel,
}, [
confirmation === 'unloadModuleByIndex' && r(React.Fragment, [
r.h3('Module unload confirmation'),
target && r.p([
'You are about to unload ',
r.code(target.name),
'.',
'This may not be easily undoable and may impair sound playback on your system.',
]),
]),
r(Checkbox, {
checked: this.props.preferences.doNotAskForConfirmations,
onChange: () => this.props.toggle('doNotAskForConfirmations'),
}, 'Do not ask for confirmations'),
r.div({
className: 'button-group',
}, [
r(Button, {
onClick: onCancel,
}, 'Cancel'),
r(Button, {
onClick: onConfirm,
autoFocus: true,
}, 'Confirm'),
]),
]);
}
}
class Modals extends React.PureComponent {
constructor(props) {
super(props);
@ -84,15 +44,21 @@ class Modals extends React.PureComponent {
target: null,
confirmation: null,
continuation: null,
connectToServerModalOpen: false,
actions: {
openConnectToServerModal: this.openConnectToServerModal.bind(this),
},
};
this.state = this.initialState;
this.handleCancel = this.handleCancel.bind(this);
}
static getDerivedStateFromProps(props) {
static getDerivedStateFromProps(props, state) {
return {
actions: mapObjIndexed((f, name) => function (...args) {
actions: merge(state.actions, mapObjIndexed((f, name) => function (...args) {
const continuation = () => {
props[name](...args);
this.setState(this.initialState);
@ -123,10 +89,14 @@ class Modals extends React.PureComponent {
return null;
},
}),
})),
};
}
openConnectToServerModal() {
this.setState({ connectToServerModalOpen: true });
}
handleCancel() {
this.setState(this.initialState);
}
@ -136,7 +106,7 @@ class Modals extends React.PureComponent {
const { actions, target, confirmation, continuation } = this.state;
return r(React.Fragment, [
...children({ actions: map(a => a.bind(this), actions) }),
...[].concat(children({ actions: map(a => a.bind(this), actions) })),
r(ConfirmationModal, {
target,
@ -147,6 +117,11 @@ class Modals extends React.PureComponent {
preferences,
toggle,
}),
r(ConnectToServerModal, {
isOpen: this.state.connectToServerModalOpen,
onRequestClose: this.handleCancel,
}),
]);
}
}

View File

@ -20,10 +20,11 @@ const theme = require('./utils/theme');
const Root = () => r(ReduxProvider, {
store: createStore(),
}, r(MenuProvider, {
}, r(HotKeys, {
}, ({ graphRef, cardsRef, preferencesRef }) => r(Modals, {
}, ({ actions }) => [
}, ({ actions }) => r(MenuProvider, {
...actions,
}, [
r(Graph, { ref: graphRef, ...actions }),
r(Cards, { ref: cardsRef }),
r(Preferences, { ref: preferencesRef }),

View File

@ -119,7 +119,7 @@ module.exports = store => {
store.dispatch(pulseActions.remove({ type, index }));
})
.on('error', error => {
console.error(error);
handleError(error);
});
const reconnect = () => new Bluebird((resolve, reject) => {