mirror of
https://github.com/transmission/transmission
synced 2024-12-26 01:27:28 +00:00
318 lines
6.9 KiB
JavaScript
318 lines
6.9 KiB
JavaScript
/**
|
|
* Copyright © Jordan Lee, Dave Perrett, Malcolm Jarvis and Bruno Bierbaumer
|
|
*
|
|
* This file is licensed under the GPLv2.
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
*/
|
|
|
|
function PrefsDialog(remote) {
|
|
|
|
var data = {
|
|
dialog: null,
|
|
remote: null,
|
|
elements: { },
|
|
|
|
// all the RPC session keys that we have gui controls for
|
|
keys: [
|
|
'alt-speed-down',
|
|
'alt-speed-time-begin',
|
|
'alt-speed-time-day',
|
|
'alt-speed-time-enabled',
|
|
'alt-speed-time-end',
|
|
'alt-speed-up',
|
|
'blocklist-enabled',
|
|
'blocklist-size',
|
|
'blocklist-url',
|
|
'dht-enabled',
|
|
'download-dir',
|
|
'encryption',
|
|
'idle-seeding-limit',
|
|
'idle-seeding-limit-enabled',
|
|
'lpd-enabled',
|
|
'peer-limit-global',
|
|
'peer-limit-per-torrent',
|
|
'peer-port',
|
|
'peer-port-random-on-start',
|
|
'pex-enabled',
|
|
'port-forwarding-enabled',
|
|
'rename-partial-files',
|
|
'seedRatioLimit',
|
|
'seedRatioLimited',
|
|
'speed-limit-down',
|
|
'speed-limit-down-enabled',
|
|
'speed-limit-up',
|
|
'speed-limit-up-enabled',
|
|
'start-added-torrents',
|
|
'utp-enabled'
|
|
],
|
|
|
|
// map of keys that are enabled only if a 'parent' key is enabled
|
|
groups: {
|
|
'alt-speed-time-enabled': ['alt-speed-time-begin',
|
|
'alt-speed-time-day',
|
|
'alt-speed-time-end' ],
|
|
'blocklist-enabled': ['blocklist-url',
|
|
'blocklist-update-button' ],
|
|
'idle-seeding-limit-enabled': [ 'idle-seeding-limit' ],
|
|
'seedRatioLimited': [ 'seedRatioLimit' ],
|
|
'speed-limit-down-enabled': [ 'speed-limit-down' ],
|
|
'speed-limit-up-enabled': [ 'speed-limit-up' ]
|
|
}
|
|
},
|
|
|
|
initTimeDropDown = function(e)
|
|
{
|
|
var i, hour, mins, value, content;
|
|
|
|
for (i=0; i<24*4; ++i) {
|
|
hour = parseInt(i/4, 10);
|
|
mins = ((i%4) * 15);
|
|
value = i * 15;
|
|
content = hour + ':' + (mins || '00');
|
|
e.options[i] = new Option(content, value);
|
|
}
|
|
},
|
|
|
|
onPortChecked = function(response)
|
|
{
|
|
var is_open = response['arguments']['port-is-open'],
|
|
text = 'Port is <b>' + (is_open ? 'Open' : 'Closed') + '</b>',
|
|
e = data.elements.root.find('#port-label');
|
|
setInnerHTML(e[0],text);
|
|
},
|
|
|
|
setGroupEnabled = function(parent_key, enabled)
|
|
{
|
|
var i, key, keys, root;
|
|
|
|
if (parent_key in data.groups)
|
|
{
|
|
root = data.elements.root,
|
|
keys = data.groups[parent_key];
|
|
|
|
for (i=0; key=keys[i]; ++i)
|
|
root.find('#'+key).attr('disabled',!enabled);
|
|
}
|
|
},
|
|
|
|
onBlocklistUpdateClicked = function ()
|
|
{
|
|
data.remote.updateBlocklist();
|
|
setBlocklistButtonEnabled(false);
|
|
},
|
|
setBlocklistButtonEnabled = function(b)
|
|
{
|
|
var e = data.elements.blocklist_button;
|
|
e.attr('disabled',!b);
|
|
e.val(b ? 'Update' : 'Updating...');
|
|
},
|
|
|
|
getValue = function(e)
|
|
{
|
|
var str;
|
|
|
|
switch (e[0].type)
|
|
{
|
|
case 'checkbox':
|
|
case 'radio':
|
|
return e.prop('checked');
|
|
|
|
case 'text':
|
|
case 'url':
|
|
case 'email':
|
|
case 'number':
|
|
case 'search':
|
|
case 'select-one':
|
|
str = e.val();
|
|
if( parseInt(str,10).toString() === str)
|
|
return parseInt(str,10);
|
|
if( parseFloat(str).toString() === str)
|
|
return parseFloat(str);
|
|
return str;
|
|
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
|
|
/* this callback is for controls whose changes can be applied
|
|
immediately, like checkboxs, radioboxes, and selects */
|
|
onControlChanged = function(ev)
|
|
{
|
|
var o = {};
|
|
o[ev.target.id] = getValue($(ev.target));
|
|
data.remote.savePrefs(o);
|
|
},
|
|
|
|
/* these two callbacks are for controls whose changes can't be applied
|
|
immediately -- like a text entry field -- because it takes many
|
|
change events for the user to get to the desired result */
|
|
onControlFocused = function(ev)
|
|
{
|
|
data.oldValue = getValue($(ev.target));
|
|
},
|
|
onControlBlurred = function(ev)
|
|
{
|
|
var newValue = getValue($(ev.target));
|
|
if (newValue !== data.oldValue)
|
|
{
|
|
var o = {};
|
|
o[ev.target.id] = newValue;
|
|
data.remote.savePrefs(o);
|
|
delete data.oldValue;
|
|
}
|
|
},
|
|
|
|
getDefaultMobileOptions = function()
|
|
{
|
|
return {
|
|
width: $(window).width(),
|
|
height: $(window).height(),
|
|
position: [ 'left', 'top' ]
|
|
};
|
|
},
|
|
|
|
initialize = function (remote)
|
|
{
|
|
var i, key, e, o;
|
|
|
|
data.remote = remote;
|
|
|
|
e = $('#prefs-dialog');
|
|
data.elements.root = e;
|
|
|
|
initTimeDropDown(e.find('#alt-speed-time-begin')[0]);
|
|
initTimeDropDown(e.find('#alt-speed-time-end')[0]);
|
|
|
|
o = isMobileDevice
|
|
? getDefaultMobileOptions()
|
|
: { width: 350, height: 400 };
|
|
o.autoOpen = false;
|
|
o.show = o.hide = 'fade';
|
|
o.close = onDialogClosed;
|
|
e.tabbedDialog(o);
|
|
|
|
e = e.find('#blocklist-update-button');
|
|
data.elements.blocklist_button = e;
|
|
e.click(onBlocklistUpdateClicked);
|
|
|
|
// listen for user input
|
|
for (i=0; key=data.keys[i]; ++i)
|
|
{
|
|
e = data.elements.root.find('#'+key);
|
|
switch (e[0].type)
|
|
{
|
|
case 'checkbox':
|
|
case 'radio':
|
|
case 'select-one':
|
|
e.change(onControlChanged);
|
|
break;
|
|
|
|
case 'text':
|
|
case 'url':
|
|
case 'email':
|
|
case 'number':
|
|
case 'search':
|
|
e.focus(onControlFocused);
|
|
e.blur(onControlBlurred);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
getValues = function()
|
|
{
|
|
var i, key, val, o={},
|
|
keys = data.keys,
|
|
root = data.elements.root;
|
|
|
|
for (i=0; key=keys[i]; ++i) {
|
|
val = getValue(root.find('#'+key));
|
|
if (val !== null)
|
|
o[key] = val;
|
|
}
|
|
|
|
return o;
|
|
},
|
|
|
|
onDialogClosed = function()
|
|
{
|
|
transmission.hideMobileAddressbar();
|
|
|
|
$(data.dialog).trigger('closed', getValues());
|
|
};
|
|
|
|
/****
|
|
***** PUBLIC FUNCTIONS
|
|
****/
|
|
|
|
// update the dialog's controls
|
|
this.set = function (o)
|
|
{
|
|
var e, i, key, val, option,
|
|
keys = data.keys,
|
|
root = data.elements.root;
|
|
|
|
setBlocklistButtonEnabled(true);
|
|
|
|
for (i=0; key=keys[i]; ++i)
|
|
{
|
|
val = o[key];
|
|
e = root.find('#'+key);
|
|
|
|
if (key === 'blocklist-size')
|
|
{
|
|
// special case -- regular text area
|
|
e.text('' + val.toStringWithCommas());
|
|
}
|
|
else switch (e[0].type)
|
|
{
|
|
case 'checkbox':
|
|
case 'radio':
|
|
e.prop('checked', val);
|
|
setGroupEnabled(key, val);
|
|
break;
|
|
case 'text':
|
|
case 'url':
|
|
case 'email':
|
|
case 'number':
|
|
case 'search':
|
|
// don't change the text if the user's editing it.
|
|
// it's very annoying when that happens!
|
|
if (e[0] !== document.activeElement)
|
|
e.val(val);
|
|
break;
|
|
case 'select-one':
|
|
e.val(val);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
this.show = function ()
|
|
{
|
|
transmission.hideMobileAddressbar();
|
|
|
|
setBlocklistButtonEnabled(true);
|
|
data.remote.checkPort(onPortChecked,this);
|
|
data.elements.root.dialog('open');
|
|
};
|
|
|
|
this.close = function ()
|
|
{
|
|
transmission.hideMobileAddressbar();
|
|
data.elements.root.dialog('close');
|
|
},
|
|
|
|
this.shouldAddedTorrentsStart = function()
|
|
{
|
|
return data.elements.root.find('#start-added-torrents')[0].checked;
|
|
};
|
|
|
|
data.dialog = this;
|
|
initialize (remote);
|
|
};
|