Add cards

This commit is contained in:
futpib 2018-11-13 06:01:58 +03:00
parent 79f3ce458a
commit 74badced08
11 changed files with 159 additions and 23 deletions

View File

@ -31,5 +31,7 @@ module.exports = createActionCreators({
SET_SOURCE_CHANNEL_VOLUME: (index, channelIndex, volume) => ({ index, channelIndex, volume }), SET_SOURCE_CHANNEL_VOLUME: (index, channelIndex, volume) => ({ index, channelIndex, volume }),
SET_SINK_INPUT_CHANNEL_VOLUME: (index, channelIndex, volume) => ({ index, channelIndex, volume }), SET_SINK_INPUT_CHANNEL_VOLUME: (index, channelIndex, volume) => ({ index, channelIndex, volume }),
SET_SOURCE_OUTPUT_CHANNEL_VOLUME: (index, channelIndex, volume) => ({ index, channelIndex, volume }), SET_SOURCE_OUTPUT_CHANNEL_VOLUME: (index, channelIndex, volume) => ({ index, channelIndex, volume }),
SET_CARD_PROFILE: (index, profileName) => ({ index, profileName }),
}, },
}); });

View File

@ -2,6 +2,7 @@
const r = require('r-dom'); const r = require('r-dom');
const Button = props => r.button({ const Button = props => r.button({
className: 'button',
...props, ...props,
}, props.children); }, props.children);

83
components/cards/index.js Normal file
View File

@ -0,0 +1,83 @@
const {
values,
map,
path,
} = require('ramda');
const r = require('r-dom');
const { connect } = require('react-redux');
const { bindActionCreators } = require('redux');
const { withStateHandlers } = require('recompose');
const { pulse: pulseActions } = require('../../actions');
const Button = require('../button');
const Label = require('../label');
const Select = require('../select');
const Preferences = withStateHandlers(
{
open: false,
},
{
toggle: ({ open }) => () => ({ open: !open }),
},
)(({ open, toggle, ...props }) => r.div({
classSet: {
panel: true,
cards: true,
open,
},
}, open ? [
r.div([
r(Button, {
style: { width: '100%' },
onClick: toggle,
}, 'Close'),
]),
r.hr(),
...map(card => r(Label, {
title: card.name,
}, [
r(Label, [
path([ 'properties', 'device', 'description' ], card),
]),
r(Select, {
options: card.profiles,
optionValue: p => p.name,
optionText: p => p.description,
value: card.activeProfileName,
onChange: e => {
props.actions.setCardProfile(card.index, e.target.value);
},
}),
]), values(props.cards)),
props.preferences.showDebugInfo && r.pre({
style: {
fontSize: '0.75em',
},
}, [
JSON.stringify(props, null, 2),
]),
] : [
r(Button, {
onClick: toggle,
}, 'Cards'),
]));
module.exports = connect(
state => ({
cards: state.pulse.infos.cards,
preferences: state.preferences,
}),
dispatch => ({
actions: bindActionCreators(pulseActions, dispatch),
}),
)(Preferences);

View File

@ -3,4 +3,5 @@ const r = require('r-dom');
module.exports = props => r.label({ module.exports = props => r.label({
className: 'label', className: 'label',
...props,
}, props.children); }, props.children);

View File

