All checks were successful
continuous-integration/drone/push Build is passing
256 lines
8.1 KiB
JavaScript
256 lines
8.1 KiB
JavaScript
/**
|
||
* Script: ppsfleet.js
|
||
* The client-side javascript code for the PPSFleet plugin.
|
||
*
|
||
* Copyright:
|
||
* (C) BlackSponge 2020 <blacksponge@tuta.io>
|
||
*
|
||
* This file is part of PPSFleet and is licensed under GNU GPL 3.0, or
|
||
* later, with the additional special exception to link portions of this
|
||
* program with the OpenSSL library. See LICENSE for more details.
|
||
*/
|
||
|
||
|
||
Ext.ns('Deluge.ux.preferences');
|
||
|
||
/**
|
||
* @class Deluge.ux.preferences.PPSFleetPage
|
||
* @extends Ext.Panel
|
||
*/
|
||
Deluge.ux.preferences.PPSFleetPage = Ext.extend(Ext.Panel, {
|
||
title: _('PPSFleet'),
|
||
header: false,
|
||
layout: 'fit',
|
||
border: false,
|
||
|
||
constructor: function(config) {
|
||
Deluge.ux.preferences.PPSFleetPage.superclass.constructor.call(this, config);
|
||
deluge.client.on('connected', this.updateConfig, this);
|
||
},
|
||
|
||
initComponent: function() {
|
||
Deluge.ux.preferences.PPSFleetPage.superclass.initComponent.call(this);
|
||
|
||
this.form = this.add({
|
||
xtype: 'form',
|
||
layout: 'form',
|
||
border: false,
|
||
autoHeight: true,
|
||
});
|
||
|
||
fieldset = this.form.add({
|
||
xtype: 'fieldset',
|
||
border: false,
|
||
title: '',
|
||
autoHeight: true,
|
||
labelAlign: 'top',
|
||
labelWidth: 80,
|
||
defaultType: 'textfield',
|
||
});
|
||
|
||
this.files_root_dir = fieldset.add({
|
||
fieldLabel: _('Web server root directory:'),
|
||
labelSeparator: '',
|
||
name: 'files_root_dir',
|
||
width: '97%',
|
||
});
|
||
|
||
fieldset = this.form.add({
|
||
xtype: 'fieldset',
|
||
border: false,
|
||
title: '',
|
||
autoHeight: true,
|
||
labelAlign: 'top',
|
||
labelWidth: 80,
|
||
defaultType: 'textfield',
|
||
});
|
||
|
||
this.files_base_url = fieldset.add({
|
||
fieldLabel: _('Web server base url:'),
|
||
labelSeparator: '',
|
||
name: 'files_base_url',
|
||
width: '97%',
|
||
});
|
||
|
||
this.on('show', this.updateConfig, this);
|
||
},
|
||
|
||
onApply: function() {
|
||
// build settings object
|
||
var config = {};
|
||
|
||
config['files_root_dir'] = this.files_root_dir.getValue();
|
||
config['files_base_url'] = this.files_base_url.getValue();
|
||
|
||
deluge.client.ppsfleet.set_config(config);
|
||
this.fireEvent('configupdated', config);
|
||
},
|
||
|
||
onOk: function() {
|
||
this.onApply();
|
||
},
|
||
|
||
updateConfig: function() {
|
||
deluge.client.ppsfleet.get_config({
|
||
success: function(config) {
|
||
if (this.files_root_dir) {
|
||
this.files_root_dir.setValue(config['files_root_dir']);
|
||
this.files_base_url.setValue(config['files_base_url']);
|
||
}
|
||
this.fireEvent('configupdated', config);
|
||
},
|
||
scope: this,
|
||
});
|
||
},
|
||
});
|
||
|
||
Deluge.plugins.PPSFleetPlugin = Ext.extend(Deluge.Plugin, {
|
||
name: 'PPSFleet',
|
||
|
||
static: {
|
||
prefsPage: null,
|
||
},
|
||
|
||
onDisable: function() {
|
||
deluge.preferences.removePage(Deluge.plugins.PPSFleetPlugin.prefsPage);
|
||
deluge.menus.filePriorities.remove(this.menuSep);
|
||
deluge.menus.filePriorities.remove(this.getFileItem);
|
||
deluge.menus.filePriorities.remove(this.copyLinkItem);
|
||
this.selModel.un('selectionchange', this.onFilesTabSelectionChange);
|
||
},
|
||
|
||
onEnable: function() {
|
||
if (!Deluge.plugins.PPSFleetPlugin.prefsPage) {
|
||
Deluge.plugins.PPSFleetPlugin.prefsPage = deluge.preferences.addPage(
|
||
new Deluge.ux.preferences.PPSFleetPage());
|
||
}
|
||
|
||
this.config = {};
|
||
Deluge.plugins.PPSFleetPlugin.prefsPage.on('configupdated', this.configUpdated, this);
|
||
|
||
this.menuSep = deluge.menus.filePriorities.add({
|
||
xtype: 'menuseparator'
|
||
});
|
||
|
||
this.getFileItem = deluge.menus.filePriorities.addMenuItem({
|
||
text: _('Get file'),
|
||
handler: this.onGetFileClick,
|
||
scope: this,
|
||
});
|
||
|
||
this.copyLinkItem = deluge.menus.filePriorities.addMenuItem({
|
||
text: _('Copy link'),
|
||
handler: this.onCopyLinkClick,
|
||
scope: this,
|
||
});
|
||
|
||
this.fileUrl = undefined;
|
||
|
||
let filesTab = deluge.details.items.items.filter(e => e instanceof Deluge.details.FilesTab)[0];
|
||
this.selModel = filesTab.getSelectionModel();
|
||
this.selModel.on('selectionchange', this.onFilesTabSelectionChange, this);
|
||
deluge.ui.MainPanel.el.dom.addEventListener('dragover', this.onDragOver);
|
||
deluge.ui.MainPanel.el.dom.addEventListener('drop', this.onDrop);
|
||
},
|
||
|
||
onFilesTabSelectionChange: function(selModel, e) {
|
||
let nodes = selModel.getSelectedNodes();
|
||
this.getFileItem.disable();
|
||
this.copyLinkItem.disable();
|
||
|
||
if (!this.config['files_root_dir'] || !this.config['files_base_url']) {
|
||
return
|
||
}
|
||
|
||
// Node is file and has finished downloading
|
||
if (nodes.length == 1 && nodes[0].isLeaf() && nodes[0].attributes.progress === 1) {
|
||
let selectedTorrent = deluge.torrents.getSelected();
|
||
let location = selectedTorrent.data.download_location;
|
||
if (location.startsWith(this.config['files_root_dir'])) {
|
||
let file_dir = location.substr(this.config['files_root_dir'].length);
|
||
let file_path = [];
|
||
let node = nodes[0];
|
||
while ('filename' in node.attributes) {
|
||
file_path.unshift(node.attributes.filename);
|
||
node = node.parentNode;
|
||
}
|
||
let path = '/' + file_dir + '/' + file_path.join('/');
|
||
this.fileUrl = this.config['files_base_url'].replace(/\/$/, '') + encodeURI(path.replace(/\/\/+/, '/'));
|
||
this.getFileItem.enable();
|
||
this.copyLinkItem.enable();
|
||
}
|
||
}
|
||
},
|
||
|
||
onGetFileClick: function(item, e) {
|
||
// not proud of that but the framework used is bad and prevent default action on click
|
||
let a = document.createElement("a")
|
||
a.style.display = "none";
|
||
a.href = this.fileUrl;
|
||
a.setAttribute("download", "");
|
||
document.body.appendChild(a);
|
||
a.click();
|
||
a.remove();
|
||
},
|
||
|
||
onCopyLinkClick: function(item, e) {
|
||
navigator.clipboard.writeText(this.fileUrl).then(function () {
|
||
console.log('Link copied')
|
||
});
|
||
},
|
||
|
||
onDrop: function(e) {
|
||
e.preventDefault();
|
||
let files = [];
|
||
|
||
// https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop
|
||
if (e.dataTransfer.items) {
|
||
for (var i = 0; i < e.dataTransfer.items.length; i++) {
|
||
if (e.dataTransfer.items[i].kind === 'file') {
|
||
files.push(e.dataTransfer.items[i].getAsFile());
|
||
}
|
||
}
|
||
} else {
|
||
for (var i = 0; i < e.dataTransfer.files.length; i++) {
|
||
files.push(file);
|
||
}
|
||
}
|
||
|
||
let options = {
|
||
'add_paused': true
|
||
};
|
||
|
||
let promises = files.filter(f => f.type === 'application/x-bittorrent')
|
||
.map(f => {
|
||
let fileName = f.name;
|
||
return new Promise((resolve, reject) => {
|
||
let reader = new FileReader();
|
||
reader.readAsDataURL(f);
|
||
reader.onload = () => {
|
||
let encodedFile = reader.result.toString().replace(/^data:(.*,)?/, '');
|
||
resolve([fileName, encodedFile, options]);
|
||
};
|
||
reader.onerror = error => reject(error);
|
||
})
|
||
});
|
||
|
||
Promise.all(promises).then(torrentsData => {
|
||
deluge.client.core.add_torrent_files(torrentsData, {
|
||
success: function(res) {
|
||
console.log('success', res);
|
||
},
|
||
scope: this,
|
||
});
|
||
});
|
||
},
|
||
|
||
onDragOver: function(e) {
|
||
e.preventDefault();
|
||
},
|
||
|
||
configUpdated: function(config) {
|
||
this.config = config;
|
||
}
|
||
});
|
||
|
||
Deluge.registerPlugin('PPSFleet', Deluge.plugins.PPSFleetPlugin);
|