Simplify prefs window
This commit is contained in:
@@ -542,6 +542,9 @@ function resumeTorrents () {
|
|||||||
.forEach((x) => startTorrentingSummary(x))
|
.forEach((x) => startTorrentingSummary(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updates a single property in the UNSAVED prefs
|
||||||
|
// For example: updatePreferences("foo.bar", "baz")
|
||||||
|
// Call savePreferences to save to config.json
|
||||||
function updatePreferences (property, value) {
|
function updatePreferences (property, value) {
|
||||||
var path = property.split('.')
|
var path = property.split('.')
|
||||||
var key = state.unsaved.prefs
|
var key = state.unsaved.prefs
|
||||||
@@ -554,6 +557,7 @@ function updatePreferences (property, value) {
|
|||||||
key[path[i]] = value
|
key[path[i]] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All unsaved prefs take effect atomically, and are saved to config.json
|
||||||
function savePreferences () {
|
function savePreferences () {
|
||||||
state.saved.prefs = Object.assign(state.saved.prefs || {}, state.unsaved.prefs)
|
state.saved.prefs = Object.assign(state.saved.prefs || {}, state.unsaved.prefs)
|
||||||
saveState()
|
saveState()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
module.exports = Preferences
|
module.exports = Preferences
|
||||||
|
|
||||||
var fs = require('fs-extra')
|
|
||||||
var h = require('virtual-dom/h')
|
var h = require('virtual-dom/h')
|
||||||
var hyperx = require('hyperx')
|
var hyperx = require('hyperx')
|
||||||
var hx = hyperx(h)
|
var hx = hyperx(h)
|
||||||
@@ -9,46 +8,70 @@ var {dispatch} = require('../lib/dispatcher')
|
|||||||
var remote = require('electron').remote
|
var remote = require('electron').remote
|
||||||
var dialog = remote.dialog
|
var dialog = remote.dialog
|
||||||
|
|
||||||
var prefState
|
|
||||||
|
|
||||||
function Preferences (state) {
|
function Preferences (state) {
|
||||||
prefState = state.unsaved.prefs
|
|
||||||
var definitions = getPreferenceDefinitions()
|
|
||||||
var sections = []
|
|
||||||
|
|
||||||
definitions.forEach(function (sectionDefinition) {
|
|
||||||
sections.push(renderSection(sectionDefinition))
|
|
||||||
})
|
|
||||||
|
|
||||||
return hx`
|
return hx`
|
||||||
<div class='preferences'>
|
<div class='preferences'>
|
||||||
${sections}
|
${renderGeneralSection(state)}
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderSection (definition) {
|
function renderGeneralSection (state) {
|
||||||
var controls = []
|
return renderSection({
|
||||||
|
title: 'General',
|
||||||
|
description: '',
|
||||||
|
icon: 'settings'
|
||||||
|
}, [
|
||||||
|
renderDownloadDirSelector(state)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
definition.controls.forEach(function (controlDefinition) {
|
function renderDownloadDirSelector (state) {
|
||||||
controls.push(controlDefinition.renderer(controlDefinition))
|
return renderFileSelector({
|
||||||
|
label: 'Download Path',
|
||||||
|
description: 'Data from torrents will be saved here',
|
||||||
|
property: 'downloadPath',
|
||||||
|
options: {
|
||||||
|
title: 'Select download directory',
|
||||||
|
properties: [ 'openDirectory' ]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
state.unsaved.prefs.downloadPath,
|
||||||
|
function (filePath) {
|
||||||
|
setStateValue('downloadPath', filePath)
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renders a prefs section.
|
||||||
|
// - definition should be {icon, title, description}
|
||||||
|
// - controls should be an array of vdom elements
|
||||||
|
function renderSection (definition, controls) {
|
||||||
|
var helpElem = !definition.description ? null : hx`
|
||||||
|
<div class='help text'>
|
||||||
|
<i.icon>help_outline</i>${definition.description}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
return hx`
|
return hx`
|
||||||
<section class='section preferences-panel'>
|
<section class='section preferences-panel'>
|
||||||
<div class='section-container'>
|
<div class='section-container'>
|
||||||
<div class='section-heading'><i.icon>${definition.icon}</i>${definition.title}</div>
|
<div class='section-heading'>
|
||||||
<div class='help text'><i.icon>help_outline</i>${definition.description}</div>
|
<i.icon>${definition.icon}</i>${definition.title}
|
||||||
<div class='section-body'>
|
</div>
|
||||||
|
${helpElem}
|
||||||
|
<div class='section-body'>
|
||||||
${controls}
|
${controls}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderFileSelector (definition) {
|
// Creates a file chooser
|
||||||
var value = getStateValue(definition.property)
|
// - defition should be {label, description, options}
|
||||||
|
// options are passed to dialog.showOpenDialog
|
||||||
|
// - value should be the current pref, a file or folder path
|
||||||
|
// - callback takes a new file or folder path
|
||||||
|
function renderFileSelector (definition, value, callback) {
|
||||||
return hx`
|
return hx`
|
||||||
<div class='control-group'>
|
<div class='control-group'>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
@@ -58,98 +81,24 @@ function renderFileSelector (definition) {
|
|||||||
</label>
|
</label>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
<input type='text' class='file-picker-text'
|
<input type='text' class='file-picker-text'
|
||||||
id=${definition.property} placeholder=${definition.placeholder}
|
id=${definition.property}
|
||||||
readonly='readonly'
|
disabled='disabled'
|
||||||
value=${value}/>
|
value=${value} />
|
||||||
<button class='btn' onclick=${filePickerHandler}><i.icon>folder_open</i></button>
|
<button class='btn' onclick=${handleClick}>
|
||||||
|
<i.icon>folder_open</i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
function filePickerHandler () {
|
function handleClick () {
|
||||||
dialog.showOpenDialog(remote.getCurrentWindow(), definition.options, function (filenames) {
|
dialog.showOpenDialog(remote.getCurrentWindow(), definition.options, function (filenames) {
|
||||||
if (!Array.isArray(filenames)) return
|
if (!Array.isArray(filenames)) return
|
||||||
if (!definition.validator || definition.validator(filenames[0])) {
|
callback(filenames[0])
|
||||||
setStateValue(definition.property, filenames[0])
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
function renderCheckbox (definition) {
|
|
||||||
var checked = getStateValue(definition.property)
|
|
||||||
var checkbox = checked ? 'check_box' : 'check_box_outline_blank'
|
|
||||||
return hx`
|
|
||||||
<div class='control-group'>
|
|
||||||
<div class='controls'>
|
|
||||||
<div class='checkbox'>
|
|
||||||
<label class='control-label'>
|
|
||||||
<i.icon onclick=${checkboxHandler}>${checkbox}</i>
|
|
||||||
<div class='preference-title' onclick=${checkboxHandler}>${definition.label}</div>
|
|
||||||
</label>
|
|
||||||
<div class='preference-description'>${definition.description}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
function checkboxHandler (e) {
|
|
||||||
setStateValue(definition.property, !getStateValue(definition.property))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
function getPreferenceDefinitions () {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
title: 'General',
|
|
||||||
description: 'These are WebTorrent Desktop main preferences. Will put a very long text to check if it overflows correctly.',
|
|
||||||
icon: 'settings',
|
|
||||||
controls: [
|
|
||||||
{
|
|
||||||
label: 'Download Path',
|
|
||||||
description: 'Directory where the files will be stored. Please, check if it has enough space!',
|
|
||||||
property: 'downloadPath',
|
|
||||||
renderer: renderFileSelector,
|
|
||||||
placeholder: 'Your downloads directory ie: $HOME/Downloads',
|
|
||||||
options: {
|
|
||||||
title: 'Select download directory.',
|
|
||||||
properties: [ 'openDirectory' ]
|
|
||||||
},
|
|
||||||
validator: function (value) {
|
|
||||||
return fs.existsSync(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}/*,
|
|
||||||
{
|
|
||||||
title: 'Interface',
|
|
||||||
description: 'Here you can change the way the application looks and beahaves.',
|
|
||||||
icon: 'view_compact',
|
|
||||||
controls: [
|
|
||||||
{
|
|
||||||
label: 'Disable Tray',
|
|
||||||
description: 'This option gives you the chance to quit immediately and don\'t send the application to background when you close it.',
|
|
||||||
property: 'interface.disableTray',
|
|
||||||
renderer: renderCheckbox
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}*/
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function getStateValue (property) {
|
|
||||||
var path = property.split('.')
|
|
||||||
var key = prefState
|
|
||||||
for (var i = 0; i < path.length - 1; i++) {
|
|
||||||
if (typeof key[path[i]] === 'undefined') {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
key = key[path[i]]
|
|
||||||
}
|
|
||||||
return key[path[i]]
|
|
||||||
}
|
|
||||||
|
|
||||||
function setStateValue (property, value) {
|
function setStateValue (property, value) {
|
||||||
dispatch('updatePreferences', property, value)
|
dispatch('updatePreferences', property, value)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user