@ -26,6 +26,7 @@ const Preferences = withStateHandlers(
}, },
)(({ open, toggle, ...props }) => r.div({ )(({ open, toggle, ...props }) => r.div({
classSet: { classSet: {
panel: true,
preferences: true, preferences: true,
open, open,
}, },

View File

@ -0,0 +1,7 @@
const r = require('r-dom');
module.exports = ({ options, optionValue, optionText, ...props }) => r.select({
className: 'select',
...props,
}, options.map(o => r.option({ value: optionValue(o) }, optionText(o))));

View File

@ -9,7 +9,7 @@ div {
box-sizing: border-box; box-sizing: border-box;
} }
button { .button {
background: var(--themeBgColor); background: var(--themeBgColor);
color: var(--themeTextColor); color: var(--themeTextColor);
border: 1px solid var(--borders); border: 1px solid var(--borders);
@ -18,16 +18,16 @@ button {
padding: 8px; padding: 8px;
} }
button:hover { .button:hover {
border-color: var(--themeSelectedBgColor); border-color: var(--themeSelectedBgColor);
} }
button:focus { .button:focus {
outline: none; outline: none;
border-color: var(--themeSelectedBgColor); border-color: var(--themeSelectedBgColor);
} }
button:active { .button:active {
background: var(--themeSelectedBgColor); background: var(--themeSelectedBgColor);
position: relative; position: relative;
top: 1px; top: 1px;
@ -62,6 +62,21 @@ button:active {
width: 64px; width: 64px;
} }
.select {
background: var(--themeUnfocusedBgColor);
color: var(--themeUnfocusedFgColor);
border: 1px solid var(--borders);
padding: 4px;
cursor: pointer;
}
.select:hover {
border-color: var(--themeSelectedBgColor);
}
.select:focus {
outline: none;
border-color: var(--themeSelectedBgColor);
}
.view-wrapper .graph { .view-wrapper .graph {
background: var(--themeBaseColor); background: var(--themeBaseColor);
} }
@ -138,28 +153,35 @@ button:active {
opacity: 1; opacity: 1;
} }
.preferences { .panel {
position: absolute; position: absolute;
right: 0;
top: 0; top: 0;
bottom: 0; bottom: 0;
padding: 1rem; padding: 1rem;
overflow: auto; overflow: auto;
} }
.preferences:not(.open) { .cards {
left: 0;
}
.preferences {
right: 0;
}
.panel:not(.open) {
pointer-events: none; pointer-events: none;
} }
.preferences:not(.open) > * { .panel:not(.open) > * {
pointer-events: initial; pointer-events: initial;
} }
.preferences.open { .panel.open {
background: var(--themeBgColor); background: var(--themeBgColor);
} }
.preferences > hr { .panel > hr {
border: none; border: none;
border-top: 1px solid var(--borders); border-top: 1px solid var(--borders);
} }

View File

@ -21,7 +21,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@futpib/paclient": "^0.0.5", "@futpib/paclient": "^0.0.7",
"bluebird": "^3.5.3", "bluebird": "^3.5.3",
"camelcase": "^5.0.0", "camelcase": "^5.0.0",
"electron-store": "^2.0.0", "electron-store": "^2.0.0",

View File

@ -11,6 +11,7 @@ const { Provider } = require('react-redux');
const createStore = require('./store'); const createStore = require('./store');
const Graph = require('./components/graph'); const Graph = require('./components/graph');
const Cards = require('./components/cards');
const Preferences = require('./components/preferences'); const Preferences = require('./components/preferences');
const theme = require('./utils/theme'); const theme = require('./utils/theme');
@ -19,6 +20,7 @@ const Root = () => r(Provider, {
store: createStore(), store: createStore(),
}, r(React.Fragment, [ }, r(React.Fragment, [
r(Graph), r(Graph),
r(Cards),
r(Preferences), r(Preferences),
])); ]));

View File

@ -51,7 +51,19 @@ function setSourceOutputChannelVolume(pa, store, index, channelIndex, volume, cb
module.exports = store => { module.exports = store => {
const pa = new PAClient(); const pa = new PAClient();
const getInfo = (type, index) => pa[getFnFromType(type)](index, (err, info) => { const getInfo = (type, index) => {
let method;
try {
method = getFnFromType(type);
} catch (error) {
if (error.message.startsWith('Unexpected type:')) {
console.warn(error);
return;
}
throw error;
}
pa[method](index, (err, info) => {
if (err) { if (err) {
if (err.message === 'No such entity') { if (err.message === 'No such entity') {
console.warn(err.message, type, index); console.warn(err.message, type, index);
@ -62,6 +74,7 @@ module.exports = store => {
info.type = info.type || type; info.type = info.type || type;
store.dispatch(pulseActions.info(info)); store.dispatch(pulseActions.info(info));
}); });
};
pa pa
.on('ready', () => { .on('ready', () => {
@ -178,6 +191,10 @@ module.exports = store => {
return setSourceOutputChannelVolume(pa, store, index, channelIndex, volume, rethrow); return setSourceOutputChannelVolume(pa, store, index, channelIndex, volume, rethrow);
}, },
[pulseActions.setCardProfile]: (state, { payload: { index, profileName } }) => {
pa.setCardProfile(index, profileName, rethrow);
return state;
},
}, null); }, null);
return next => action => { return next => action => {

View File

@ -84,10 +84,10 @@
dependencies: dependencies:
arrify "^1.0.1" arrify "^1.0.1"
"@futpib/paclient@^0.0.5": "@futpib/paclient@^0.0.7":
version "0.0.5" version "0.0.7"
resolved "https://registry.yarnpkg.com/@futpib/paclient/-/paclient-0.0.5.tgz#0de89ee7175e3de994bc298ddb1e461aa3007543" resolved "https://registry.yarnpkg.com/@futpib/paclient/-/paclient-0.0.7.tgz#d8957135ba81888f5e92812d8e9e4e8e1ebf935f"
integrity sha512-49jeRSEOXto3MntDj2Dzm4t7U9M0X41seqF+T/xwFRYk/pBUKdiXHuofNFJvn4rwM7P4BVjxU6fRpCOEAxH/VA== integrity sha512-fjpJaS3LHuo+51/7g3dqpZBGO2wZtnLAWYKVk5CIBsfqn3345xJaEe0HfLpBxPAdpAHRTcTz5aWXlhOWsBClHA==
"@ladjs/time-require@^0.1.4": "@ladjs/time-require@^0.1.4":
version "0.1.4" version "0.1.4"